예제 #1
0
    def draw_legend(self, top_offset):
        """Add a legend to the map using our custom legend renderer.

        .. note:: getLegend generates a pixmap in 150dpi so if you set
           the map to a higher dpi it will appear undersized.

        :param top_offset: Vertical offset at which the logo should be drawn.
        :type top_offset: int
        """
        LOGGER.debug('InaSAFE Map drawLegend called')
        mapLegendAttributes = self.map_legend_attributes()
        legendNotes = mapLegendAttributes.get('legend_notes', None)
        legendUnits = mapLegendAttributes.get('legend_units', None)
        legendTitle = mapLegendAttributes.get('legend_title', None)
        LOGGER.debug(mapLegendAttributes)
        myLegend = MapLegend(self.layer, self.pageDpi, legendTitle,
                             legendNotes, legendUnits)
        self.legend = myLegend.get_legend()
        myPicture1 = QgsComposerPicture(self.composition)
        myLegendFilePath = unique_filename(
            prefix='legend', suffix='.png', dir='work')
        self.legend.save(myLegendFilePath, 'PNG')
        myPicture1.setPictureFile(myLegendFilePath)
        myLegendHeight = points_to_mm(self.legend.height(), self.pageDpi)
        myLegendWidth = points_to_mm(self.legend.width(), self.pageDpi)
        myPicture1.setItemPosition(self.pageMargin,
                                   top_offset,
                                   myLegendWidth,
                                   myLegendHeight)
        myPicture1.setFrameEnabled(False)
        self.composition.addItem(myPicture1)
        os.remove(myLegendFilePath)
예제 #2
0
파일: map.py 프로젝트: feyeandal/inasafe
    def render(self):
        """Render the map composition to an image and save that to disk.

        :returns: A three-tuple of:
            * str: myImagePath - absolute path to png of rendered map
            * QImage: myImage - in memory copy of rendered map
            * QRectF: myTargetArea - dimensions of rendered map
        :rtype: tuple
        """
        LOGGER.debug('InaSAFE Map renderComposition called')
        # NOTE: we ignore self.composition.printAsRaster() and always rasterise
        myWidth = (int)(self.pageDpi * self.pageWidth / 25.4)
        myHeight = (int)(self.pageDpi * self.pageHeight / 25.4)
        myImage = QtGui.QImage(QtCore.QSize(myWidth, myHeight),
                               QtGui.QImage.Format_ARGB32)
        myImage.setDotsPerMeterX(dpi_to_meters(self.pageDpi))
        myImage.setDotsPerMeterY(dpi_to_meters(self.pageDpi))

        # Only works in Qt4.8
        #myImage.fill(QtGui.qRgb(255, 255, 255))
        # Works in older Qt4 versions
        myImage.fill(55 + 255 * 256 + 255 * 256 * 256)
        myImagePainter = QtGui.QPainter(myImage)
        mySourceArea = QtCore.QRectF(0, 0, self.pageWidth, self.pageHeight)
        myTargetArea = QtCore.QRectF(0, 0, myWidth, myHeight)
        self.composition.render(myImagePainter, myTargetArea, mySourceArea)
        myImagePainter.end()
        myImagePath = unique_filename(prefix='mapRender_',
                                      suffix='.png',
                                      dir=temp_dir())
        myImage.save(myImagePath)
        return myImagePath, myImage, myTargetArea
예제 #3
0
 def test_print_to_pdf(self):
     """Test that we can render some html to a pdf (most common use case).
     """
     LOGGER.debug('InaSAFE HtmlRenderer testing printToPdf')
     html = self.sample_html()
     page_dpi = 300
     renderer = HtmlRenderer(page_dpi)
     path = unique_filename(prefix='testHtmlTable',
                            suffix='.pdf',
                            dir=temp_dir('test'))
     LOGGER.debug(path)
     # If it fails new_path will come back as None
     new_path = renderer.to_pdf(html, path)
     message = 'Rendered output does not exist: %s' % new_path
     self.assertTrue(os.path.exists(new_path), message)
     # Also it should use our desired output file name
     message = 'Incorrect path - got: %s\nExpected: %s\n' % (new_path, path)
     self.assertEqual(path, new_path, message)
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     size = os.stat(new_path).st_size
     expected_size = 16600  # as rendered on linux ub 13.04-64 (MB)
     message = ('Expected rendered map pdf to be at least %s, got %s. '
                'Please update expected_size if the rendered output '
                'is acceptible on your system.' % (expected_size, size))
     self.assertTrue(size >= expected_size, message)
예제 #4
0
def clone_raster_layer(name, extension, include_keywords, directory):
    """Helper function that copies a test raster and returns it.

    :param name: The default name for the raster layer.
    :type name: str

    :param include_keywords: Include keywords file if True.
    :type include_keywords: bool

    :param directory: Directory where the file is located.
    :type directory: str
    """
    extensions = ['.prj', '.sld', 'qml', '.prj', extension]
    if include_keywords:
        extensions.append('.keywords')
    temp_path = unique_filename()

    # copy to temp file
    for ext in extensions:
        src_path = os.path.join(directory, name + ext)
        if os.path.exists(src_path):
            trg_path = temp_path + ext
            shutil.copy2(src_path, trg_path)
    layer = QgsRasterLayer(temp_path + extension, os.path.basename(temp_path))
    return layer
예제 #5
0
    def render(self):
        """Render the map composition to an image and save that to disk.

        :returns: A three-tuple of:
            * str: myImagePath - absolute path to png of rendered map
            * QImage: myImage - in memory copy of rendered map
            * QRectF: myTargetArea - dimensions of rendered map
        :rtype: tuple
        """
        LOGGER.debug('InaSAFE Map renderComposition called')
        # NOTE: we ignore self.composition.printAsRaster() and always rasterise
        myWidth = int(self.pageDpi * self.pageWidth / 25.4)
        myHeight = int(self.pageDpi * self.pageHeight / 25.4)
        myImage = QtGui.QImage(QtCore.QSize(myWidth, myHeight),
                               QtGui.QImage.Format_ARGB32)
        myImage.setDotsPerMeterX(dpi_to_meters(self.pageDpi))
        myImage.setDotsPerMeterY(dpi_to_meters(self.pageDpi))

        # Only works in Qt4.8
        #myImage.fill(QtGui.qRgb(255, 255, 255))
        # Works in older Qt4 versions
        myImage.fill(55 + 255 * 256 + 255 * 256 * 256)
        myImagePainter = QtGui.QPainter(myImage)
        mySourceArea = QtCore.QRectF(0, 0, self.pageWidth,
                                     self.pageHeight)
        myTargetArea = QtCore.QRectF(0, 0, myWidth, myHeight)
        self.composition.render(myImagePainter, myTargetArea, mySourceArea)
        myImagePainter.end()
        myImagePath = unique_filename(prefix='mapRender_',
                                      suffix='.png',
                                      dir=temp_dir())
        myImage.save(myImagePath)
        return myImagePath, myImage, myTargetArea
예제 #6
0
파일: map.py 프로젝트: rlbartolome/inasafe
    def printToPdf(self, theFilename):
        """Generate the printout for our final map.

        Args:
            theFilename: str - optional path on the file system to which the
                pdf should be saved. If None, a generated file name will be
                used.
        Returns:
            str: file name of the output file (equivalent to theFilename if
                provided).
        Raises:
            None
        """
        LOGGER.debug("InaSAFE Map printToPdf called")
        if theFilename is None:
            myMapPdfPath = unique_filename(prefix="report", suffix=".pdf", dir=temp_dir("work"))
        else:
            # We need to cast to python string in case we receive a QString
            myMapPdfPath = str(theFilename)

        self.composeMap()
        self.printer = setupPrinter(myMapPdfPath)
        _, myImage, myRectangle = self.renderComposition()
        myPainter = QtGui.QPainter(self.printer)
        myPainter.drawImage(myRectangle, myImage, myRectangle)
        myPainter.end()
        return myMapPdfPath
예제 #7
0
    def printToPdf(self, theHtml, theFilename=None):
        """Render an html snippet into the printer, paginating as needed.

        Args:
            * theHtml: str A string containing an html snippet. It will have a
                header and footer appended to it in order to make it a valid
                html document. The header will also apply the bootstrap theme
                to the document.
            * theFilename: str String containing a pdf file path that the
                output will be written to.
        Returns:
            str: The file path of the output pdf (which is the same as the
                theFilename parameter if it was specified.

        Raises:
            None
        """
        LOGGER.info('InaSAFE Map printToPdf called')
        if theFilename is None:
            myHtmlPdfPath = unique_filename(
                prefix='table', suffix='.pdf', dir=temp_dir('work'))
        else:
            # We need to cast to python string in case we receive a QString
            myHtmlPdfPath = str(theFilename)

        self.printer = setup_printer(myHtmlPdfPath)
        self.loadAndWait(theHtmlSnippet=theHtml)
        self.webView.print_(self.printer)

        return myHtmlPdfPath
예제 #8
0
파일: map.py 프로젝트: simod/inasafe
    def drawLegend(self, theTopOffset):
        """Add a legend to the map using our custom legend renderer.

        .. note:: getLegend generates a pixmap in 150dpi so if you set
           the map to a higher dpi it will appear undersized.

        Args:
            theTopOffset - vertical offset at which to begin drawing
        Returns:
            None
        Raises:
            None
        """
        LOGGER.debug('InaSAFE Map drawLegend called')
        myLegend = MapLegend(self.layer, self.pageDpi)
        self.legend = myLegend.getLegend()
        myPicture1 = QgsComposerPicture(self.composition)
        myLegendFilePath = unique_filename(prefix='legend',
                                       suffix='.png',
                                       dir='work')
        self.legend.save(myLegendFilePath, 'PNG')
        myPicture1.setPictureFile(myLegendFilePath)
        myLegendHeight = pointsToMM(self.legend.height(), self.pageDpi)
        myLegendWidth = pointsToMM(self.legend.width(), self.pageDpi)
        myPicture1.setItemPosition(self.pageMargin,
                                   theTopOffset,
                                   myLegendWidth,
                                   myLegendHeight)
        myPicture1.setFrame(False)
        self.composition.addItem(myPicture1)
        os.remove(myLegendFilePath)
예제 #9
0
    def test_addSymbolToLegend(self):
        """Test we can add a symbol to the legend."""
        myLayer, _ = loadLayer('test_floodimpact.tif')
        myMapLegend = MapLegend(myLayer)
        mySymbol = QgsSymbol()
        mySymbol.setColor(QtGui.QColor(12, 34, 56))
        myMapLegend.addSymbolToLegend(mySymbol,
                                      theMin=0,
                                      # expect 2.0303 in legend
                                      theMax=2.02030,
                                      theCategory=None,
                                      theLabel='Foo')
        myPath = unique_filename(prefix='addSymbolToLegend',
                                 suffix='.png',
                                 dir=temp_dir('test'))
        myMapLegend.getLegend().save(myPath, 'PNG')
        LOGGER.debug(myPath)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        myTolerance = 0  # to allow for version number changes in disclaimer
        myFlag, myMessage = checkImages('addSymbolToLegend.png',
                                        myPath,
                                        myTolerance)
        myMessage += ('\nWe want these images to match, if they do already '
                      'copy the test image generated to create a new control '
                      'image.')
        assert myFlag, myMessage
예제 #10
0
    def test_add_symbol_to_legend(self):
        """Test we can add a symbol to the legend."""
        layer, _ = load_layer('test_floodimpact.tif')
        map_legend = MapLegend(layer)
        symbol = QgsFillSymbolV2()
        symbol.setColor(QtGui.QColor(12, 34, 56))
        map_legend.add_symbol(
            symbol,
            minimum=0,
            # expect 2.0303 in legend
            maximum=2.02030,
            label='Foo')
        path = unique_filename(
            prefix='addSymbolToLegend',
            suffix='.png',
            dir=temp_dir('test'))
        map_legend.get_legend().save(path, 'PNG')
        LOGGER.debug(path)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        tolerance = 0  # to allow for version number changes in disclaimer
        flag, message = check_images(
            'addSymbolToLegend', path, tolerance)
        message += (
            '\nWe want these images to match, if they do already, copy the '
            'test image generated to create a new control image.')
        self.assertTrue(flag, message)
예제 #11
0
    def draw_legend(self, top_offset):
        """Add a legend to the map using our custom legend renderer.

        .. note:: getLegend generates a pixmap in 150dpi so if you set
           the map to a higher dpi it will appear undersized.

        :param top_offset: Vertical offset at which the logo should be drawn.
        :type top_offset: int
        """
        LOGGER.debug('InaSAFE Map drawLegend called')
        legend_attributes = self.map_legend_attributes()
        legend_notes = legend_attributes.get('legend_notes', None)
        legend_units = legend_attributes.get('legend_units', None)
        legend_title = legend_attributes.get('legend_title', None)
        LOGGER.debug(legend_attributes)
        legend = MapLegend(self.layer, self.page_dpi, legend_title,
                           legend_notes, legend_units)
        self.legend = legend.get_legend()
        picture1 = QgsComposerPicture(self.composition)
        legend_file_path = unique_filename(prefix='legend',
                                           suffix='.png',
                                           dir='work')
        self.legend.save(legend_file_path, 'PNG')
        picture1.setPictureFile(legend_file_path)
        legend_height = points_to_mm(self.legend.height(), self.page_dpi)
        legend_width = points_to_mm(self.legend.width(), self.page_dpi)
        picture1.setItemPosition(self.page_margin, top_offset, legend_width,
                                 legend_height)
        picture1.setFrameEnabled(False)
        self.composition.addItem(picture1)
        os.remove(legend_file_path)
예제 #12
0
    def make_pdf(self, filename):
        """Generate the printout for our final map.

        :param filename: Path on the file system to which the pdf should be
            saved. If None, a generated file name will be used.
        :type filename: str

        :returns: File name of the output file (equivalent to filename if
                provided).
        :rtype: str
        """
        LOGGER.debug('InaSAFE Map printToPdf called')
        if filename is None:
            myMapPdfPath = unique_filename(
                prefix='report', suffix='.pdf', dir=temp_dir('work'))
        else:
            # We need to cast to python string in case we receive a QString
            myMapPdfPath = str(filename)

        self.compose_map()
        self.printer = setup_printer(myMapPdfPath)
        _, myImage, myRectangle = self.render()
        myPainter = QtGui.QPainter(self.printer)
        myPainter.drawImage(myRectangle, myImage, myRectangle)
        myPainter.end()
        return myMapPdfPath
예제 #13
0
    def make_pdf(self, filename):
        """Generate the printout for our final map.

        :param filename: Path on the file system to which the pdf should be
            saved. If None, a generated file name will be used.
        :type filename: str

        :returns: File name of the output file (equivalent to filename if
                provided).
        :rtype: str
        """
        LOGGER.debug('InaSAFE Map printToPdf called')
        if filename is None:
            map_pdf_path = unique_filename(prefix='report',
                                           suffix='.pdf',
                                           dir=temp_dir())
        else:
            # We need to cast to python string in case we receive a QString
            map_pdf_path = str(filename)

        self.load_template()

        resolution = self.composition.printResolution()
        self.printer = setup_printer(map_pdf_path, resolution=resolution)
        _, image, rectangle = self.render()
        painter = QtGui.QPainter(self.printer)
        painter.drawImage(rectangle, image, rectangle)
        painter.end()
        return map_pdf_path
예제 #14
0
    def render(self):
        """Render the map composition to an image and save that to disk.

        :returns: A three-tuple of:
            * str: image_path - absolute path to png of rendered map
            * QImage: image - in memory copy of rendered map
            * QRectF: target_area - dimensions of rendered map
        :rtype: tuple
        """
        LOGGER.debug('InaSAFE Map renderComposition called')
        # NOTE: we ignore self.composition.printAsRaster() and always rasterise
        width = int(self.page_dpi * self.page_width / 25.4)
        height = int(self.page_dpi * self.page_height / 25.4)
        image = QtGui.QImage(QtCore.QSize(width, height),
                             QtGui.QImage.Format_ARGB32)
        image.setDotsPerMeterX(dpi_to_meters(self.page_dpi))
        image.setDotsPerMeterY(dpi_to_meters(self.page_dpi))

        # Only works in Qt4.8
        #image.fill(QtGui.qRgb(255, 255, 255))
        # Works in older Qt4 versions
        image.fill(55 + 255 * 256 + 255 * 256 * 256)
        image_painter = QtGui.QPainter(image)
        source_area = QtCore.QRectF(0, 0, self.page_width, self.page_height)
        target_area = QtCore.QRectF(0, 0, width, height)
        self.composition.render(image_painter, target_area, source_area)
        image_painter.end()
        image_path = unique_filename(prefix='mapRender_',
                                     suffix='.png',
                                     dir=temp_dir())
        image.save(image_path)
        return image_path, image, target_area
예제 #15
0
 def test_getVectorLegend(self):
     """Getting a legend for a vector layer works."""
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myMapLegend = MapLegend(myLayer)
     myImage = myMapLegend.getVectorLegend()
     myPath = unique_filename(prefix='getVectorLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myImage.save(myPath, 'PNG')
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so myControlImages is a list
     # of 'known good' renders.
     myControlImages = ['getVectorLegend.png',
                        'getVectorLegend-variantWindosVistaSP2-32.png',
                        'getVectorLegend-variantUB12.04-64.png',
                        'getVectorLegend-variantUB11.04-64.png',
                        'getVectorLegend-variantJenkins.png']
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages(myControlImages,
                                 myPath,
                                 myTolerance)
     myMessage += ('\nWe want these images to match, if they do already '
             'copy the test image generated to create a new control image.')
     assert myFlag, myMessage
예제 #16
0
    def to_pdf(self, html, filename=None):
        """Render an html snippet into the printer, paginating as needed.

        :param html: A string containing an html snippet. It will have a
            header and footer appended to it in order to make it a valid
            html document. The header will also apply the bootstrap theme
            to the document.
        :type html: str

        :param filename: String containing a pdf file path that the
            output will be written to. If no file name is given we will make
            up one for you - nice eh?
        :type filename: str

        :returns: The file path of the output pdf (which is the same as the
            filename parameter if it was specified).
        :rtype: str
        """
        LOGGER.info('InaSAFE Map printToPdf called')
        if filename is None:
            myHtmlPdfPath = unique_filename(prefix='table',
                                            suffix='.pdf',
                                            dir=temp_dir('work'))
        else:
            # We need to cast to python string in case we receive a QString
            myHtmlPdfPath = str(filename)

        self.printer = setup_printer(myHtmlPdfPath)
        self.load_and_wait(html_snippet=html)
        self.webView.print_(self.printer)

        return myHtmlPdfPath
예제 #17
0
 def test_addClassToLegend(self):
     """Test we can add a class to the map legend."""
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myMapLegend = MapLegend(myLayer)
     myColour = QtGui.QColor(12, 34, 126)
     myMapLegend.addClassToLegend(myColour,
                                  theMin=None,
                                  theMax=None,
                                  theCategory=None,
                                  theLabel='bar')
     myMapLegend.addClassToLegend(myColour,
                                  theMin=None,
                                  theMax=None,
                                  theCategory=None,
                                  theLabel='foo')
     myPath = unique_filename(prefix='addClassToLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myMapLegend.getLegend().save(myPath, 'PNG')
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so place any other possible
     # variants in the safe_qgis/test_data/test_images/ dir e.g.
     # addClassToLegend-variantUbuntu13.04.png
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages('addClassToLegend.png',
                                     myPath,
                                     myTolerance)
     myMessage += ('\nWe want these images to match, if they do already '
                   'copy the test image generated to create a new control '
                   'image.')
     assert myFlag, myMessage
예제 #18
0
 def test_printImpactTable(self):
     """Test that we can render html from impact table keywords."""
     LOGGER.debug('InaSAFE HtmlRenderer testing printImpactTable')
     myFilename = 'test_floodimpact.tif'
     myLayer, _ = load_layer(myFilename)
     myMessage = 'Layer is not valid: %s' % myFilename
     assert myLayer.isValid(), myMessage
     myPageDpi = 300
     myHtmlRenderer = HtmlRenderer(myPageDpi)
     myPath = unique_filename(prefix='impactTable',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     myKeywordIO = KeywordIO()
     myKeywords = myKeywordIO.read_keywords(myLayer)
     myPath = myHtmlRenderer.print_impact_table(myKeywords,
                                              filename=myPath)
     myMessage = 'Rendered output does not exist: %s' % myPath
     assert os.path.exists(myPath), myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myPath).st_size
     myExpectedSizes = [20936,  # as rendered on linux ub 12.04 64
                        21523,  # as rendered on linux ub 12.10 64
                        20605,  # as rendered on linux ub 13.04 64
                        21527,  # as rendered on Jenkins post 22 June 2013
                        377191,  # as rendered on OSX
                        252699L,  # as rendered on Windows 7 64 bit
                        251782L,  # as rendered on Windows 8 64 bit amd
                        21491,  # as rendered on Slackware64 14.0
                        ]
     print 'Output pdf to %s' % myPath
     self.assertIn(mySize, myExpectedSizes)
예제 #19
0
    def test_getVectorLegend(self):
        """Getting a legend for a vector layer works."""
        myLayer, _ = loadLayer('test_shakeimpact.shp')
        myMapLegend = MapLegend(
            myLayer,
            theLegendNotes='Thousand separator represented by \'.\'',
            theLegendUnits='(people per cell)')
        myImage = myMapLegend.getVectorLegend()
        myPath = unique_filename(prefix='getVectorLegend',
                                 suffix='.png',
                                 dir=temp_dir('test'))
        myImage.save(myPath, 'PNG')
        print myMapLegend.legendUnits
        print myMapLegend.legendNotes
        print myPath
        LOGGER.debug(myPath)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        myTolerance = 0  # to allow for version number changes in disclaimer
        myFlag, myMessage = checkImages(
            'getVectorLegend.png', myPath, myTolerance)
        myMessage += ('\nWe want these images to match, if they do already '
                      'copy the test image generated to create a new control '
                      'image.')
        assert myFlag, myMessage
예제 #20
0
    def test_get_legend(self):
        """Getting a legend for a generic layer works."""
        LOGGER.debug('test_get_legend called')
        layer, _ = load_layer('test_shakeimpact.shp')
        map_legend = MapLegend(layer)
        self.assertTrue(map_legend.layer is not None)
        legend = map_legend.get_legend()
        path = unique_filename(
            prefix='getLegend',
            suffix='.png',
            dir=temp_dir('test'))
        legend.save(path, 'PNG')
        LOGGER.debug(path)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        tolerance = 0  # to allow for version number changes in disclaimer

        flag, message = check_images('getLegend', path, tolerance)
        message += (
            '\nWe want these images to match, if they do already '
            'copy the test image generated to create a new control '
            'image.')
        self.assertTrue(flag, message)
        LOGGER.debug('test_getLegend done')
예제 #21
0
    def test_renderHtmlToImage(self):
        """Test that we can render html to a pixmap."""
        LOGGER.debug('InaSAFE HtmlRenderer testing renderHtmlToImage')
        myHtml = self.sampleHtml(20)
        LOGGER.debug(myHtml)
        myPageDpi = 300
        myRenderer = HtmlRenderer(myPageDpi)
        myPath = unique_filename(prefix='testHtmlToImage',
                                 suffix='.png',
                                 dir=temp_dir('test'))
        LOGGER.debug(myPath)
        myWidth = 250
        myPixmap = myRenderer.renderHtmlToImage(myHtml, myWidth)
        assert not myPixmap.isNull()
        LOGGER.debug(myPixmap.__class__)
        myPixmap.save(myPath)
        myMessage = 'Rendered output does not exist: %s' % myPath
        assert os.path.exists(myPath), myMessage

        myControlImages = [
            'renderHtmlToImage.png',
            'renderHtmlToImage-variantWindosVistaSP2-32.png',
            'renderHtmlToImage-variantUB11.04-64.png',
            'renderHtmlToImage-variantUB11.10-64.png'
        ]
        myTolerance = 1000  # to allow for version number changes in disclaimer
        myFlag, myMessage = checkImages(myControlImages, myPath, myTolerance)
        assert myFlag, myMessage
예제 #22
0
def clone_shp_layer(name='tsunami_polygon',
                    include_keywords=False,
                    source_directory=TESTDATA,
                    target_directory='testing'):
    """Helper function that copies a test shp layer and returns it.

    :param name: The default name for the shp layer.
    :type name: str

    :param include_keywords: Include keywords file if True.
    :type include_keywords: bool

    :param source_directory: Directory where the file is located.
    :type source_directory: str

    :param target_directory: Subdirectory in InaSAFE temp dir that we want to
        put the files into. Default to 'testing'.
    :type target_directory: str
    """
    extensions = ['.shp', '.shx', '.dbf', '.prj']
    if include_keywords:
        extensions.append('.keywords')
    temp_path = unique_filename(dir=temp_dir(target_directory))
    # copy to temp file
    for ext in extensions:
        src_path = os.path.join(source_directory, name + ext)
        if os.path.exists(src_path):
            target_path = temp_path + ext
            shutil.copy2(src_path, target_path)

    shp_path = '%s.shp' % temp_path
    layer = QgsVectorLayer(shp_path, os.path.basename(shp_path), 'ogr')
    return layer
예제 #23
0
파일: test_map.py 프로젝트: maning/inasafe
 def test_printToPdf(self):
     """Test making a pdf of the map - this is the most typical use of map.
     """
     LOGGER.info('Testing printToPdf')
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myCanvasLayer = QgsMapCanvasLayer(myLayer)
     CANVAS.setLayerSet([myCanvasLayer])
     myRect = QgsRectangle(106.7894, -6.2308, 106.8004, -6.2264)
     CANVAS.setExtent(myRect)
     CANVAS.refresh()
     myMap = Map(IFACE)
     myMap.setImpactLayer(myLayer)
     myMap.composeMap()
     myPath = unique_filename(prefix='mapPdfTest',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     myMap.printToPdf(myPath)
     LOGGER.debug(myPath)
     myMessage = 'Rendered output does not exist: %s' % myPath
     assert os.path.exists(myPath), myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myPath).st_size
     myExpectedSizes = [
         441541,  # as rendered on ub 13.04 post 17 May 2013
         447217,  # Nadia Linux Mint 14
         0,  # as rendered on Jenkins post 24 April 2013
         447138,  # Windows 7 SP1 AMD64
     ]
     myMessage = 'Expected rendered map pdf to be in %s, got %s' % (
         myExpectedSizes, mySize)
     self.assertIn(mySize, myExpectedSizes, myMessage)
예제 #24
0
    def test_defaultTemplate(self):
        """Test that loading default template works"""
        LOGGER.info('Testing defaultTemplate')
        myLayer, _ = load_layer('test_shakeimpact.shp')
        myCanvasLayer = QgsMapCanvasLayer(myLayer)
        CANVAS.setLayerSet([myCanvasLayer])
        myRect = QgsRectangle(106.7894, -6.2308, 106.8004, -6.2264)
        CANVAS.setExtent(myRect)
        CANVAS.refresh()
        myMap = Map(IFACE)
        myMap.set_impact_layer(myLayer)
        myPath = unique_filename(prefix='mapDefaultTemplateTest',
                                 suffix='.pdf',
                                 dir=temp_dir('test'))
        myMap.make_pdf(myPath)
        LOGGER.debug(myPath)
        myMessage = 'Rendered output does not exist: %s' % myPath
        assert os.path.exists(myPath), myMessage
        # pdf rendering is non deterministic so we can't do a hash check
        # test_renderComposition renders just the image instead of pdf
        # so we hash check there and here we just do a basic minimum file
        # size check.
        mySize = os.stat(myPath).st_size

        # Note: You should replace, not append the numbers for a given
        # platform. Also note that this test will break every time the
        # version number of InaSAFE changes so we should ultimately come up
        # with a lower maintenance test strategy.

        myExpectedSizes = [
            400350,  # Slackware64 14.0
        ]
        myMessage = '%s\nExpected rendered map pdf to be in %s, got %s' % (
            myPath, myExpectedSizes, mySize)
        self.assertIn(mySize, myExpectedSizes, myMessage)
예제 #25
0
    def printToPdf(self, theFilename):
        """Generate the printout for our final map.

        Args:
            theFilename: str - optional path on the file system to which the
                pdf should be saved. If None, a generated file name will be
                used.
        Returns:
            str: file name of the output file (equivalent to theFilename if
                provided).
        Raises:
            None
        """
        LOGGER.debug('InaSAFE Map printToPdf called')
        if theFilename is None:
            myMapPdfPath = unique_filename(prefix='report',
                                           suffix='.pdf',
                                           dir=temp_dir('work'))
        else:
            # We need to cast to python string in case we receive a QString
            myMapPdfPath = str(theFilename)

        self.composeMap()
        self.printer = setupPrinter(myMapPdfPath)
        _, myImage, myRectangle = self.renderComposition()
        myPainter = QtGui.QPainter(self.printer)
        myPainter.drawImage(myRectangle, myImage, myRectangle)
        myPainter.end()
        return myMapPdfPath
예제 #26
0
 def test_addClassToLegend(self):
     """Test we can add a class to the map legend."""
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myMapLegend = MapLegend(myLayer)
     myColour = QtGui.QColor(12, 34, 126)
     myMapLegend.addClassToLegend(myColour,
                            theMin=None,
                            theMax=None,
                            theCategory=None,
                            theLabel='bar')
     myMapLegend.addClassToLegend(myColour,
                            theMin=None,
                            theMax=None,
                            theCategory=None,
                            theLabel='foo')
     myPath = unique_filename(prefix='addClassToLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myMapLegend.getLegend().save(myPath, 'PNG')
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so myControlImages is a list
     # of 'known good' renders.
     myControlImages = ['getClassToLegend.png',
                        'getClassToLegend-variantWindosVistaSP2-32.png',
                        'getClassToLegend-variantUB12.04-64.png',
                        'getClassToLegend-variantUB11.04-64.png',
                        'getClassToLegend-variantJenkins.png']
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages(myControlImages,
                                     myPath,
                                     myTolerance)
     myMessage += ('\nWe want these images to match, if they do already '
             'copy the test image generated to create a new control image.')
     assert myFlag, myMessage
예제 #27
0
    def drawLegend(self, theTopOffset):
        """Add a legend to the map using our custom legend renderer.

        .. note:: getLegend generates a pixmap in 150dpi so if you set
           the map to a higher dpi it will appear undersized.

        Args:
            theTopOffset - vertical offset at which to begin drawing
        Returns:
            None
        Raises:
            None
        """
        LOGGER.debug('InaSAFE Map drawLegend called')
        mapLegendAttributes = self.getMapLegendAtributes()
        legendNotes = mapLegendAttributes.get('legend_notes', None)
        legendUnits = mapLegendAttributes.get('legend_units', None)
        legendTitle = mapLegendAttributes.get('legend_title', None)
        LOGGER.debug(mapLegendAttributes)
        myLegend = MapLegend(self.layer, self.pageDpi, legendTitle,
                             legendNotes, legendUnits)
        self.legend = myLegend.getLegend()
        myPicture1 = QgsComposerPicture(self.composition)
        myLegendFilePath = unique_filename(prefix='legend',
                                           suffix='.png',
                                           dir='work')
        self.legend.save(myLegendFilePath, 'PNG')
        myPicture1.setPictureFile(myLegendFilePath)
        myLegendHeight = pointsToMM(self.legend.height(), self.pageDpi)
        myLegendWidth = pointsToMM(self.legend.width(), self.pageDpi)
        myPicture1.setItemPosition(self.pageMargin, theTopOffset,
                                   myLegendWidth, myLegendHeight)
        myPicture1.setFrame(False)
        self.composition.addItem(myPicture1)
        os.remove(myLegendFilePath)
예제 #28
0
파일: map.py 프로젝트: rlbartolome/inasafe
    def drawLegend(self, theTopOffset):
        """Add a legend to the map using our custom legend renderer.

        .. note:: getLegend generates a pixmap in 150dpi so if you set
           the map to a higher dpi it will appear undersized.

        Args:
            theTopOffset - vertical offset at which to begin drawing
        Returns:
            None
        Raises:
            None
        """
        LOGGER.debug("InaSAFE Map drawLegend called")
        mapLegendAttributes = self.getMapLegendAtributes()
        legendNotes = mapLegendAttributes.get("legend_notes", None)
        legendUnits = mapLegendAttributes.get("legend_units", None)
        legendTitle = mapLegendAttributes.get("legend_title", None)
        LOGGER.debug(mapLegendAttributes)
        myLegend = MapLegend(self.layer, self.pageDpi, legendTitle, legendNotes, legendUnits)
        self.legend = myLegend.getLegend()
        myPicture1 = QgsComposerPicture(self.composition)
        myLegendFilePath = unique_filename(prefix="legend", suffix=".png", dir="work")
        self.legend.save(myLegendFilePath, "PNG")
        myPicture1.setPictureFile(myLegendFilePath)
        myLegendHeight = pointsToMM(self.legend.height(), self.pageDpi)
        myLegendWidth = pointsToMM(self.legend.width(), self.pageDpi)
        myPicture1.setItemPosition(self.pageMargin, theTopOffset, myLegendWidth, myLegendHeight)
        myPicture1.setFrame(False)
        self.composition.addItem(myPicture1)
        os.remove(myLegendFilePath)
예제 #29
0
 def test_printImpactTable(self):
     """Test that we can render html from impact table keywords."""
     LOGGER.debug('InaSAFE HtmlRenderer testing printImpactTable')
     myFilename = 'test_floodimpact.tif'
     myLayer, _ = loadLayer(myFilename)
     myMessage = 'Layer is not valid: %s' % myFilename
     assert myLayer.isValid(), myMessage
     myPageDpi = 300
     myHtmlRenderer = HtmlRenderer(myPageDpi)
     myPath = unique_filename(prefix='impactTable',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     myKeywordIO = KeywordIO()
     myKeywords = myKeywordIO.readKeywords(myLayer)
     myPath = myHtmlRenderer.printImpactTable(myKeywords,
                                              theFilename=myPath)
     myMessage = 'Rendered output does not exist: %s' % myPath
     assert os.path.exists(myPath), myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myPath).st_size
     myExpectedSize = 20936  # as rendered on linux ub 12.04 64
     myMessage = ('Expected rendered table pdf to be at least %s, got %s'
                  % (myExpectedSize, mySize))
     assert mySize >= myExpectedSize, myMessage
예제 #30
0
def clone_shp_layer(
        name='tsunami_polygon', include_keywords=False, directory=TESTDATA):
    """Helper function that copies a test shplayer and returns it.

    :param name: The default name for the shp layer.
    :type name: str

    :param include_keywords: Include keywords file if True.
    :type include_keywords: bool

    :param directory: Directory where the file is located.
    :type directory: str

    """
    extensions = ['.shp', '.shx', '.dbf', '.prj']
    if include_keywords:
        extensions.append('.keywords')
    temp_path = unique_filename()
    # copy to temp file
    for ext in extensions:
        src_path = os.path.join(directory, name + ext)
        if os.path.exists(src_path):
            trg_path = temp_path + ext
            shutil.copy2(src_path, trg_path)
    # return a single predefined layer
    layer = QgsVectorLayer(temp_path + '.shp', 'TestLayer', 'ogr')
    return layer
예제 #31
0
 def test_addSymbolToLegend(self):
     """Test we can add a symbol to the legend."""
     myLayer, _ = loadLayer('test_floodimpact.tif')
     myMapLegend = MapLegend(myLayer)
     mySymbol = QgsSymbol()
     mySymbol.setColor(QtGui.QColor(12, 34, 56))
     myMapLegend.addSymbolToLegend(mySymbol,
                                   theMin=0,
                                   theMax=2,
                                   theCategory=None,
                                   theLabel='Foo')
     myPath = unique_filename(prefix='addSymblToLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myMapLegend.getLegend().save(myPath, 'PNG')
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so myControlImages is a list
     # of 'known good' renders.
     myControlImages = [
         'addSymbolToLegend.png',
         'addSymbolToLegend-variantWindosVistaSP2-32.png',
         'addSymbolToLegend-variantUB12.04-64.png',
         'addSymbolToLegend-variantUB11.04-64.png',
         'addSymbolToLegend-variantJenkins.png'
     ]
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages(myControlImages, myPath, myTolerance)
     myMessage += (
         '\nWe want these images to match, if they do already '
         'copy the test image generated to create a new control image.')
     assert myFlag, myMessage
예제 #32
0
 def test_printToPdf(self):
     """Test that we can render some html to a pdf (most common use case).
     """
     LOGGER.debug('InaSAFE HtmlRenderer testing printToPdf')
     html = self.sample_html()
     page_dpi = 300
     renderer = HtmlRenderer(page_dpi)
     path = unique_filename(
         prefix='testHtmlTable',
         suffix='.pdf',
         dir=temp_dir('test'))
     LOGGER.debug(path)
     # If it fails new_path will come back as None
     new_path = renderer.to_pdf(html, path)
     message = 'Rendered output does not exist: %s' % new_path
     assert os.path.exists(new_path), message
     # Also it should use our desired output file name
     message = 'Incorrect path - got: %s\nExpected: %s\n' % (
         new_path, path)
     assert new_path == path, message
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     size = os.stat(new_path).st_size
     expected_size = 16600  # as rendered on linux ub 13.04-64 (MB)
     message = (
         'Expected rendered map pdf to be at least %s, got %s. '
         'Please update expected_size if the rendered output '
         'is acceptible on your system.'
         % (expected_size, size))
     assert size >= expected_size, message
예제 #33
0
 def test_getRasterLegend(self):
     """Getting a legend for a raster layer works."""
     myLayer, _ = loadLayer('test_floodimpact.tif')
     myMapLegend = MapLegend(myLayer)
     myImage = myMapLegend.getRasterLegend()
     myPath = unique_filename(prefix='getRasterLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myImage.save(myPath, 'PNG')
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so myControlImages is a list
     # of 'known good' renders.
     myControlImages = [
         'getRasterLegend.png',
         'getRasterLegend-variantWindosVistaSP2-32.png',
         'getRasterLegend-variantUB12.04-64.png',
         'getRasterLegend-variantUB11.04-64.png',
         'getRasterLegend-variantJenkins.png'
     ]
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages(myControlImages, myPath, myTolerance)
     myMessage += (
         '\nWe want these images to match, if they do already '
         'copy the test image generated to create a new control image.')
     assert myFlag, myMessage
예제 #34
0
    def make_pdf(self, filename):
        """Generate the printout for our final map.

        :param filename: Path on the file system to which the pdf should be
            saved. If None, a generated file name will be used.
        :type filename: str

        :raises: TemplateElementMissingError - when template elements are
            missing

        :returns: File name of the output file (equivalent to filename if
                provided).
        :rtype: str
        """
        LOGGER.debug('InaSAFE Map printToPdf called')
        self.setup_composition()
        self.load_template()

        if filename is None:
            map_pdf_path = unique_filename(prefix='report',
                                           suffix='.pdf',
                                           dir=temp_dir())
        else:
            # We need to cast to python string in case we receive a QString
            map_pdf_path = str(filename)

        self.composition.exportAsPDF(map_pdf_path)
        return map_pdf_path
예제 #35
0
 def test_printImpactTable(self):
     """Test that we can render html from impact table keywords."""
     LOGGER.debug('InaSAFE HtmlRenderer testing printImpactTable')
     myFilename = 'test_floodimpact.tif'
     myLayer, _ = loadLayer(myFilename)
     myMessage = 'Layer is not valid: %s' % myFilename
     assert myLayer.isValid(), myMessage
     myPageDpi = 300
     myHtmlRenderer = HtmlRenderer(myPageDpi)
     myPath = unique_filename(prefix='impactTable',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     myKeywordIO = KeywordIO()
     myKeywords = myKeywordIO.readKeywords(myLayer)
     myPath = myHtmlRenderer.printImpactTable(myKeywords,
                                              theFilename=myPath)
     myMessage = 'Rendered output does not exist: %s' % myPath
     assert os.path.exists(myPath), myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myPath).st_size
     myExpectedSize = 20936  # as rendered on linux ub 12.04 64
     myMessage = ('Expected rendered table pdf to be at least %s, got %s'
                  % (myExpectedSize, mySize))
     assert mySize >= myExpectedSize, myMessage
예제 #36
0
 def test_printToPdf(self):
     """Test that we can render some html to a pdf (most common use case).
     """
     LOGGER.debug('InaSAFE HtmlRenderer testing printToPdf')
     myHtml = self.sampleHtml()
     myPageDpi = 300
     myRenderer = HtmlRenderer(myPageDpi)
     myPath = unique_filename(prefix='testHtmlTable',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     LOGGER.debug(myPath)
     # If it fails myNewPath will come back as None
     myNewPath = myRenderer.to_pdf(myHtml, myPath)
     myMessage = 'Rendered output does not exist: %s' % myNewPath
     assert os.path.exists(myNewPath), myMessage
     # Also it should use our desired output file name
     myMessage = 'Incorrect path - got: %s\nExpected: %s\n' % (
         myNewPath, myPath)
     assert myNewPath == myPath, myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myNewPath).st_size
     myExpectedSize = 18449  # as rendered on linux ub 11.04-64
     myMessage = ('Expected rendered map pdf to be at least %s, got %s. '
                  'Please update myExpectedSize if the rendered output '
                  'is acceptible on your system.'
                  % (myExpectedSize, mySize))
     assert mySize >= myExpectedSize, myMessage
예제 #37
0
    def test_renderHtmlToImage(self):
        """Test that we can render html to a pixmap."""
        LOGGER.debug('InaSAFE HtmlRenderer testing renderHtmlToImage')
        myHtml = self.sampleHtml(20)
        LOGGER.debug(myHtml)
        myPageDpi = 300
        myRenderer = HtmlRenderer(myPageDpi)
        myPath = unique_filename(prefix='testHtmlToImage',
                                 suffix='.png',
                                 dir=temp_dir('test'))
        LOGGER.debug(myPath)
        myWidth = 250
        myPixmap = myRenderer.renderHtmlToImage(myHtml, myWidth)
        assert not myPixmap.isNull()
        LOGGER.debug(myPixmap.__class__)
        myPixmap.save(myPath)
        myMessage = 'Rendered output does not exist: %s' % myPath
        assert os.path.exists(myPath), myMessage

        myControlImages = ['renderHtmlToImage.png',
                           'renderHtmlToImage-variantOSX10.8.png',
                           'renderHtmlToImage-variantWindosVistaSP2-32.png',
                           'renderHtmlToImage-variantWindowsXPSP3-32.png',
                           'renderHtmlToImage-variantUB11.04-64.png',
                           'renderHtmlToImage-variantLinuxMint-14-x86_64.png',
                           'renderHtmlToImage-variantWindows7-SP1-AMD64.png',
                           'renderHtmlToImage-variantUB11.10-64.png']
        myTolerance = 1000  # to allow for version number changes in disclaimer
        myFlag, myMessage = checkImages(myControlImages, myPath, myTolerance)
        assert myFlag, myMessage
예제 #38
0
 def test_add_class_to_legend(self):
     """Test we can add a class to the map legend."""
     layer, _ = load_layer('test_shakeimpact.shp')
     map_legend = MapLegend(layer)
     colour = QtGui.QColor(12, 34, 126)
     map_legend.add_class(
         colour,
         label='bar')
     map_legend.add_class(
         colour,
         label='foo')
     path = unique_filename(
         prefix='addClassToLegend',
         suffix='.png',
         dir=temp_dir('test'))
     map_legend.get_legend().save(path, 'PNG')
     LOGGER.debug(path)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so place any other possible
     # variants in the safe_qgis/test_data/test_images/ dir e.g.
     # addClassToLegend-variantUbuntu13.04.png
     tolerance = 0  # to allow for version number changes in disclaimer
     flag, message = check_images(
         'addClassToLegend', path, tolerance)
     message += (
         '\nWe want these images to match, if they do already copy the test'
         ' image generated to create a new control image.')
     self.assertTrue(flag, message)
예제 #39
0
def html_to_file(html, file_path=None, open_browser=False):
    """Save the html to an html file adapting the paths to the filesystem.

    if a file_path is passed, it is used, if not a unique_filename is
    generated.

    qrc:/..../ paths gets converted to file:///..../

    :param html: the html for the output file.
    :type html: str

    :param file_path: the path for the html output file.
    :type file_path: str

    :param open_browser: if true open the generated html in an external browser
    :type open_browser: bool
    """
    if file_path is None:
        file_path = unique_filename(suffix='.html')

    file_dir = os.path.dirname(file_path)
    reg_exp = re.compile(r'qrc:/plugins/inasafe/([-./ \w]*)')
    html = reg_exp.sub(lambda match: map_qrc_to_file(match, file_dir), html)

    with open(file_path, 'w') as f:
        f.write(html)

    if open_browser:
        open_in_browser(file_path)
예제 #40
0
    def test_get_vector_legend(self):
        """Getting a legend for a vector layer works.

        .. note:: This test is not related do thousand separator since we
            insert our own legend notes and our own layer.
        """
        layer, _ = load_layer('test_shakeimpact.shp')
        map_legend = MapLegend(
            layer,
            legend_notes='Thousand separator represented by \',\'',
            legend_units='(people per cell)')
        image = map_legend.vector_legend()
        path = unique_filename(
            prefix='getVectorLegend',
            suffix='.png',
            dir=temp_dir('test'))
        image.save(path, 'PNG')
        LOGGER.debug(path)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        tolerance = 0  # to allow for version number changes in disclaimer
        flag, message = check_images(
            'getVectorLegend', path, tolerance)
        message += (
            '\nWe want these images to match, if they do already '
            'copy the test image generated to create a new control image.')
        self.assertTrue(flag, message)
예제 #41
0
    def test_getVectorLegend(self):
        """Getting a legend for a vector layer works.
        @note This test is not related do thousand separator since we insert
        our own legend notes and our own layer.
        """
        myLayer, _ = load_layer('test_shakeimpact.shp')
        myMapLegend = MapLegend(
            myLayer,
            theLegendNotes='Thousand separator represented by \',\'',
            theLegendUnits='(people per cell)')
        myImage = myMapLegend.getVectorLegend()
        myPath = unique_filename(
            prefix='getVectorLegend',
            suffix='.png',
            dir=temp_dir('test'))
        myImage.save(myPath, 'PNG')
        LOGGER.debug(myPath)
        # As we have discovered, different versions of Qt and
        # OS platforms cause different output, so myControlImages is a list
        # of 'known good' renders.

        myTolerance = 0  # to allow for version number changes in disclaimer
        myFlag, myMessage = check_images(
            'getVectorLegend', myPath, myTolerance)
        myMessage += ('\nWe want these images to match, if they do already '
                      'copy the test image generated to create a new control '
                      'image.')
        assert myFlag, myMessage
예제 #42
0
    def to_pdf(self, html, filename=None):
        """Render an html snippet into the printer, paginating as needed.

        :param html: A string containing an html snippet. It will have a
            header and footer appended to it in order to make it a valid
            html document. The header will also apply the bootstrap theme
            to the document.
        :type html: str

        :param filename: String containing a pdf file path that the
            output will be written to. If no file name is given we will make
            up one for you - nice eh?
        :type filename: str

        :returns: The file path of the output pdf (which is the same as the
            filename parameter if it was specified).
        :rtype: str
        """
        LOGGER.info('InaSAFE Map printToPdf called')
        if filename is None:
            html_pdf_path = unique_filename(
                prefix='table', suffix='.pdf', dir=temp_dir())
        else:
            # We need to cast to python string in case we receive a QString
            html_pdf_path = str(filename)

        self.printer = setup_printer(html_pdf_path)
        self.load_and_wait(html_snippet=html)
        self.web_view.print_(self.printer)

        return html_pdf_path
예제 #43
0
def clone_shp_layer(
        name='tsunami_polygon',
        include_keywords=False,
        source_directory=TESTDATA,
        target_directory='testing'):
    """Helper function that copies a test shp layer and returns it.

    :param name: The default name for the shp layer.
    :type name: str

    :param include_keywords: Include keywords file if True.
    :type include_keywords: bool

    :param source_directory: Directory where the file is located.
    :type source_directory: str

    :param target_directory: Subdirectory in InaSAFE temp dir that we want to
        put the files into. Default to 'testing'.
    :type target_directory: str
    """
    extensions = ['.shp', '.shx', '.dbf', '.prj']
    if include_keywords:
        extensions.append('.keywords')
    temp_path = unique_filename(dir=temp_dir(target_directory))
    # copy to temp file
    for ext in extensions:
        src_path = os.path.join(source_directory, name + ext)
        if os.path.exists(src_path):
            target_path = temp_path + ext
            shutil.copy2(src_path, target_path)

    shp_path = '%s.shp' % temp_path
    layer = QgsVectorLayer(shp_path, os.path.basename(shp_path), 'ogr')
    return layer
예제 #44
0
파일: map.py 프로젝트: cccs-ip/inasafe
    def make_pdf(self, filename):
        """Generate the printout for our final map.

        :param filename: Path on the file system to which the pdf should be
            saved. If None, a generated file name will be used.
        :type filename: str

        :raises: TemplateElementMissingError - when template elements are
            missing

        :returns: File name of the output file (equivalent to filename if
                provided).
        :rtype: str
        """
        LOGGER.debug('InaSAFE Map printToPdf called')
        self.setup_composition()
        self.load_template()

        if filename is None:
            map_pdf_path = unique_filename(
                prefix='report', suffix='.pdf', dir=temp_dir())
        else:
            # We need to cast to python string in case we receive a QString
            map_pdf_path = str(filename)

        self.composition.exportAsPDF(map_pdf_path)
        return map_pdf_path
예제 #45
0
 def test_getVectorLegend(self):
     """Getting a legend for a vector layer works."""
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myMapLegend = MapLegend(
         myLayer,
         theLegendNotes='Thousand separator represented by \'.\'',
         theLegendUnits='(people per cell)')
     myImage = myMapLegend.getVectorLegend()
     myPath = unique_filename(prefix='getVectorLegend',
                              suffix='.png',
                              dir=temp_dir('test'))
     myImage.save(myPath, 'PNG')
     print myMapLegend.legendUnits
     print myMapLegend.legendNotes
     print myPath
     LOGGER.debug(myPath)
     # As we have discovered, different versions of Qt and
     # OS platforms cause different output, so myControlImages is a list
     # of 'known good' renders.
     myControlImages = ['getVectorLegend.png',
                        'getVectorLegend-variantWindowsVistaSP2-32.png',
                        'getVectorLegend-variantWindowsXPSP3-32.png',
                        'getVectorLegend-variantOSXml.png',
                        'getVectorLegend-variantUB12.04-64.png',
                        'getVectorLegend-variantUB11.04-64.png',
                        'getVectorLegend-variantLinuxMint-14-x86_64.png',
                        'getVectorLegend-variantWindows7-SP1-AMD64.png',
                        'getVectorLegend-variantJenkins.png']
     myTolerance = 0  # to allow for version number changes in disclaimer
     myFlag, myMessage = checkImages(myControlImages, myPath, myTolerance)
     myMessage += ('\nWe want these images to match, if they do already '
                   'copy the test image generated to create a new control '
                   'image.')
     assert myFlag, myMessage
예제 #46
0
파일: utilities.py 프로젝트: D2KG/FLOOgin
def html_to_file(html, file_path=None, open_browser=False):
    """Save the html to an html file adapting the paths to the filesystem.

    if a file_path is passed, it is used, if not a unique_filename is
    generated.

    qrc:/..../ paths gets converted to file:///..../

    :param html: the html for the output file.
    :type html: str

    :param file_path: the path for the html output file.
    :type file_path: str

    :param open_browser: if true open the generated html in an external browser
    :type open_browser: bool
    """
    if file_path is None:
        file_path = unique_filename(suffix='.html')

    file_dir = os.path.dirname(file_path)
    reg_exp = re.compile(r'qrc:/plugins/inasafe/([-./ \w]*)')
    html = reg_exp.sub(lambda match: map_qrc_to_file(match, file_dir),
                       html)

    with open(file_path, 'w') as f:
        f.write(html)

    if open_browser:
        open_in_browser(file_path)
예제 #47
0
 def test_printToPdf(self):
     """Test making a pdf of the map - this is the most typical use of map.
     """
     LOGGER.info('Testing printToPdf')
     myLayer, _ = loadLayer('test_shakeimpact.shp')
     myCanvasLayer = QgsMapCanvasLayer(myLayer)
     CANVAS.setLayerSet([myCanvasLayer])
     myRect = QgsRectangle(106.7894, -6.2308, 106.8004, -6.2264)
     CANVAS.setExtent(myRect)
     CANVAS.refresh()
     myMap = Map(IFACE)
     myMap.setImpactLayer(myLayer)
     myMap.composeMap()
     myPath = unique_filename(prefix='mapPdfTest',
                              suffix='.pdf',
                              dir=temp_dir('test'))
     myMap.printToPdf(myPath)
     LOGGER.debug(myPath)
     myMessage = 'Rendered output does not exist: %s' % myPath
     assert os.path.exists(myPath), myMessage
     # pdf rendering is non deterministic so we can't do a hash check
     # test_renderComposition renders just the image instead of pdf
     # so we hash check there and here we just do a basic minimum file
     # size check.
     mySize = os.stat(myPath).st_size
     myExpectedSize = 352798  # as rendered on linux ub 12.04 64
     myMessage = 'Expected rendered map pdf to be at least %s, got %s' % (
         myExpectedSize, mySize)
     assert mySize >= myExpectedSize, myMessage
예제 #48
0
    def printImpactTable(self, theKeywords, theFilename=None):
        """High level table generator to print layer keywords.

        It gets the summary and impact table from a QgsMapLayer's keywords and
        renders to pdf, returning the resulting PDF file path.

        Args:
            theKeywords: dic containing impact layer keywords (required)

        Returns:
            str: Path to generated pdf file.

        Raises:
            None

        """
        myFilePath = theFilename

        if theFilename is None:
            myFilePath = unique_filename(suffix='.pdf', dir=temp_dir())

        try:
            mySummaryTable = theKeywords['impact_summary']
        except KeyError:
            mySummaryTable = None

        myAttributionTable = impact_attribution(theKeywords)

        try:
            myFullTable = theKeywords['impact_table']
        except KeyError:
            myFullTable = None

        try:
            myAggregationTable = theKeywords['postprocessing_report']
        except KeyError:
            myAggregationTable = None

        myHtml = ''
        if mySummaryTable != myFullTable and mySummaryTable is not None:
            myHtml = '<h2>%s</h2>' % self.tr('Summary Table')
            myHtml += mySummaryTable
            if myAggregationTable is not None:
                myHtml += myAggregationTable
            if myAttributionTable is not None:
                myHtml += myAttributionTable.to_html()
            myHtml += '<h2>%s</h2>' % self.tr('Detailed Table')
            myHtml += myFullTable
        else:
            if myAggregationTable is not None:
                myHtml = myAggregationTable
            if myFullTable is not None:
                myHtml += myFullTable
            if myAttributionTable is not None:
                myHtml += myAttributionTable.to_html()

        # myNewFilePath should be the same as myFilePath
        myNewFilePath = self.printToPdf(myHtml, myFilePath)
        return myNewFilePath
예제 #49
0
def clone_csv_layer():
    """Helper function that copies a test csv layer and returns it."""
    path = 'test_buildings.csv'
    temp_path = unique_filename()
    # copy to temp file
    source_path = os.path.join(TESTDATA, path)
    shutil.copy2(source_path, temp_path)
    # return a single predefined layer
    layer = QgsVectorLayer(temp_path, '', 'delimitedtext')
    return layer
예제 #50
0
    def test_windowsDrawingArtifacts(self):
        """Test that windows rendering does not make artifacts"""
        # sometimes spurious lines are drawn on the layout
        LOGGER.info('Testing windowsDrawingArtifacts')
        myPath = unique_filename(
            prefix='artifacts',
            suffix='.pdf',
            dir=temp_dir('test'))
        myMap = Map(IFACE)
        setup_printer(myPath)
        myMap.setup_composition()

        myImage = QtGui.QImage(10, 10, QtGui.QImage.Format_RGB32)
        myImage.setDotsPerMeterX(dpi_to_meters(300))
        myImage.setDotsPerMeterY(dpi_to_meters(300))
        #myImage.fill(QtGui.QColor(250, 250, 250))
        # Look at the output, you will see antialiasing issues around some
        # of the boxes drawn...
        # myImage.fill(QtGui.QColor(200, 200, 200))
        myImage.fill(200 + 200 * 256 + 200 * 256 * 256)
        myFilename = os.path.join(temp_dir(), 'greyBox')
        myImage.save(myFilename, 'PNG')
        for i in range(10, 190, 10):
            myPicture = QgsComposerPicture(myMap.composition)
            myPicture.setPictureFile(myFilename)
            if qgis_version() >= 10800:  # 1.8 or newer
                myPicture.setFrameEnabled(False)
            else:
                myPicture.setFrame(False)
            myPicture.setItemPosition(i,  # x
                                      i,  # y
                                      10,  # width
                                      10)  # height
            myMap.composition.addItem(myPicture)
            # Same drawing drawn directly as a pixmap
            # noinspection PyCallByClass,PyTypeChecker,PyArgumentList
            myPixmapItem = myMap.composition.addPixmap(
                QtGui.QPixmap.fromImage(myImage))
            myPixmapItem.setOffset(i, i + 20)
            # Same drawing using our drawImage Helper
            myWidthMM = 1
            myMap.draw_image(myImage, myWidthMM, i, i + 40)

        myImagePath, _, _ = myMap.render()
        # when this test no longer matches our broken render hash
        # we know the issue is fixed

        myTolerance = 0
        myFlag, myMessage = check_images(
            'windowsArtifacts',
            myImagePath,
            myTolerance)
        myMessage += ('\nWe want these images to match, if they do not '
                      'there may be rendering artifacts in windows.\n')
        assert myFlag, myMessage
예제 #51
0
    def test_save_scenario(self):
        """Test saving Current scenario."""
        result, message = setup_scenario(
            DOCK,
            hazard='Flood in Jakarta',
            exposure='Penduduk Jakarta',
            function='Be impacted',
            function_id='Categorised Hazard Population Impact Function')
        self.assertTrue(result, message)

        # Enable on-the-fly reprojection
        set_canvas_crs(GEOCRS, True)
        set_jakarta_extent(dock=DOCK)

        # create unique file
        scenario_file = unique_filename(
            prefix='scenarioTest', suffix='.txt', dir=temp_dir('test'))

        self.save_scenario_dialog.save_scenario(
            scenario_file_path=scenario_file)
        with open(scenario_file) as f:
            data = f.readlines()
        title = data[0][:-1]
        exposure = data[1][:-1]
        hazard = data[2][:-1]
        function = data[3][:-1]
        extent = data[4][:-1]
        self.assertTrue(
            os.path.exists(scenario_file),
            'File %s does not exist' % scenario_file)
        self.assertTrue(title == '[Flood in Jakarta]', 'Title is not the same')
        self.assertTrue(
            exposure.startswith('exposure =') and exposure.endswith(
                'Population_Jakarta_geographic.asc'),
            'Exposure is not the same')
        self.assertTrue(
            hazard.startswith('hazard =') and hazard.endswith(
                'jakarta_flood_category_123.asc'),
            'Hazard is not the same')
        self.assertTrue(
            function == (
                'function = Categorised Hazard Population Impact Function'),
            'Impact function is not same')

        # TODO: figure out why this changed between releases
        if qgis_version() < 20400:
            # For QGIS 2.0
            expected_extent = (
                'extent = 106.313333, -6.380000, 107.346667, -6.070000')
            self.assertEqual(expected_extent, extent)
        else:
            # for QGIS 2.4
            expected_extent = (
                'extent = 106.287500, -6.380000, 107.372500, -6.070000')
            self.assertEqual(expected_extent, expected_extent)