mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
In progress support for retrieval of html composer and items by id from map composition. Also refactoring python composer tests.
This commit is contained in:
parent
014175e534
commit
11dead9a3a
@ -42,6 +42,10 @@ public:
|
||||
/**Removes and deletes all frames from mComposition*/
|
||||
void deleteFrames();
|
||||
|
||||
int nFrames() const;
|
||||
int nFrames() const /Deprecated/;
|
||||
/** Return the number of frames associated with this multiframeset.
|
||||
@note added in 2.0, replaces nFrames
|
||||
**/
|
||||
int frameCount() const;
|
||||
QgsComposerFrame* frame( int i );
|
||||
};
|
||||
|
@ -238,7 +238,7 @@ void QgsComposerMultiFrame::deleteFrames()
|
||||
mResizeMode = bkResizeMode;
|
||||
}
|
||||
|
||||
QgsComposerFrame* QgsComposerMultiFrame::frame( int i )
|
||||
QgsComposerFrame* QgsComposerMultiFrame::frame( int i ) const
|
||||
{
|
||||
if ( i >= mFrameItems.size() )
|
||||
{
|
||||
|
@ -69,8 +69,14 @@ class CORE_EXPORT QgsComposerMultiFrame: public QObject
|
||||
/**Removes and deletes all frames from mComposition*/
|
||||
void deleteFrames();
|
||||
|
||||
int nFrames() const { return mFrameItems.size(); }
|
||||
QgsComposerFrame* frame( int i );
|
||||
|
||||
/** Deprecated in 2.0 use frameCount rather. **/
|
||||
Q_DECL_DEPRECATED int nFrames() const { return mFrameItems.size(); }
|
||||
/** Return the number of frames associated with this multiframeset.
|
||||
@note added in 2.0, replaces nFrames
|
||||
**/
|
||||
int frameCount() const { return mFrameItems.size(); }
|
||||
QgsComposerFrame* frame( int i ) const;
|
||||
|
||||
protected:
|
||||
QgsComposition* mComposition;
|
||||
|
@ -185,8 +185,6 @@ QList<const QgsComposerMap*> QgsComposition::composerMapItems() const
|
||||
|
||||
const QgsComposerMap* QgsComposition::getComposerMapById( int id ) const
|
||||
{
|
||||
QList<const QgsComposerMap*> resultList;
|
||||
|
||||
QList<QGraphicsItem *> itemList = items();
|
||||
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
|
||||
for ( ; itemIt != itemList.end(); ++itemIt )
|
||||
@ -200,7 +198,47 @@ const QgsComposerMap* QgsComposition::getComposerMapById( int id ) const
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QgsComposerHtml* QgsComposition::getComposerHtmlByItem( QgsComposerItem *item ) const
|
||||
{
|
||||
QList<QGraphicsItem *> itemList = items();
|
||||
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
|
||||
for ( ; itemIt != itemList.end(); ++itemIt )
|
||||
{
|
||||
const QgsComposerHtml* composerHtml = dynamic_cast<const QgsComposerHtml *>( *itemIt );
|
||||
if ( composerHtml )
|
||||
{
|
||||
//Now cycle through the items associated with this html composer
|
||||
//and return the composer if the item matches any of them
|
||||
for ( int i=0; i<composerHtml->frameCount(); i++ )
|
||||
{
|
||||
if ( composerHtml->frame(i)->id() == item->id() )
|
||||
{
|
||||
return composerHtml;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QgsComposerItem* QgsComposition::getComposerItemById( QString theId ) const
|
||||
{
|
||||
QList<QGraphicsItem *> itemList = items();
|
||||
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
|
||||
for ( ; itemIt != itemList.end(); ++itemIt )
|
||||
{
|
||||
const QgsComposerItem* mypItem = dynamic_cast<const QgsComposerItem *>( *itemIt );
|
||||
if ( mypItem )
|
||||
{
|
||||
if ( mypItem->id() == theId )
|
||||
{
|
||||
return mypItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1282,7 +1320,7 @@ void QgsComposition::removeComposerItem( QgsComposerItem* item, bool createComma
|
||||
//check if there are frames left. If not, remove the multi frame
|
||||
if ( frameItem && multiFrame )
|
||||
{
|
||||
if ( multiFrame->nFrames() < 1 )
|
||||
if ( multiFrame->frameCount() < 1 )
|
||||
{
|
||||
removeMultiFrame( multiFrame );
|
||||
if ( createCommand )
|
||||
|
@ -124,9 +124,25 @@ class CORE_EXPORT QgsComposition: public QGraphicsScene
|
||||
template<class T> void composerItems( QList<T*>& itemList );
|
||||
|
||||
/**Returns the composer map with specified id
|
||||
@return id or 0 pointer if the composer map item does not exist*/
|
||||
@return QgsComposerMap or 0 pointer if the composer map item does not exist*/
|
||||
const QgsComposerMap* getComposerMapById( int id ) const;
|
||||
|
||||
/*Returns the composer html with specified id (a string as named in the
|
||||
composer user interface item properties).
|
||||
@note Added in QGIS 2.0
|
||||
@param id - A QString representing the id of the item.
|
||||
@return QgsComposerHtml pointer or 0 pointer if no such item exists.
|
||||
*/
|
||||
const QgsComposerHtml* getComposerHtmlByItem( QgsComposerItem *item ) const;
|
||||
|
||||
/**Returns a composer item given its text identifier.
|
||||
@note added in 2.0
|
||||
@param theId - A QString representing the identifier of the item to
|
||||
retrieve.
|
||||
@return QgsComposerItem pointer or 0 pointer if no such item exists.
|
||||
**/
|
||||
const QgsComposerItem* getComposerItemById( QString theId ) const;
|
||||
|
||||
int printResolution() const {return mPrintResolution;}
|
||||
void setPrintResolution( int dpi ) {mPrintResolution = dpi;}
|
||||
|
||||
|
@ -14,7 +14,7 @@ qgscompositionchecker.py - check rendering of Qgscomposition against an expected
|
||||
* *
|
||||
***************************************************************************/
|
||||
'''
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
from qgis.core import *
|
||||
|
||||
@ -22,17 +22,18 @@ class QgsCompositionChecker:
|
||||
|
||||
def testComposition(self, mTestName, mComposition, mExpectedImageFile, page=0 ):
|
||||
if ( mComposition == None):
|
||||
return false
|
||||
myMessage = "Composition not valid"
|
||||
return False, myMessage
|
||||
|
||||
|
||||
#load expected image
|
||||
expectedImage = QImage( mExpectedImageFile )
|
||||
|
||||
|
||||
#get width/height, create image and render the composition to it
|
||||
width = expectedImage.width();
|
||||
height = expectedImage.height();
|
||||
outputImage = QImage( QSize( width, height ), QImage.Format_ARGB32 )
|
||||
|
||||
|
||||
mComposition.setPlotStyle( QgsComposition.Print )
|
||||
outputImage.setDotsPerMeterX( expectedImage.dotsPerMeterX() )
|
||||
outputImage.setDotsPerMeterY( expectedImage.dotsPerMeterX() )
|
||||
@ -40,29 +41,47 @@ class QgsCompositionChecker:
|
||||
p = QPainter( outputImage )
|
||||
mComposition.renderPage( p, page )
|
||||
p.end()
|
||||
|
||||
|
||||
renderedFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_rendered_python.png"
|
||||
outputImage.save( renderedFilePath, "PNG" )
|
||||
|
||||
|
||||
diffFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_diff_python.png"
|
||||
testResult = self.compareImages( expectedImage, outputImage, diffFilePath )
|
||||
|
||||
myDashMessage = "<DartMeasurementFile name=\"Rendered Image " + mTestName + "\"" + " type=\"image/png\">" + renderedFilePath + "</DartMeasurementFile>" + "\n" + "<DartMeasurementFile name=\"Expected Image " + mTestName + "\"" + " type=\"image/png\">" + mExpectedImageFile + "</DartMeasurementFile>" + "\n" + "<DartMeasurementFile name=\"Difference Image " + mTestName + "\"" + " type=\"image/png\">" + diffFilePath + "</DartMeasurementFile>"
|
||||
|
||||
myDashMessage = (('<DartMeasurementFile name="Rendered Image '
|
||||
'%s" type="image/png">'
|
||||
'%s</DartMeasurementFile>'
|
||||
'<DartMeasurementFile name="Expected Image '
|
||||
'%s" type="image/png">'
|
||||
'%s</DartMeasurementFile>\n'
|
||||
'<DartMeasurementFile name="Difference Image '
|
||||
'%s" type="image/png">'
|
||||
'%s</DartMeasurementFile>') %
|
||||
(mTestName, renderedFilePath, mTestName,
|
||||
mExpectedImageFile, mTestName, diffFilePath )
|
||||
)
|
||||
qDebug( myDashMessage )
|
||||
return testResult
|
||||
if not testResult:
|
||||
myMessage = ('Expected: %s\nGot: %s\nDifference: %s\n' %
|
||||
(mExpectedImageFile, renderedFilePath, diffFilePath))
|
||||
else:
|
||||
myMessage = 'Control and test images matched.'
|
||||
return testResult, myMessage
|
||||
|
||||
def compareImages( self, imgExpected, imgRendered, differenceImagePath ):
|
||||
|
||||
if ( imgExpected.width() != imgRendered.width() or imgExpected.height() != imgRendered.height() ):
|
||||
return false
|
||||
|
||||
if ( imgExpected.width() != imgRendered.width()
|
||||
or imgExpected.height() != imgRendered.height() ):
|
||||
return False
|
||||
|
||||
imageWidth = imgExpected.width()
|
||||
imageHeight = imgExpected.height()
|
||||
mismatchCount = 0
|
||||
|
||||
differenceImage = QImage( imageWidth, imageHeight, QImage.Format_ARGB32_Premultiplied )
|
||||
|
||||
differenceImage = QImage(
|
||||
imageWidth, imageHeight, QImage.Format_ARGB32_Premultiplied )
|
||||
differenceImage.fill( qRgb( 152, 219, 249 ) )
|
||||
|
||||
|
||||
pixel1 = QColor().rgb()
|
||||
pixel2 = QColor().rgb()
|
||||
for i in range( imageHeight ):
|
||||
@ -72,13 +91,12 @@ class QgsCompositionChecker:
|
||||
if ( pixel1 != pixel2 ):
|
||||
mismatchCount = mismatchCount + 1
|
||||
differenceImage.setPixel( j, i, qRgb( 255, 0, 0 ) )
|
||||
|
||||
|
||||
if not differenceImagePath.isEmpty():
|
||||
differenceImage.save( differenceImagePath, "PNG" )
|
||||
|
||||
|
||||
#allow pixel deviation of 1 percent
|
||||
pixelCount = imageWidth * imageHeight;
|
||||
# print "MismatchCount: "+str(mismatchCount)
|
||||
# print "PixelCount: "+str(pixelCount)
|
||||
return (float(mismatchCount) / float(pixelCount) ) < 0.01
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
test_qgscomposerhtml.py
|
||||
test_qgscomposerhtml.py
|
||||
--------------------------------------
|
||||
Date : August 2012
|
||||
Copyright : (C) 2012 by Dr. Horst Düster / Dr. Marco Hugentobler
|
||||
Copyright : (C) 2012 by Dr. Horst Düster /
|
||||
Dr. Marco Hugentobler
|
||||
Tim Sutton
|
||||
email : marco@sourcepole.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
@ -13,66 +15,107 @@ test_qgscomposerhtml.py
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
'''
|
||||
'''
|
||||
import unittest
|
||||
from utilities import *
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtGui import *
|
||||
from qgis.core import *
|
||||
import os
|
||||
from utilities import unitTestDataPath, getQgisTestApp
|
||||
from PyQt4.QtCore import QUrl, QString, qDebug
|
||||
from qgis.core import (QgsComposition,
|
||||
QgsComposerHtml,
|
||||
QgsComposerFrame,
|
||||
QgsComposerMultiFrame)
|
||||
|
||||
from qgscompositionchecker import QgsCompositionChecker
|
||||
|
||||
QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
|
||||
class TestQgsComposerMap(unittest.TestCase):
|
||||
|
||||
def testCase(self):
|
||||
self.mComposition = QgsComposition( None )
|
||||
self.mComposition.setPaperSize( 297, 210 ) #A4 landscape
|
||||
self.table()
|
||||
self.tableMultiFrame()
|
||||
|
||||
def table(self):
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
htmlItem = QgsComposerHtml( self.mComposition, False )
|
||||
htmlFrame = QgsComposerFrame( self.mComposition, htmlItem, 0, 0, 100, 200 )
|
||||
htmlFrame.setFrameEnabled( True )
|
||||
htmlItem.addFrame( htmlFrame )
|
||||
htmlItem.setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir.separator() + "html_table.html" ) ) );
|
||||
checker = QgsCompositionChecker( )
|
||||
result = checker.testComposition( "Composer html table", self.mComposition, QString( TEST_DATA_DIR + QDir.separator().toAscii() + "control_images" + QDir.separator().toAscii() + "expected_composerhtml" + QDir.separator().toAscii() + "composerhtml_table.png" ) )
|
||||
self.mComposition.removeMultiFrame( htmlItem )
|
||||
del htmlItem
|
||||
assert result == True
|
||||
|
||||
def tableMultiFrame(self):
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
htmlItem = QgsComposerHtml( self.mComposition, False )
|
||||
htmlFrame = QgsComposerFrame( self.mComposition, htmlItem, 10, 10, 100, 50 )
|
||||
htmlItem.addFrame( htmlFrame )
|
||||
htmlItem.setResizeMode( QgsComposerMultiFrame.RepeatUntilFinished )
|
||||
|
||||
htmlItem.setUrl( QUrl( QString( "file:///%1" ).arg( QString( TEST_DATA_DIR ) + QDir.separator() + "html_table.html" ) ) )
|
||||
htmlItem.frame( 0 ).setFrameEnabled( True )
|
||||
|
||||
|
||||
def setUp(self):
|
||||
"""Run before each test."""
|
||||
self.mComposition = QgsComposition(None)
|
||||
self.mComposition.setPaperSize(297, 210) #A4 landscape
|
||||
self.htmlItem = QgsComposerHtml(self.mComposition, False)
|
||||
|
||||
def tearDown(self):
|
||||
"""Run after each test."""
|
||||
print "Tear down"
|
||||
if self.htmlItem:
|
||||
self.mComposition.removeMultiFrame(self.htmlItem)
|
||||
del self.htmlItem
|
||||
|
||||
def controlImagePath(self, theImageName):
|
||||
"""Helper to get the path to a control image."""
|
||||
myPath = os.path.join(TEST_DATA_DIR,
|
||||
"control_images",
|
||||
"expected_composerhtml",
|
||||
theImageName)
|
||||
assert os.path.exists(myPath)
|
||||
return myPath
|
||||
|
||||
def htmlUrl(self):
|
||||
"""Helper to get the url of the html doc."""
|
||||
myPath = os.path.join(TEST_DATA_DIR, "html_table.html")
|
||||
myUrl = QUrl(QString("file:///%1").arg(myPath))
|
||||
return myUrl
|
||||
|
||||
def testTable(self):
|
||||
"""Test we can render a html table in a single frame."""
|
||||
htmlFrame = QgsComposerFrame(self.mComposition,
|
||||
self.htmlItem, 0, 0, 100, 200)
|
||||
htmlFrame.setFrameEnabled(True)
|
||||
self.htmlItem.addFrame(htmlFrame)
|
||||
self.htmlItem.setUrl(self.htmlUrl())
|
||||
checker = QgsCompositionChecker()
|
||||
myResult, myMessage = checker.testComposition(
|
||||
"Composer html table",
|
||||
self.mComposition,
|
||||
self.controlImagePath("composerhtml_table.png"))
|
||||
qDebug(myMessage)
|
||||
assert myResult, myMessage
|
||||
|
||||
def testTableMultiFrame(self):
|
||||
"""Test we can render to multiframes."""
|
||||
htmlFrame = QgsComposerFrame(self.mComposition, self.htmlItem,
|
||||
10, 10, 100, 50)
|
||||
self.htmlItem.addFrame(htmlFrame)
|
||||
self.htmlItem.setResizeMode(QgsComposerMultiFrame.RepeatUntilFinished)
|
||||
self.htmlItem.setUrl(self.htmlUrl())
|
||||
self.htmlItem.frame(0).setFrameEnabled(True)
|
||||
|
||||
result = True
|
||||
|
||||
#page 1
|
||||
checker1 = QgsCompositionChecker( )
|
||||
if not checker1.testComposition( "Composer html table", self.mComposition, QString( QString( TEST_DATA_DIR ) + QDir.separator() + "control_images" + QDir.separator() + "expected_composerhtml" + QDir.separator() + "composerhtml_table_multiframe1.png" ), 0 ):
|
||||
result = False
|
||||
|
||||
checker2 = QgsCompositionChecker( )
|
||||
if not checker2.testComposition( "Composer html table", self.mComposition, QString( QString( TEST_DATA_DIR ) + QDir.separator() + "control_images" + QDir.separator() + "expected_composerhtml" + QDir.separator() + "composerhtml_table_multiframe2.png" ) , 1 ):
|
||||
result = False
|
||||
|
||||
checker3 = QgsCompositionChecker( )
|
||||
if not checker3.testComposition( "Composer html table", self.mComposition, QString( QString( TEST_DATA_DIR ) + QDir.separator() + "control_images" + QDir.separator() + "expected_composerhtml" + QDir.separator() + "composerhtml_table_multiframe3.png" ), 2 ):
|
||||
result = False
|
||||
|
||||
self.mComposition.removeMultiFrame( htmlItem )
|
||||
del htmlItem
|
||||
|
||||
assert result == True
|
||||
|
||||
myPage = 0
|
||||
checker1 = QgsCompositionChecker()
|
||||
myControlImage = self.controlImagePath(
|
||||
"composerhtml_table_multiframe1.png")
|
||||
print "Checking page 1"
|
||||
myResult, myMessage = checker1.testComposition("Composer html table",
|
||||
self.mComposition,
|
||||
myControlImage,
|
||||
myPage)
|
||||
assert myResult, myMessage
|
||||
|
||||
myPage = 1
|
||||
checker2 = QgsCompositionChecker()
|
||||
myControlImage = self.controlImagePath(
|
||||
"composerhtml_table_multiframe2.png")
|
||||
myResult, myMessage = checker2.testComposition("Composer html table",
|
||||
self.mComposition,
|
||||
myControlImage,
|
||||
myPage)
|
||||
assert myResult, myMessage
|
||||
|
||||
myPage = 2
|
||||
checker3 = QgsCompositionChecker()
|
||||
myControlImage = self.controlImagePath(
|
||||
"composerhtml_table_multiframe3.png")
|
||||
myResult, myMessage = checker3.testComposition("Composer html table",
|
||||
self.mComposition,
|
||||
myControlImage,
|
||||
myPage)
|
||||
assert myResult, myMessage
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user