1
/***************************************************************************
3
A class to quickly print a map with minimal effort.
6
copyright : (c) Tim Sutton, 2008
7
email : tim@linfiniti.com
9
***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
17
/* $Id: plugin.cpp 7796 2007-12-16 22:11:38Z homann $ */
20
// QGIS Specific includes
23
#include <qgisinterface.h>
25
#include "qgsquickprint.h"
26
#include <qgsapplication.h>
27
#include <qgsmaplayerregistry.h>
28
#include <qgsvectorlayer.h>
29
#include <qgssymbol.h>
30
#include <qgsmapcanvas.h>
31
#include <qgsrenderer.h>
32
#include <qgslogger.h>
33
#include <qgslabelattributes.h>
37
// Qt4 Related Includes
48
#include <QSvgRenderer>
49
#include <QLinearGradient>
55
#define round(x) ((x) >= 0 ? floor((x)+0.5) : floor((x)-0.5))
58
QgsQuickPrint::QgsQuickPrint()
60
mPageSize = QPrinter::A4;
63
QgsQuickPrint::~QgsQuickPrint()
67
void QgsQuickPrint::setTitle( QString theText )
71
void QgsQuickPrint::setName( QString theText )
75
void QgsQuickPrint::setCopyright( QString theText )
77
mCopyrightText = theText;
79
void QgsQuickPrint::setNorthArrow( QString theFileName )
81
mNorthArrowFile = theFileName;
83
void QgsQuickPrint::setLogo1( QString theFileName )
85
mLogo1File = theFileName;
86
QgsDebugMsg( QString( "Logo1 set to: %1" ).arg( mLogo1File ) );
88
void QgsQuickPrint::setLogo2( QString theFileName )
90
mLogo2File = theFileName;
91
QgsDebugMsg( QString( "Logo2 set to: %1" ).arg( mLogo2File ) );
93
void QgsQuickPrint::setOutputPdf( QString theFileName )
95
mOutputFileName = theFileName;
97
void QgsQuickPrint::setMapCanvas( QgsMapCanvas * thepMapCanvas )
99
mpMapRenderer = thepMapCanvas->mapRenderer();
100
mMapBackgroundColor = thepMapCanvas->canvasColor();
102
void QgsQuickPrint::setMapRenderer( QgsMapRenderer * thepMapRenderer )
104
mpMapRenderer = thepMapRenderer;
106
void QgsQuickPrint::setMapBackgroundColor( QColor theColor )
108
mMapBackgroundColor = theColor;
110
void QgsQuickPrint::setPageSize( QPrinter::PageSize theSize )
115
void QgsQuickPrint::printMap()
117
if ( mOutputFileName.isEmpty() )
121
if ( mpMapRenderer == NULL )
125
//ensure the user never omitted the extension from the file name
126
if ( !mOutputFileName.toUpper().endsWith( ".PDF" ) )
128
mOutputFileName += ".pdf";
131
// Initialising the printer this way lets us find out what
132
// the screen resolution is which we store and then
133
// reset the resolution of the printer after that...
134
QPrinter myPrinter( QPrinter::ScreenResolution );
136
// Try to force the printer resolution to 300dpi
137
// to get past platform specific defaults in printer
140
int myPrintResolutionDpi = 300;
141
myPrinter.setResolution( myPrintResolutionDpi );
142
myPrinter.setOutputFormat( QPrinter::PdfFormat );
143
QgsDebugMsg( QString( "Printing to page size %1" ).arg( pageSizeToString( mPageSize ) ) );
144
myPrinter.setPageSize( mPageSize );
145
myPrinter.setOutputFileName( mOutputFileName );
146
myPrinter.setOrientation( QPrinter::Landscape );
147
myPrinter.setDocName( "quickprint Report" );
148
QPainter myPrintPainter( &myPrinter );
149
myPrintPainter.setPen( Qt::gray );
150
myPrintPainter.setBrush( Qt::white );
151
// This is what we are aiming for:
153
// +-(1)------ Acme Maps (2) --------------------------------------+
154
// |b 12/01/2007 (3) |
155
// | Earthquakes (4) |
156
// | +--(5)--------------------------------------------------------+ |
158
// | | +-(6)---------------------------------------+ +~(7)~~~~~~+ | |
170
// | | +-------------------------------------------+ +~~~~~~~~~~+ | |
172
// | +-------------------------------------------------------------+ |
174
// | +-(8)-----+ +-(9-)----+ +-(10)----+ /|\ |
175
// | | | |Copyright| | | / | \ |
176
// | | | | 2008 | | | |(11) |
177
// | +---------+ +---------+ +---------+ |
179
// +-----------------------------------------------------------------+
181
// 1) PageBorder 8) Logo1
182
// 2) PageTitle 9) CopyrightText
183
// 3) MapDate 10) Logo2
184
// 4) MapTitle 11) NorthArrow
185
// 5) MapFrame 12) ScaleBar
189
// b HorizontalSpacing
193
// Note: Different operating systems will use different
194
// page resolutions for QPrinter::HighResolution so I'm
195
// working all coordinates out as percentages of page
196
// size so that we can hopefully get comarable print
197
// results on all platforms.
201
// Note #2: Im defining all measurements here as my plan
202
// is to later support templates with different page
203
// layouts and paper sizes etc.
207
//set the top left origin for the print layout
208
int myOriginX = myPrinter.pageRect().left();
209
int myOriginY = myPrinter.pageRect().top();
210
int myDrawableWidth = myPrinter.pageRect().width() - myOriginX;
211
int myDrawableHeight = myPrinter.pageRect().height() - myOriginY;
213
//define the spacing between layout elements
214
int myHorizontalSpacing = myDrawableWidth / 100; // 1%
215
int myVerticalSpacing = myDrawableHeight / 100; // 1%
217
//define the proportions for the page layout
218
int myMapWidthPercent = 65;
219
int myMapHeightPercent = 71;
220
int myLegendWidthPercent = 25;
221
int myLegendHeightPercent = 65;
222
int myLogoWidthPercent = 23;
223
int myLogoHeightPercent = 17;
225
// Remember the size and dpi of the maprender
226
// so we can restore it properly
228
int myOriginalDpi = mpMapRenderer->outputDpi();
229
//sensible default to prevent divide by zero
230
if ( 0 == myOriginalDpi ) myOriginalDpi = 96;
231
QSize myOriginalSize = mpMapRenderer->outputSize();
233
//define the font sizes and family
234
int myMapTitleFontSize = 24;
235
int myMapDateFontSize = 16;
236
int myMapNameFontSize = 32;
237
int myLegendFontSize = 12;
238
#ifdef Q_OS_LINUX//this sucks...
239
myLegendFontSize -= 2;
242
#ifdef WIN32 //this sucks too...
243
myMapTitleFontSize /= 2;
244
myMapDateFontSize /= 2;
245
myMapNameFontSize /= 2;
246
myLegendFontSize /= 2;
248
QString myFontFamily = "Arial";
250
// Background color for pixmaps
251
QColor myLegendBackgroundColor = Qt::white;
252
//QColor myMapBackgroundColor = "#98dbf9"; // nice blue color
256
// Draw the PageBorder
258
myPrintPainter.drawRect(
259
myOriginX, myOriginY, myDrawableWidth, myDrawableHeight );
261
// Draw the PageTitle
263
QFont myTitleFont( myFontFamily, myMapTitleFontSize );
264
myPrintPainter.setFont( myTitleFont );
265
QFontMetrics myTitleMetrics( myTitleFont, &myPrinter );
266
int myPageTitleHeight = myTitleMetrics.height();
267
int myPageTitleWidth = myTitleMetrics.width( mTitleText );
268
myOriginX += myHorizontalSpacing;
269
myOriginY -= ( myPageTitleHeight / 2 );
270
QRect myPageTitleRect( myOriginX,
274
// make sure the title goes onto a white background
275
myPrintPainter.setPen( Qt::white );
276
myPrintPainter.drawRect( myPageTitleRect );
277
myPrintPainter.setPen( Qt::black );
278
myPrintPainter.drawText( myPageTitleRect, Qt::AlignCenter, mTitleText );
283
QFont myDateFont( myFontFamily, myMapDateFontSize );
284
QString myDateText( QDate::currentDate().toString( Qt::LocalDate ) );
285
myPrintPainter.setFont( myDateFont );
286
QFontMetrics myDateMetrics( myDateFont, &myPrinter );
287
int myDateHeight = myDateMetrics.height();
288
//int myDateWidth = myDateMetrics.width(myDateText);
289
myOriginX += myHorizontalSpacing;
290
myOriginY += myPageTitleHeight + myVerticalSpacing ;
291
QRect myDateRect( myOriginX,
293
myPageTitleWidth, //use same width as page title for centering
295
// make sure the title goes onto a white background
296
myPrintPainter.setPen( Qt::white );
297
myPrintPainter.drawRect( myDateRect );
298
myPrintPainter.setPen( Qt::black );
299
myPrintPainter.drawText( myDateRect, Qt::AlignCenter, myDateText );
304
QFont myNameFont( myFontFamily, myMapNameFontSize );
305
myPrintPainter.setFont( myNameFont );
306
QFontMetrics myNameMetrics( myNameFont, &myPrinter );
307
int myNameHeight = myNameMetrics.height();
308
int myNameWidth = myNameMetrics.width( mNameText );
309
myOriginX = myPrinter.pageRect().left() + myDrawableWidth / 2; //page center
310
myOriginX -= myNameWidth / 2;
311
myOriginY = myPrinter.pageRect().top() + ( myPageTitleHeight / 2 ) + myVerticalSpacing ;
312
QRect myNameRect( myOriginX,
316
// make sure the title goes onto a white background
317
myPrintPainter.setPen( Qt::white );
318
myPrintPainter.drawRect( myNameRect );
319
myPrintPainter.setPen( Qt::black );
320
myPrintPainter.drawText( myNameRect, Qt::AlignCenter, mNameText );
323
// Draw the MapFrame (top)
325
int myMapFrameWidth = myDrawableWidth ;
326
myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing;
327
myOriginY += myNameHeight + myVerticalSpacing;
328
QLine myMapFrameTopLine( myOriginX,
332
myPrintPainter.setPen( Qt::black );
333
myPrintPainter.drawLine( myMapFrameTopLine );
336
// Draw the map onto a pixmap
337
// @TODO: we need to save teh extent of the screen map and
338
// then set them again for the print map so that the map scales
339
// properly in the print
340
int myMapDimensionX = ( myDrawableWidth / 100 ) * myMapHeightPercent;
341
int myMapDimensionY = ( myDrawableHeight / 100 ) * myMapWidthPercent;
343
QImage myMapImage( QSize( myMapDimensionX, myMapDimensionY ), QImage::Format_ARGB32 );
344
myMapImage.setDotsPerMeterX(( double )( myPrinter.logicalDpiX() ) / 25.4 * 1000.0 );
345
myMapImage.setDotsPerMeterY(( double )( myPrinter.logicalDpiY() ) / 25.4 * 1000.0 );
346
myMapImage.fill( 0 );
347
QPainter myMapPainter;
348
myMapPainter.begin( &myMapImage );
349
// Now resize for print
350
mpMapRenderer->setOutputSize( QSize( myMapDimensionX, myMapDimensionY ), ( myPrinter.logicalDpiX() + myPrinter.logicalDpiY() ) / 2 );
351
mpMapRenderer->render( &myMapPainter );
354
//draw the map pixmap onto our pdf print device
355
myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing;
356
myOriginY += myVerticalSpacing * 2;
358
myPrintPainter.drawImage( myOriginX, myOriginY, myMapImage );
363
QFont myLegendFont( myFontFamily, myLegendFontSize );
364
//myPrintPainter.setFont(myLegendFont);
365
int myLegendDimensionX = ( myDrawableWidth / 100 ) * myLegendWidthPercent;
366
int myLegendDimensionY = ( myDrawableHeight / 100 ) * myLegendHeightPercent;
369
// Create a viewport to make coordinate conversions easier
370
// The viewport has the same dimensions as the page(otherwise items
371
// drawn into it will appear squashed), but a different origin.
372
QRect myOriginalViewport = myPrintPainter.viewport(); //for restoring later
373
myOriginX += myMapDimensionX + myHorizontalSpacing;
374
myPrintPainter.setViewport( myOriginX,
376
myOriginalViewport.width(),
377
myOriginalViewport.height() );
378
//draw a rectangale around the legend frame
379
//@TODO make this user settable
380
if ( 0 == 1 ) //put some real logic here
382
myPrintPainter.drawRect( 0, 0, myLegendDimensionX, myLegendDimensionY );
384
//get font metric and other vars needed
385
QFontMetrics myLegendFontMetrics( myLegendFont, &myPrinter );
386
int myLegendFontHeight = myLegendFontMetrics.height();
387
int myLegendXPos = 0;
388
int myLegendYPos = 0;
389
int myLegendSpacer = myLegendFontHeight / 2; //for vertical and horizontal spacing
390
int myLegendVerticalSpacer = myLegendFontHeight / 3; //for vertical between rows
391
int myIconWidth = myLegendFontHeight;
392
myPrintPainter.setFont( myLegendFont );
393
QStringList myLayerSet = mpMapRenderer->layerSet();
394
QStringListIterator myLayerIterator( myLayerSet );
395
//second clause below is to prevent legend spilling out the bottom
396
while ( myLayerIterator.hasNext() &&
397
myLegendYPos < myLegendDimensionY )
399
QString myLayerId = myLayerIterator.next();
400
QgsMapLayer * mypLayer =
401
QgsMapLayerRegistry::instance()->mapLayer( myLayerId );
404
QgsVectorLayer *mypVectorLayer =
405
qobject_cast<QgsVectorLayer *>( mypLayer );
406
// TODO: add support for symbology-ng renderers
407
if ( mypVectorLayer && mypVectorLayer->renderer() )
409
QString myLayerName = mypVectorLayer->name();
411
QPixmap myPixmap( QSize( myIconWidth, myIconWidth ) ); //square
412
//based on code from qgslegendlayer.cpp - see that file for more info
413
const QgsRenderer* mypRenderer = mypVectorLayer->renderer();
414
const QList<QgsSymbol*> mySymbolList = mypRenderer->symbols();
418
double widthScale = ( myPrinter.logicalDpiX() + myPrinter.logicalDpiY() ) / 2.0 / 25.4;
420
if ( 1 == mySymbolList.size() )
422
QgsSymbol * mypSymbol = mySymbolList.at( 0 );
423
myPrintPainter.setPen( mypSymbol->pen() );
424
myPrintPainter.setBrush( mypSymbol->brush() );
426
if ( mypSymbol->type() == QGis::Point )
429
myImage = mypSymbol->getPointSymbolAsImage( widthScale );
430
myPrintPainter.drawImage( myLegendXPos, myLegendYPos, myImage );
432
else if ( mypSymbol->type() == QGis::Line )
434
myPrintPainter.drawLine( myLegendXPos, myLegendYPos,
435
myLegendXPos + myIconWidth,
436
myLegendYPos + myIconWidth );
440
myPrintPainter.drawRect( myLegendXPos, myLegendYPos, myIconWidth, myIconWidth );
442
myLegendXPos += myIconWidth + myLegendSpacer;
443
myPrintPainter.setPen( Qt::black );
444
QStringList myWrappedLayerNameList = wordWrap( myLayerName,
446
myLegendDimensionX - myIconWidth );
448
// Loop through wrapped legend label lines
450
QStringListIterator myLineWrapIterator( myWrappedLayerNameList );
451
while ( myLineWrapIterator.hasNext() )
453
QString myLine = myLineWrapIterator.next();
454
QRect myLegendItemRect( myLegendXPos,
456
myLegendDimensionX - myIconWidth,
457
myLegendFontHeight );
458
myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
459
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
464
// draw in the layer name first, after we loop for the class breaks
465
QStringList myWrappedLayerNameList = wordWrap( myLayerName,
467
myLegendDimensionX - myIconWidth );
468
// Check the wrapped layer name wont overrun the space we have
469
// for the legend ...
470
int myLabelHeight = myLegendFontHeight *
471
myWrappedLayerNameList.count();
472
if ( myLegendYPos + myLabelHeight > myLegendDimensionY )
478
// Loop through wrapped legend label lines
480
QStringListIterator myLineWrapIterator( myWrappedLayerNameList );
481
while ( myLineWrapIterator.hasNext() )
483
QString myLine = myLineWrapIterator.next();
484
myLegendXPos = myIconWidth;
485
QRect myLegendItemRect( myLegendXPos,
487
myLegendFontMetrics.width( myLine ),
488
myLegendFontHeight );
489
myPrintPainter.setPen( Qt::black );
490
myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
491
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
494
// Loop through the class breaks
496
QListIterator<QgsSymbol *> myIterator( mySymbolList );
497
while ( myIterator.hasNext() && myLegendYPos < myLegendDimensionY )
499
QgsSymbol * mypSymbol = myIterator.next();
500
myPrintPainter.setPen( mypSymbol->pen() );
501
myPrintPainter.setBrush( mypSymbol->brush() );
502
myLegendXPos = myLegendSpacer * 3; //extra indent for class breaks
503
if ( mypSymbol->type() == QGis::Point )
506
myImage = mypSymbol->getPointSymbolAsImage( widthScale );
507
myPrintPainter.drawImage( myLegendXPos, myLegendYPos, myImage );
509
else if ( mypSymbol->type() == QGis::Line )
511
myPrintPainter.drawLine( myLegendXPos, myLegendYPos,
512
myLegendXPos + myIconWidth,
513
myLegendYPos + myIconWidth );
517
myPrintPainter.drawRect(
518
myLegendXPos, myLegendYPos, myIconWidth, myIconWidth );
521
// Now work out the class break label
524
QString myLower = mypSymbol->lowerValue();
525
if ( !myLower.isEmpty() )
529
QString myUpper = mypSymbol->upperValue();
530
if ( !myUpper.isEmpty() )
535
QString myText = mypSymbol->label();
536
if ( !myText.isEmpty() )
541
myLabel = myLabel.trimmed();
542
myLegendXPos += myIconWidth + myLegendSpacer;
543
myPrintPainter.setPen( Qt::black );
545
QStringList myWrappedLayerNameList = wordWrap( myLabel,
547
myLegendDimensionX - myLegendXPos );
549
// Loop through wrapped legend label lines
551
QStringListIterator myLineWrapIterator( myWrappedLayerNameList );
552
while ( myLineWrapIterator.hasNext() )
554
QString myLine = myLineWrapIterator.next();
555
// check if the text will overflow the space we have
556
QRect myLegendItemRect( myLegendXPos,
558
myLegendDimensionX - myIconWidth,
559
myLegendFontHeight );
560
myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
561
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
569
//reinstate the viewport
570
myPrintPainter.setViewport( myOriginalViewport );
574
// Draw the MapFrame (bottom)
576
myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing;
577
myOriginY += myMapDimensionY + ( myVerticalSpacing * 2 );
578
QLine myMapFrameBottomLine( myOriginX,
582
myPrintPainter.setPen( Qt::black );
583
myPrintPainter.drawLine( myMapFrameBottomLine );
589
int myLogoXDim = ( myDrawableWidth / 100 ) * myLogoWidthPercent;
590
int myLogoYDim = ( myDrawableHeight / 100 ) * myLogoHeightPercent;
592
QgsDebugMsg( QString( "Logo1: %1" ).arg( mLogo1File ) );
593
myLogo1.fill( Qt::white );
594
myLogo1.load( mLogo1File );
595
myLogo1 = myLogo1.scaled( myLogoXDim, myLogoYDim, Qt::KeepAspectRatio );
596
myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing;
597
myOriginY += myVerticalSpacing ;
598
myPrintPainter.drawPixmap( myOriginX,
603
// Draw Copyright Text
605
myOriginX += myHorizontalSpacing + myLogoXDim;
606
QRect myCopyrightRect( myOriginX, myOriginY, myLogoXDim, myLogoYDim );
607
myPrintPainter.setPen( Qt::black );
608
QFont myCopyrightFont( myFontFamily, myMapDateFontSize );
609
myPrintPainter.setFont( myCopyrightFont );
610
//myPrintPainter.drawRect( myCopyrightRect );
611
myPrintPainter.drawText( myCopyrightRect, Qt::AlignCenter | Qt::TextWordWrap, mCopyrightText );
617
myLogo2.fill( Qt::white );
618
myLogo2.load( mLogo2File );
619
myLogo2 = myLogo2.scaled( myLogoXDim, myLogoYDim, Qt::KeepAspectRatio );
620
myOriginX += myHorizontalSpacing + myLogoXDim;
621
myPrintPainter.drawPixmap( myOriginX,
626
// Draw the north arrow
628
myOriginX += myHorizontalSpacing + myLogoXDim;
629
// use half the available space for the n.arrow
630
// and the rest for the scale bar (see below)
631
QPixmap myNorthArrow( myLogoYDim / 2, myLogoYDim / 2 );
632
myNorthArrow.fill( Qt::white );
633
QPainter myNorthPainter( &myNorthArrow );
634
QSvgRenderer mySvgRenderer( mNorthArrowFile );
635
mySvgRenderer.render( &myNorthPainter );
636
myPrintPainter.drawPixmap( myOriginX + (( myLogoXDim / 2 ) ),
641
// Draw the scale bar
643
myOriginY += myLogoYDim / 2 + myVerticalSpacing;
644
myPrintPainter.setViewport( myOriginX,
646
myOriginalViewport.width(),
647
myOriginalViewport.height() );
648
renderPrintScaleBar( &myPrintPainter, mpMapRenderer, myLogoXDim );
649
myPrintPainter.setViewport( myOriginalViewport );
656
myPrintPainter.end();
658
mProgressDialog.setValue( 0 );
659
mProgressDialog.setLabelText( tr( "Please wait while your report is generated", "COMMENTED OUT" ) );
660
mProgressDialog.show();
661
mProgressDialog.setWindowModality( Qt::WindowModal );
662
mProgressDialog.setAutoClose( true );
665
// Restore the map render to its former glory
667
mpMapRenderer->setOutputSize( myOriginalSize, myOriginalDpi );
670
void QgsQuickPrint::scaleTextLabels( int theScaleFactor, SymbolScalingType theDirection )
672
if ( 0 >= theScaleFactor )
674
QgsDebugMsg( "invalid scale factor" );
677
QStringList myLayerSet = mpMapRenderer->layerSet();
678
QStringListIterator myLayerIterator( myLayerSet );
679
while ( myLayerIterator.hasNext() )
681
QString myLayerId = myLayerIterator.next();
682
QgsDebugMsg( "Scaling text labels for print for " + myLayerId );
683
QgsMapLayer * mypLayer =
684
QgsMapLayerRegistry::instance()->mapLayer( myLayerId );
687
QgsVectorLayer *mypVectorLayer =
688
qobject_cast<QgsVectorLayer *>( mypLayer );
689
if ( mypVectorLayer )
691
QgsLabel * mypLabel = mypVectorLayer->label();
692
QgsLabelAttributes * mypLabelAttributes = mypLabel->labelAttributes();
693
if ( theDirection == ScaleUp )
695
mypLabelAttributes->setSize(
696
mypLabelAttributes->size() * theScaleFactor,
697
mypLabelAttributes->sizeType() );
701
mypLabelAttributes->setSize(
702
mypLabelAttributes->size() / theScaleFactor,
703
mypLabelAttributes->sizeType() );
710
void QgsQuickPrint::scalePointSymbols( int theScaleFactor, SymbolScalingType theDirection )
712
if ( 0 >= theScaleFactor )
714
QgsDebugMsg( "invalid scale factor" );
717
QStringList myLayerSet = mpMapRenderer->layerSet();
718
QStringListIterator myLayerIterator( myLayerSet );
719
while ( myLayerIterator.hasNext() )
721
QString myLayerId = myLayerIterator.next();
722
QgsDebugMsg( "Scaling point symbols for print for " + myLayerId );
723
QgsMapLayer * mypLayer =
724
QgsMapLayerRegistry::instance()->mapLayer( myLayerId );
727
QgsVectorLayer *mypVectorLayer =
728
qobject_cast<QgsVectorLayer *>( mypLayer );
729
if ( mypVectorLayer )
731
const QgsRenderer* mypRenderer = mypVectorLayer->renderer();
732
const QList<QgsSymbol*> mySymbolList = mypRenderer->symbols();
736
if ( 1 == mySymbolList.size() )
738
QgsSymbol * mypSymbol = mySymbolList.at( 0 );
739
if ( mypSymbol->type() == QGis::Point )
741
if ( theDirection == ScaleUp )
743
mypSymbol->setPointSize( mypSymbol->pointSize() * theScaleFactor );
747
mypSymbol->setPointSize( mypSymbol->pointSize() / theScaleFactor );
753
QListIterator<QgsSymbol *> myIterator( mySymbolList );
754
while ( myIterator.hasNext() )
756
QgsSymbol * mypSymbol = myIterator.next();
757
if ( mypSymbol->type() == QGis::Point )
759
if ( theDirection == ScaleUp )
761
mypSymbol->setPointSize( mypSymbol->pointSize() * theScaleFactor );
765
mypSymbol->setPointSize( mypSymbol->pointSize() / theScaleFactor );
777
void QgsQuickPrint::renderPrintScaleBar( QPainter * thepPainter,
778
QgsMapRenderer * thepMapRenderer,
779
int theMaximumWidth )
781
//hard coding some options for now
782
bool mySnappingFlag = true;
783
QColor mColor = Qt::black;
785
int myTextOffsetX = 0;
786
int myTextOffsetY = 5;
789
int myPreferredSize = theMaximumWidth - ( myXMargin * 2 );
790
double myActualSize = 0;
791
int myBufferSize = 1; //softcode this later
792
QColor myBackColor = Qt::white; //used for text
793
QColor myForeColor = Qt::black; //used for text
795
//Get canvas dimensions
796
//int myCanvasHeight = thepMapCanvas->height();
798
//Get map units per pixel. This can be negative at times (to do with
799
//projections) and that just confuses the rest of the code in this
800
//function, so force to a positive number.
801
double myMapUnitsPerPixelDouble = std::abs( thepMapRenderer->mapUnitsPerPixel() );
803
// Exit if the canvas width is 0 or layercount is 0 or QGIS will freeze
804
int myLayerCount = thepMapRenderer->layerSet().count();
805
if ( !myLayerCount || !myMapUnitsPerPixelDouble ) return;
807
//Calculate size of scale bar for preferred number of map units
808
double myScaleBarWidth = myPreferredSize;
809
myActualSize = myScaleBarWidth * myMapUnitsPerPixelDouble;
812
// Work out the exponent for the number - e.g, 1234 will give 3,
813
// and .001234 will give -3
814
double myPowerOf10 = floor( log10( myActualSize ) );
816
// snap to integer < 10 times power of 10
817
if ( mySnappingFlag )
819
double scaler = pow( 10.0, myPowerOf10 );
820
myActualSize = round( myActualSize / scaler ) * scaler;
821
myScaleBarWidth = myActualSize / myMapUnitsPerPixelDouble;
824
//Get type of map units and set scale bar unit label text
825
QGis::UnitType myMapUnits = thepMapRenderer->mapUnits();
826
QString myScaleBarUnitLabel;
827
switch ( myMapUnits )
830
if ( myActualSize > 1000.0 )
832
myScaleBarUnitLabel = tr( " km" );
833
myActualSize = myActualSize / 1000;
835
else if ( myActualSize < 0.01 )
837
myScaleBarUnitLabel = tr( " mm" );
838
myActualSize = myActualSize * 1000;
840
else if ( myActualSize < 0.1 )
842
myScaleBarUnitLabel = tr( " cm" );
843
myActualSize = myActualSize * 100;
846
myScaleBarUnitLabel = tr( " m" );
849
if ( myActualSize > 5280.0 ) //5280 feet to the mile
851
myScaleBarUnitLabel = tr( " miles" );
852
myActualSize = myActualSize / 5280;
854
else if ( myActualSize == 5280.0 ) //5280 feet to the mile
856
myScaleBarUnitLabel = tr( " mile" );
857
myActualSize = myActualSize / 5280;
859
else if ( myActualSize < 1 )
861
myScaleBarUnitLabel = tr( " inches" );
862
myActualSize = myActualSize * 12;
864
else if ( myActualSize == 1.0 )
866
myScaleBarUnitLabel = tr( " foot" );
870
myScaleBarUnitLabel = tr( " feet" );
874
if ( myActualSize == 1.0 )
875
myScaleBarUnitLabel = tr( " degree" );
877
myScaleBarUnitLabel = tr( " degrees" );
879
case QGis::UnknownUnit:
880
myScaleBarUnitLabel = tr( " unknown" );
882
QgsDebugMsg( "Error: not picked up map units - actual value = "
883
+ QString::number( myMapUnits ) );
886
//Set font and calculate width of unit label
887
int myFontSize = 10; //we use this later for buffering
888
QFont myFont( "helvetica", myFontSize );
889
thepPainter->setFont( myFont );
890
QFontMetrics myFontMetrics( myFont );
891
double myFontWidth = myFontMetrics.width( myScaleBarUnitLabel );
892
double myFontHeight = myFontMetrics.height();
894
//Set the maximum label
895
QString myScaleBarMaxLabel = QString::number( myActualSize );
897
//Calculate total width of scale bar and label
898
//we divide by 2 because the max scale label
899
//will be centered over the endpoint of the scale bar
900
double myTotalScaleBarWidth = myScaleBarWidth + ( myFontWidth / 2 );
902
//determine the origin of scale bar (bottom right)
903
//for x origin set things up so the scalebar is centered
904
int myOriginX = ( theMaximumWidth - myTotalScaleBarWidth ) / 2;
905
int myOriginY = myYMargin;
907
//Set pen to draw with
908
QPen myForegroundPen( mColor, 2 );
909
QPen myBackgroundPen( Qt::white, 3 );
911
//Cast myScaleBarWidth to int for drawing
912
int myScaleBarWidthInt = ( int ) myScaleBarWidth;
914
//now draw the bar itself in user selected color
915
thepPainter->setPen( myForegroundPen );
916
//make a glossygradient for the background
917
QGradientStops myStops;
918
myStops << QGradientStop( 0.0, QColor( "#616161" ) );
919
myStops << QGradientStop( 0.5, QColor( "#505050" ) );
920
myStops << QGradientStop( 0.6, QColor( "#434343" ) );
921
myStops << QGradientStop( 1.0, QColor( "#656565" ) );
922
//draw again with the brush in the revers direction to complete teh glossiness
923
QLinearGradient myReverseGlossyBrush(
924
QPointF( myOriginX, myOriginY + myFontHeight*3 ),
925
QPointF( myOriginX, myOriginY ) );
926
thepPainter->setBrush( myReverseGlossyBrush );
927
thepPainter->drawRect(
930
myOriginX + myScaleBarWidthInt,
931
myOriginY + myFontHeight
935
//Do drawing of scale bar text
939
//Draw the minimum label buffer
940
thepPainter->setPen( myBackColor );
941
myFontWidth = myFontMetrics.width( "0" );
943
for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
945
for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
947
thepPainter->drawText( int( i + ( myOriginX - ( myFontWidth / 2 ) ) ),
948
int( j + ( myOriginY - ( myFontHeight / 4 ) ) ) - myTextOffsetY,
954
thepPainter->setPen( myForeColor );
956
thepPainter->drawText(
957
int( myOriginX - ( myFontWidth / 2 ) ),
958
int( myOriginY - ( myFontHeight / 4 ) ) - myTextOffsetY,
965
thepPainter->setPen( myBackColor );
966
myFontWidth = myFontMetrics.width( myScaleBarMaxLabel );
967
myFontHeight = myFontMetrics.height();
969
for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
971
for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
973
thepPainter->drawText( int( i + ( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ) ),
974
int( j + ( myOriginY - ( myFontHeight / 4 ) ) ) - myTextOffsetY,
975
myScaleBarMaxLabel );
978
//then the text itself
979
thepPainter->setPen( myForeColor );
980
thepPainter->drawText(
981
int( myOriginX + myScaleBarWidthInt - ( myFontWidth / 2 ) ),
982
int( myOriginY - ( myFontHeight / 4 ) ) - myTextOffsetY,
989
thepPainter->setPen( myBackColor );
990
myFontWidth = myFontMetrics.width( myScaleBarUnitLabel );
992
for ( int i = 0 - myBufferSize; i <= myBufferSize; i++ )
994
for ( int j = 0 - myBufferSize; j <= myBufferSize; j++ )
996
thepPainter->drawText( i + ( myOriginX + myScaleBarWidthInt + myTextOffsetX ),
997
j + myOriginY + myFontHeight + ( myFontHeight*2.5 ) + myTextOffsetY,
998
myScaleBarUnitLabel );
1001
//then the text itself
1002
thepPainter->setPen( myForeColor );
1003
thepPainter->drawText(
1004
myOriginX + myScaleBarWidthInt + myTextOffsetX,
1005
myOriginY + myFontHeight + ( myFontHeight*2.5 ) + myTextOffsetY,
1010
QStringList QgsQuickPrint::wordWrap( QString theString,
1011
QFontMetrics theMetrics,
1014
//iterate the string
1016
QString myCumulativeLine = "";
1017
QString myStringToPreviousSpace = "";
1018
int myPreviousSpacePos = 0;
1019
for ( int i = 0; i < theString.count(); ++i )
1021
QChar myChar = theString.at( i );
1022
if ( myChar == QChar( ' ' ) )
1024
myStringToPreviousSpace = myCumulativeLine;
1025
myPreviousSpacePos = i;
1027
myCumulativeLine += myChar;
1028
if ( theMetrics.width( myCumulativeLine ) >= theWidth )
1031
//@todo deal with long strings that have no spaces
1032
//forcing a break at current pos...
1033
myList << myStringToPreviousSpace.trimmed();
1034
i = myPreviousSpacePos;
1035
myStringToPreviousSpace = "";
1036
myCumulativeLine = "";
1039
//add whatever is left in the string to the list
1040
if ( !myCumulativeLine.trimmed().isEmpty() )
1042
myList << myCumulativeLine.trimmed();
1045
//qDebug("Wrapped legend entry: %s\n%s", theString, myList.join("\n").toLocal8Bit().constData() );
1049
QString QgsQuickPrint::pageSizeToString( QPrinter::PageSize theSize )
1051
if ( theSize == QPrinter::A0 ) return "QPrinter::A0";
1052
if ( theSize == QPrinter::A1 ) return "QPrinter::A1";
1053
if ( theSize == QPrinter::A2 ) return "QPrinter::A2";
1054
if ( theSize == QPrinter::A3 ) return "QPrinter::A3";
1055
if ( theSize == QPrinter::A4 ) return "QPrinter::A4";
1056
if ( theSize == QPrinter::A5 ) return "QPrinter::A5";
1057
if ( theSize == QPrinter::A6 ) return "QPrinter::A6";
1058
if ( theSize == QPrinter::A7 ) return "QPrinter::A7";
1059
if ( theSize == QPrinter::A8 ) return "QPrinter::A8";
1060
if ( theSize == QPrinter::A9 ) return "QPrinter::A9";
1061
if ( theSize == QPrinter::B0 ) return "QPrinter::B0";
1062
if ( theSize == QPrinter::B1 ) return "QPrinter::B1";
1063
if ( theSize == QPrinter::B10 ) return "QPrinter::B10";
1064
if ( theSize == QPrinter::B2 ) return "QPrinter::B2";
1065
if ( theSize == QPrinter::B3 ) return "QPrinter::B3";
1066
if ( theSize == QPrinter::B4 ) return "QPrinter::B4";
1067
if ( theSize == QPrinter::B5 ) return "QPrinter::B5";
1068
if ( theSize == QPrinter::B6 ) return "QPrinter::B6";
1069
if ( theSize == QPrinter::B7 ) return "QPrinter::B7";
1070
if ( theSize == QPrinter::B8 ) return "QPrinter::B8";
1071
if ( theSize == QPrinter::B9 ) return "QPrinter::B9";
1072
if ( theSize == QPrinter::C5E ) return "QPrinter::C5E";
1073
if ( theSize == QPrinter::Comm10E ) return "QPrinter::Comm10E";
1074
if ( theSize == QPrinter::DLE ) return "QPrinter::DLE";
1075
if ( theSize == QPrinter::Executive ) return "QPrinter::Executive";
1076
if ( theSize == QPrinter::Folio ) return "QPrinter::Folio";
1077
if ( theSize == QPrinter::Ledger ) return "QPrinter::Ledger";
1078
if ( theSize == QPrinter::Legal ) return "QPrinter::Legal";
1079
if ( theSize == QPrinter::Letter ) return "QPrinter::Letter";
1081
return "QPrinter::A4";
1085
QPrinter::PageSize QgsQuickPrint::stringToPageSize( QString theSize )
1087
if ( theSize == "QPrinter::A0" ) return QPrinter::A0;
1088
if ( theSize == "QPrinter::A1" ) return QPrinter::A1;
1089
if ( theSize == "QPrinter::A2" ) return QPrinter::A2;
1090
if ( theSize == "QPrinter::A3" ) return QPrinter::A3;
1091
if ( theSize == "QPrinter::A4" ) return QPrinter::A4;
1092
if ( theSize == "QPrinter::A5" ) return QPrinter::A5;
1093
if ( theSize == "QPrinter::A6" ) return QPrinter::A6;
1094
if ( theSize == "QPrinter::A7" ) return QPrinter::A7;
1095
if ( theSize == "QPrinter::A8" ) return QPrinter::A8;
1096
if ( theSize == "QPrinter::A9" ) return QPrinter::A9;
1097
if ( theSize == "QPrinter::B0" ) return QPrinter::B0;
1098
if ( theSize == "QPrinter::B1" ) return QPrinter::B1;
1099
if ( theSize == "QPrinter::B10" ) return QPrinter::B10;
1100
if ( theSize == "QPrinter::B2" ) return QPrinter::B2;
1101
if ( theSize == "QPrinter::B3" ) return QPrinter::B3;
1102
if ( theSize == "QPrinter::B4" ) return QPrinter::B4;
1103
if ( theSize == "QPrinter::B5" ) return QPrinter::B5;
1104
if ( theSize == "QPrinter::B6" ) return QPrinter::B6;
1105
if ( theSize == "QPrinter::B7" ) return QPrinter::B7;
1106
if ( theSize == "QPrinter::B8" ) return QPrinter::B8;
1107
if ( theSize == "QPrinter::B9" ) return QPrinter::B9;
1108
if ( theSize == "QPrinter::C5E" ) return QPrinter::C5E;
1109
if ( theSize == "QPrinter::Comm10E" ) return QPrinter::Comm10E;
1110
if ( theSize == "QPrinter::DLE" ) return QPrinter::DLE;
1111
if ( theSize == "QPrinter::Executive" ) return QPrinter::Executive;
1112
if ( theSize == "QPrinter::Folio" ) return QPrinter::Folio;
1113
if ( theSize == "QPrinter::Ledger" ) return QPrinter::Ledger;
1114
if ( theSize == "QPrinter::Legal" ) return QPrinter::Legal;
1115
if ( theSize == "QPrinter::Letter" ) return QPrinter::Letter;
1117
return QPrinter::A4;