Tidy ups for quickprint:

- let the quickprint be based on either qgsmapcanvas or qgsmaprender
 - word wrapping for legend entries
 - added setMapBackgroundColor to public api


git-svn-id: http://svn.osgeo.org/qgis/trunk@8013 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
timlinux 2008-01-21 13:08:29 +00:00
parent 0cef849bc7
commit 89e2a97e68
2 changed files with 138 additions and 80 deletions

View File

@ -95,7 +95,16 @@ void QgsQuickPrint::setOutputPdf(QString theFileName)
} }
void QgsQuickPrint::setMapCanvas(QgsMapCanvas * thepMapCanvas) void QgsQuickPrint::setMapCanvas(QgsMapCanvas * thepMapCanvas)
{ {
mpMapCanvas=thepMapCanvas; mpMapRender=thepMapCanvas->mapRender();
mMapBackgroundColour = thepMapCanvas->canvasColor();
}
void QgsQuickPrint::setMapRender(QgsMapRender * thepMapRender)
{
mpMapRender=thepMapRender;
}
void QgsQuickPrint::setMapBackgroundColor(QColor theColor)
{
mMapBackgroundColour = theColor;
} }
void QgsQuickPrint::printMap() void QgsQuickPrint::printMap()
@ -104,7 +113,7 @@ void QgsQuickPrint::printMap()
{ {
return; return;
} }
if ( mpMapCanvas == NULL ) if ( mpMapRender == NULL )
{ {
return; return;
} }
@ -222,7 +231,6 @@ void QgsQuickPrint::printMap()
// Background colour for pixmaps // Background colour for pixmaps
QColor myLegendBackgroundColour = Qt::white; QColor myLegendBackgroundColour = Qt::white;
QColor myMapBackgroundColour = mpMapCanvas->canvasColor();
//QColor myMapBackgroundColour = "#98dbf9"; // nice blue colour //QColor myMapBackgroundColour = "#98dbf9"; // nice blue colour
@ -314,20 +322,20 @@ void QgsQuickPrint::printMap()
int myMapDimensionX = (myDrawableWidth / 100) * myMapHeightPercent; int myMapDimensionX = (myDrawableWidth / 100) * myMapHeightPercent;
int myMapDimensionY = (myDrawableHeight / 100) * myMapWidthPercent; int myMapDimensionY = (myDrawableHeight / 100) * myMapWidthPercent;
QPixmap myMapPixmap ( myMapDimensionX,myMapDimensionY ); QPixmap myMapPixmap ( myMapDimensionX,myMapDimensionY );
myMapPixmap.fill ( myMapBackgroundColour ); myMapPixmap.fill ( mMapBackgroundColour );
QPainter myMapPainter; QPainter myMapPainter;
myMapPainter.begin( &myMapPixmap ); myMapPainter.begin( &myMapPixmap );
mpMapCanvas->mapRender()->setOutputSize( mpMapRender->setOutputSize(
QSize ( myMapDimensionX, myMapDimensionY ), myPrinter.resolution() ); QSize ( myMapDimensionX, myMapDimensionY ), myPrinter.resolution() );
scalePointSymbols(mySymbolScalingAmount, ScaleUp); scalePointSymbols(mySymbolScalingAmount, ScaleUp);
scaleTextLabels(mySymbolScalingAmount, ScaleUp); scaleTextLabels(mySymbolScalingAmount, ScaleUp);
mpMapCanvas->mapRender()->render( &myMapPainter ); mpMapRender->render( &myMapPainter );
//maprender has no accessor for output size so //maprender has no accessor for output size so
//we couldnt store the size before starting the print render //we couldnt store the size before starting the print render
//so that it can be restored properly so what follows here is a //so that it can be restored properly so what follows here is a
//best guess approach //best guess approach
mpMapCanvas->mapRender()->setOutputSize( mpMapRender->setOutputSize(
QSize ( mpMapCanvas->width(), mpMapCanvas->height() ), myScreenResolutionDpi ); QSize ( mpMapRender->width(), mpMapRender->height() ), myScreenResolutionDpi );
myMapPainter.end(); myMapPainter.end();
//draw the map pixmap onto our pdf print device //draw the map pixmap onto our pdf print device
myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing; myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing;
@ -344,6 +352,8 @@ void QgsQuickPrint::printMap()
//myPrintPainter.setFont(myLegendFont); //myPrintPainter.setFont(myLegendFont);
int myLegendDimensionX = (myDrawableWidth / 100) * myLegendWidthPercent; int myLegendDimensionX = (myDrawableWidth / 100) * myLegendWidthPercent;
int myLegendDimensionY = (myDrawableHeight / 100) * myLegendHeightPercent; int myLegendDimensionY = (myDrawableHeight / 100) * myLegendHeightPercent;
// Create a viewport to make coordinate conversions easier // Create a viewport to make coordinate conversions easier
// The viewport has the same dimensions as the page(otherwise items // The viewport has the same dimensions as the page(otherwise items
// drawn into it will appear squashed), but a different origin. // drawn into it will appear squashed), but a different origin.
@ -353,15 +363,22 @@ void QgsQuickPrint::printMap()
myOriginY, myOriginY,
myOriginalViewport.width(), myOriginalViewport.width(),
myOriginalViewport.height()); myOriginalViewport.height());
//draw a rectangale around the legend frame
//@TODO make this user settable
if (0==1) //put some real logic here
{
myPrintPainter.drawRect( 0, 0, myLegendDimensionX, myLegendDimensionY );
}
//get font metric and other vars needed
QFontMetrics myLegendFontMetrics( myLegendFont, &myPrinter ); QFontMetrics myLegendFontMetrics( myLegendFont, &myPrinter );
int myLegendFontHeight = myLegendFontMetrics.height(); int myLegendFontHeight = myLegendFontMetrics.height();
int myLegendXPos = 0; int myLegendXPos = 0;
int myLegendYPos = 0; int myLegendYPos = 0;
int myLegendSpacer = myLegendFontHeight; //for vertical and horizontal spacing int myLegendSpacer = myLegendFontHeight/2; //for vertical and horizontal spacing
int myLegendVerticalSpacer = myLegendFontHeight/3; //for vertical between rows int myLegendVerticalSpacer = myLegendFontHeight/3; //for vertical between rows
int myIconWidth = myLegendFontHeight; int myIconWidth = myLegendFontHeight;
myPrintPainter.setFont( myLegendFont ); myPrintPainter.setFont( myLegendFont );
QStringList myLayerSet = mpMapCanvas->mapRender()->layerSet(); QStringList myLayerSet = mpMapRender->layerSet();
QStringListIterator myLayerIterator ( myLayerSet ); QStringListIterator myLayerIterator ( myLayerSet );
while ( myLayerIterator.hasNext() ) while ( myLayerIterator.hasNext() )
{ {
@ -389,7 +406,7 @@ void QgsQuickPrint::printMap()
QgsSymbol * mypSymbol = mySymbolList.at(0); QgsSymbol * mypSymbol = mySymbolList.at(0);
myPrintPainter.setPen( mypSymbol->pen() ); myPrintPainter.setPen( mypSymbol->pen() );
myPrintPainter.setBrush( mypSymbol->brush() ); myPrintPainter.setBrush( mypSymbol->brush() );
myLegendXPos = myLegendSpacer; myLegendXPos = 0 ;
if ( mypSymbol->type() == QGis::Point ) if ( mypSymbol->type() == QGis::Point )
{ {
QImage myImage; QImage myImage;
@ -410,46 +427,50 @@ void QgsQuickPrint::printMap()
} }
myLegendXPos += myIconWidth + myLegendSpacer; myLegendXPos += myIconWidth + myLegendSpacer;
myPrintPainter.setPen( Qt::black ); myPrintPainter.setPen( Qt::black );
// check if the text will overflow the space we have
int myMaximumLabelWidth = myLegendDimensionX - myLegendXPos; int myMaximumLabelWidth = myLegendDimensionX - myLegendXPos;
if (myLayerNameWidth > myMaximumLabelWidth) QStringList myWrappedLayerNameList = wordWrap(myLayerName,
myLegendFontMetrics,
myLegendDimensionX - myIconWidth);
//
// Loop through wrapped legend label lines
//
QStringListIterator myLineWrapIterator(myWrappedLayerNameList);
while (myLineWrapIterator.hasNext())
{ {
int myRowCount = (myLayerNameWidth / myMaximumLabelWidth) + 1; QString myLine = myLineWrapIterator.next();
QRect myLegendItemRect (myLegendXPos, QRect myLegendItemRect (myLegendXPos,
myLegendYPos, myLegendYPos,
myLayerNameWidth, myLegendDimensionX - myIconWidth,
myLegendFontHeight * myRowCount);
QTextOption myTextOption( Qt::AlignCenter );
myTextOption.setWrapMode (
QTextOption::WrapAtWordBoundaryOrAnywhere );
myPrintPainter.drawText(
myLegendItemRect,
myLayerName,
myTextOption
);
myLegendYPos += myLegendVerticalSpacer + (myLegendFontHeight * myRowCount);
}
else //fits ok on a single line
{
QRect myLegendItemRect (myLegendXPos,
myLegendYPos,
myLayerNameWidth,
myLegendFontHeight); myLegendFontHeight);
myPrintPainter.drawText( myLegendItemRect, Qt::AlignCenter, myLayerName ); myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
} }
} }
else //class breaks else //class breaks
{ {
// draw in the layer name first, after we loop for the class breaks // draw in the layer name first, after we loop for the class breaks
myLegendXPos = myIconWidth + myLegendSpacer; QStringList myWrappedLayerNameList = wordWrap(myLayerName,
QRect myLegendItemRect (myLegendXPos, myLegendFontMetrics,
myLegendYPos, myLegendDimensionX - myIconWidth);
myLayerNameWidth, //
myLegendFontHeight); // Loop through wrapped legend label lines
myPrintPainter.setPen( Qt::black ); //
myPrintPainter.drawText( myLegendItemRect, Qt::AlignCenter, myLayerName ); QStringListIterator myLineWrapIterator(myWrappedLayerNameList);
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; while (myLineWrapIterator.hasNext())
{
QString myLine = myLineWrapIterator.next();
myLegendXPos = myIconWidth;
QRect myLegendItemRect (myLegendXPos,
myLegendYPos,
myLegendFontMetrics.width(myLine),
myLegendFontHeight);
myPrintPainter.setPen( Qt::black );
myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
}
//
// Lop through the class breaks
//
QListIterator<QgsSymbol *> myIterator ( mySymbolList ); QListIterator<QgsSymbol *> myIterator ( mySymbolList );
while ( myIterator.hasNext() ) while ( myIterator.hasNext() )
{ {
@ -500,41 +521,26 @@ void QgsQuickPrint::printMap()
myLegendXPos += myIconWidth + myLegendSpacer; myLegendXPos += myIconWidth + myLegendSpacer;
int myLabelWidth = myLegendFontMetrics.width(myLabel); int myLabelWidth = myLegendFontMetrics.width(myLabel);
myPrintPainter.setPen( Qt::black ); myPrintPainter.setPen( Qt::black );
// check if the text will overflow the space we have //
int myMaximumLabelWidth = myLegendDimensionX - myLegendXPos;
if (myLabelWidth > myMaximumLabelWidth) QStringList myWrappedLayerNameList = wordWrap(myLabel,
myLegendFontMetrics,
myLegendDimensionX - myIconWidth);
//
// Loop through wrapped legend label lines
//
QStringListIterator myLineWrapIterator(myWrappedLayerNameList);
while (myLineWrapIterator.hasNext())
{ {
int myRowCount = (myLabelWidth / myMaximumLabelWidth) + 1; QString myLine = myLineWrapIterator.next();
// check if the text will overflow the space we have
QRect myLegendItemRect (myLegendXPos, QRect myLegendItemRect (myLegendXPos,
myLegendYPos, myLegendYPos,
myLabelWidth, myLegendDimensionX - myIconWidth,
myLegendFontHeight * myRowCount);
QTextOption myTextOption( Qt::AlignLeft );
myTextOption.setWrapMode (
QTextOption::WordWrap);
//QTextOption::WrapAtWordBoundaryOrAnywhere );
myPrintPainter.drawText(
myLegendItemRect,
myLabel,
myTextOption
);
/*
myPrintPainter.drawText( myLegendItemRect,
Qt::AlignLeft | Qt::TextWordWrap,
myLabel );
myPrintPainter.drawRect( myLegendItemRect ),
*/
myLegendYPos += myLegendVerticalSpacer + (myLegendFontHeight * myRowCount);
}
else //fits ok on a single line
{
QRect myLegendItemRect (myLegendXPos,
myLegendYPos,
myLabelWidth,
myLegendFontHeight); myLegendFontHeight);
myPrintPainter.drawText( myLegendItemRect, Qt::AlignCenter, myLabel ); myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine );
myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight;
} } //wordwrap loop
} //symbol loop } //symbol loop
} //class breaks } //class breaks
} //if vectorlayer } //if vectorlayer
@ -615,7 +621,7 @@ void QgsQuickPrint::printMap()
// //
// Draw the scale bar // Draw the scale bar
// //
renderPrintScaleBar(&myPrintPainter, mpMapCanvas, myLogoXDim); renderPrintScaleBar(&myPrintPainter, mpMapRender, myLogoXDim);
// //
// Finish up // Finish up
@ -643,7 +649,7 @@ void QgsQuickPrint::scaleTextLabels( int theScaleFactor, SymbolScalingType theDi
QgsDebugMsg ("QgsQuickPrintGui::scaleTextLabels invalid scale factor"); QgsDebugMsg ("QgsQuickPrintGui::scaleTextLabels invalid scale factor");
return; return;
} }
QStringList myLayerSet = mpMapCanvas->mapRender()->layerSet(); QStringList myLayerSet = mpMapRender->layerSet();
QStringListIterator myLayerIterator ( myLayerSet ); QStringListIterator myLayerIterator ( myLayerSet );
while ( myLayerIterator.hasNext() ) while ( myLayerIterator.hasNext() )
{ {
@ -683,7 +689,7 @@ void QgsQuickPrint::scalePointSymbols( int theScaleFactor, SymbolScalingType the
QgsDebugMsg ("QgsQuickPrintGui::scalePointSymbolsForPrint invalid scale factor"); QgsDebugMsg ("QgsQuickPrintGui::scalePointSymbolsForPrint invalid scale factor");
return; return;
} }
QStringList myLayerSet = mpMapCanvas->mapRender()->layerSet(); QStringList myLayerSet = mpMapRender->layerSet();
QStringListIterator myLayerIterator ( myLayerSet ); QStringListIterator myLayerIterator ( myLayerSet );
while ( myLayerIterator.hasNext() ) while ( myLayerIterator.hasNext() )
{ {
@ -744,7 +750,7 @@ void QgsQuickPrint::scalePointSymbols( int theScaleFactor, SymbolScalingType the
void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter, void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter,
QgsMapCanvas * thepMapCanvas, QgsMapRender * thepMapRender,
int theMaximumWidth) int theMaximumWidth)
{ {
//hard coding some options for now //hard coding some options for now
@ -758,7 +764,7 @@ void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter,
int myTextOffsetY=30; int myTextOffsetY=30;
int myXMargin=260; int myXMargin=260;
int myYMargin=180; int myYMargin=180;
int myCanvasWidth = thepMapCanvas->width(); int myCanvasWidth = thepMapRender->width();
int myPreferredSize = theMaximumWidth; int myPreferredSize = theMaximumWidth;
double myActualSize=myPreferredSize; double myActualSize=myPreferredSize;
int myBufferSize=1; //softcode this later int myBufferSize=1; //softcode this later
@ -771,10 +777,10 @@ void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter,
//Get map units per pixel. This can be negative at times (to do with //Get map units per pixel. This can be negative at times (to do with
//projections) and that just confuses the rest of the code in this //projections) and that just confuses the rest of the code in this
//function, so force to a positive number. //function, so force to a positive number.
double myMuppDouble = std::abs(thepMapCanvas->mupp()); double myMuppDouble = std::abs(thepMapRender->mupp());
// Exit if the canvas width is 0 or layercount is 0 or QGIS will freeze // Exit if the canvas width is 0 or layercount is 0 or QGIS will freeze
int myLayerCount=thepMapCanvas->layerCount(); int myLayerCount=thepMapRender->layerSet().count();
if (!myLayerCount || !myMuppDouble) return; if (!myLayerCount || !myMuppDouble) return;
@ -803,7 +809,7 @@ void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter,
} }
//Get type of map units and set scale bar unit label text //Get type of map units and set scale bar unit label text
QGis::units myMapUnits=thepMapCanvas->mapUnits(); QGis::units myMapUnits=thepMapRender->mapUnits();
QString myScaleBarUnitLabel; QString myScaleBarUnitLabel;
switch (myMapUnits) switch (myMapUnits)
{ {
@ -1104,3 +1110,46 @@ void QgsQuickPrint::renderPrintScaleBar(QPainter * thepPainter,
myScaleBarUnitLabel myScaleBarUnitLabel
); );
} }
QStringList QgsQuickPrint::wordWrap(QString theString,
QFontMetrics theMetrics,
int theWidth)
{
//iterate the string
QStringList myList;
QString myCumulativeLine="";
QString myStringToPreviousSpace="";
int myPreviousSpacePos=0;
for (int i=0; i < theString.count(); ++i)
{
QChar myChar = theString.at(i);
if (myChar == QChar(' '))
{
myStringToPreviousSpace = myCumulativeLine;
myPreviousSpacePos=i;
}
myCumulativeLine += myChar;
if (theMetrics.width(myCumulativeLine) >= theWidth)
{
//time to wrap
//@todo deal with long strings that have no spaces
//forcing a break at current pos...
myList << myStringToPreviousSpace.trimmed();
i = myPreviousSpacePos;
myStringToPreviousSpace = "";
myCumulativeLine = "";
}
}//end of i loop
//add whatever is left in the string to the list
if (!myCumulativeLine.trimmed().isEmpty())
{
myList << myCumulativeLine.trimmed();
}
//qDebug("Wrapped legend entry:");
//qDebug(theString);
//qDebug(myList.join("\n").toLocal8Bit());
return myList;
}

View File

@ -21,6 +21,7 @@
//QT4 includes //QT4 includes
#include <QObject> #include <QObject>
#include <QColor>
//QGIS includes //QGIS includes
#include <qgsmaprender.h> #include <qgsmaprender.h>
@ -51,11 +52,18 @@ public slots:
void setLogo1(QString theFileName); void setLogo1(QString theFileName);
void setLogo2(QString theFileName); void setLogo2(QString theFileName);
void setOutputPdf(QString theFileName); void setOutputPdf(QString theFileName);
//! This is just a convenience function to get the
//map render from the mapcanvas
void setMapCanvas(QgsMapCanvas * thepMapCanvas); void setMapCanvas(QgsMapCanvas * thepMapCanvas);
void setMapRender(QgsMapRender * thepMapRender);
void setMapBackgroundColor(QColor theColor);
private: private:
void renderPrintScaleBar(QPainter * thepPainter, void renderPrintScaleBar(QPainter * thepPainter,
QgsMapCanvas * thepMapCanvas, QgsMapRender * thepMapRender,
int theMaximumWidth); int theMaximumWidth);
QStringList wordWrap(QString theString,
QFontMetrics theMetrics,
int theWidth);
/** /**
* Scale symbols in all layers by the specified amount. * Scale symbols in all layers by the specified amount.
* Typically used for printing. Each symbol in * Typically used for printing. Each symbol in
@ -89,7 +97,7 @@ private:
*/ */
void scaleTextLabels( int theScaleFactor, SymbolScalingType theDirection); void scaleTextLabels( int theScaleFactor, SymbolScalingType theDirection);
QgsMapCanvas * mpMapCanvas; QgsMapRender * mpMapRender;
QString mTitleText; QString mTitleText;
QString mNameText; QString mNameText;
QString mCopyrightText; QString mCopyrightText;
@ -97,6 +105,7 @@ private:
QString mLogo1File; QString mLogo1File;
QString mLogo2File; QString mLogo2File;
QString mOutputFileName; QString mOutputFileName;
QColor mMapBackgroundColour;
}; };
#endif //QGSQUICKPRINT_H #endif //QGSQUICKPRINT_H