Example #1
0
  def accept( self ):
    if not self.config:
      return

    if self.leOutput.text().isEmpty():
      QMessageBox.warning( self,
                           self.tr( "Reporter" ),
                           self.tr( "Please specify output report file" ) )
      return

    self.cleanupConfigAndGui()
    self.saveSettings()

    # get layer count
    layerCount = 0
    layerNames = []
    for i in xrange( self.lstLayers.topLevelItemCount() ):
      item = self.lstLayers.topLevelItem( i )
      if item.checkState( 0 ) == Qt.Checked:
        layerCount += 1
        layerNames.append( item.text( 0 ) )

    self.progressBar.setRange( 0, layerCount )

    QApplication.setOverrideCursor( QCursor( Qt.WaitCursor ) )
    self.btnOk.setEnabled( False )

    # ***************** create reports ************************
    overlayLayer = utils.getVectorLayerByName( self.cmbAnalysisRegion.currentText() )
    overlayProvider = overlayLayer.dataProvider()

    isFirst = True
    mapCRS = self.iface.mapCanvas().mapRenderer().destinationCrs()
    hasOTFR = self.iface.mapCanvas().hasCrsTransformEnabled()
    crsTransform = QgsCoordinateTransform( overlayLayer.crs(), mapCRS )
    needTransform = ( overlayLayer.crs() != mapCRS )
    dirName = QFileInfo( self.leOutput.text() ).absolutePath()

    # get dimensioning coefficient
    coef = 1.0
    settings = QSettings( "NextGIS", "reporter" )
    if settings.value( "dimensioning", "none" ).toString() == "none":
      coef = 1.0
    elif settings.value( "dimensioning", "none" ).toString() == "kilo":
      coef = 0.00001
    else:
      coef = 0.0000001

    # variables to store information used in reports
    dataArea = dict()
    dataObjects = dict()

    # init report writer
    writer = wordmlwriter.WordMLWriter()

    for layerName in layerNames:
      self.progressBar.setFormat( self.tr( "%p% processing: %1" ).arg( layerName ) )
      QCoreApplication.processEvents()

      layerElement = utils.findLayerInConfig( self.cfgRoot, layerName )
      labelFieldName = utils.labelFieldName( layerElement )

      vLayer = utils.getVectorLayerByName( layerName )
      vProvider = vLayer.dataProvider()

      vProvider.rewind()
      vProvider.select( vProvider.attributeIndexes() )

      # check layer renderer and determine classification field
      rendererType = None
      fieldName = None
      fieldIndex = None
      categories = None

      if vLayer.isUsingRendererV2():
        renderer = vLayer.rendererV2()
        rendererType = renderer.type()
        if rendererType in [ "singleSymbol", "Single Symbol" ]:
          tmp = utils.labelFieldName( layerElement )
          if tmp.isEmpty():
            fieldIndex = 0
            fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          else:
            fieldName = tmp
            fieldIndex = utils.fieldIndexByName( vProvider, fieldName )
        elif rendererType in [ "categorizedSymbol", "Unique Value" ]:
          fieldName = renderer.classAttribute()
          fieldIndex = utils.fieldIndexByName( vProvider, fieldName )
          categories = renderer.categories()
        else:
          print "Invalid renderer type! Skip this layer..."
          continue
      else:
        renderer = vLayer.renderer()
        rendererType = renderer.name()
        if rendererType in [ "singleSymbol", "Single Symbol" ]:
          tmp = utils.labelFieldName( layerElement )
          if tmp.isEmpty():
            fieldIndex = 0
            fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          else:
            fieldName = tmp
            fieldIndex = utils.fieldIndexByName( vProvider, fieldName )
        elif rendererType in [ "categorizedSymbol", "Unique Value" ]:
          fieldIndex = renderer.classificationField()
          fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          categories = renderer.symbolMap()
        else:
          print "Invalid renderer type! Skip this layer..."
          continue

      # override fieldIndex using layer from config
      tryLegendLabels = False
      attributeIndexes = []
      labelFieldIndex = utils.fieldIndexByName( vProvider, labelFieldName )
      if labelFieldIndex == fieldIndex:
        tryLegendLabels = True
        attributeIndexes.append( fieldIndex )
      else:
        attributeIndexes.append( fieldIndex )
        attributeIndexes.append( labelFieldIndex )

      # unsupported renderer, process next layer
      if rendererType not in [ "categorizedSymbol", "Unique Value", "singleSymbol", "Single Symbol" ]:
        print "Invalid renderer type! Skip this layer..."
        continue

      # prepare to collect information
      overlayFeat = QgsFeature()
      currentFeat = QgsFeature()
      geom = QgsGeometry()

      spatialIndex = utils.createSpatialIndex( vProvider )

      if overlayLayer.selectedFeatureCount() != 0:
        sel = overlayLayer.selectedFeaturesIds()
        overlayProvider.featureAtId( max( sel ), overlayFeat )
      else:
        overlayProvider.featureAtId( overlayProvider.featureCount() - 1, overlayFeat )

      dataArea.clear()
      dataObjects.clear()
      legendCategories = []
      featureClass = None
      category = None

      geom = QgsGeometry( overlayFeat.geometry() )
      if needTransform:
        if geom.transform( crsTransform ) != 0:
          print "Unable transform geometry"
          continue

      dataArea[ "totalArea" ] = float( geom.area() * coef )

      # find intersections in data layer
      intersections = spatialIndex.intersects( geom.boundingBox() )
      for i in intersections:
        vProvider.featureAtId( int( i ), currentFeat, True, attributeIndexes )
        tmpGeom = QgsGeometry( currentFeat.geometry() )
        # precision test for intersection
        if geom.intersects( tmpGeom ):
          # get data for area report
          attrMap = currentFeat.attributeMap()
          if tryLegendLabels:
            featureClass = attrMap[ fieldIndex ].toString()
            if vLayer.isUsingRendererV2():
              if vLayer.rendererV2().type() in [ "categorizedSymbol", "Unique Value" ]:
                category = categories[ renderer.categoryIndexForValue( attrMap.values()[ 0 ] ) ].label()
            else:
              if vLayer.renderer().name() in [ "categorizedSymbol", "Unique Value" ]:
                category = categories[ attrMap.values()[ 0 ].toString() ].label()

            if categories is not None:
              if category.isEmpty():
                category = featureClass
              if category not in legendCategories:
                legendCategories.append( category )
          else:
            if categories is not None:
              category = attrMap[ labelFieldIndex ].toString()
              tmp = attrMap[ fieldIndex ].toString()
              if tmp not in legendCategories:
                legendCategories.append( tmp )

          # count objects
          if categories is not None:
            if category not in dataObjects:
              dataObjects[ category ] = 1
            else:
              dataObjects[ category ] += 1
          else:
            if str(fieldName) not in dataObjects:
              dataObjects[ str(fieldName) ] = 1
            else:
              dataObjects[ str(fieldName) ] += 1

          # calculate intersection area
          intGeom = QgsGeometry( geom.intersection( tmpGeom ) )
          if intGeom.wkbType() == 7:
            intCom = geom.combine( tmpGeom )
            intSym = geom.symDifference( tmpGeom )
            intGeom = QgsGeometry( intCom.difference( intSym ) )

          if categories is not None:
            if category not in dataArea:
              dataArea[ category ] = float( intGeom.area() * coef )
            else:
              dataArea[ category ] += float( intGeom.area() * coef )
          else:
            if str(fieldName) not in dataArea:
              dataArea[ str(fieldName) ] = float( intGeom.area() * coef )
            else:
              dataArea[ str(fieldName) ] += float( intGeom.area() * coef )

      # get extent of the overlay geometry (for reports)
      rect = geom.boundingBox()
      dw = rect.width() * 0.025
      dh = rect.height() * 0.025
      rect.setXMinimum( rect.xMinimum() - dw )
      rect.setXMaximum( rect.xMaximum() + dw )
      rect.setYMinimum( rect.yMinimum() - dh )
      rect.setYMaximum( rect.yMaximum() + dh )

      # create map
      #mapImage = utils.createMapImage( overlayLayer, vLayer, rect, mapCRS, hasOTFR, dataObjects.keys() )
      mapImage = utils.createMapImage( overlayLayer, vLayer, rect, mapCRS, hasOTFR, legendCategories )

      # create all necessary reports
      layerConfig = utils.findLayerInConfig( self.cfgRoot, layerName )

      # add page break after first layer
      if not isFirst:
        writer.addPageBreak()
      isFirst = False

      # print title
      writer.addTitle( layerName )
      writer.addDescription( self.txtComment.toPlainText() + " " + utils.layerComment( layerConfig ) )

      if utils.hasReport( layerConfig, "area" ):
        writer.addAreaTable( fieldName, dataArea )

      if utils.hasReport( layerConfig, "objects" ):
        writer.addObjectsTable( dataObjects )

      # embed image in report if requested
      if self.chkAddMapsToReport.isChecked():
        imgData = QByteArray()
        buff = QBuffer( imgData )
        buff.open( QIODevice.WriteOnly )
        mapImage.save( buff, "png" )
        writer.addThematicImage( layerName, QString.fromLatin1( imgData.toBase64() ) )

      # save separate map if requested
      if self.chkCreateMaps.isChecked():
        mapImage.save( dirName + "/" + layerName + ".png", "png" )

      self.progressBar.setValue( self.progressBar.value() + 1 )
      QCoreApplication.processEvents()

    # save report to files
    writer.closeReport()
    writer.write( self.leOutput.text() )

    # restore UI
    self.progressBar.setFormat( "%p%" )
    self.progressBar.setRange( 0, 1 )
    self.progressBar.setValue( 0 )

    QApplication.restoreOverrideCursor()

    QMessageBox.information( self, self.tr( "Done" ), self.tr( "Completed!" ) )

    self.btnOk.setEnabled( True )
Example #2
0
  def toggleLayer( self, item, column ):
    if self.config:
      if item.checkState( 0 ) == Qt.Checked:
        utils.addLayerToConfig( self.config, self.cfgRoot, item.text( 0 ) )

        layerElement = utils.findLayerInConfig( self.cfgRoot, item.text( 0 ) )

        vLayer = utils.getVectorLayerByName( item.text( 0 ) )
        vProvider = vLayer.dataProvider()

        # check layer renderer and determine classification field
        fieldName = None
        fieldIndex = None

        if vLayer.isUsingRendererV2():
          renderer = vLayer.rendererV2()
          rendererType = renderer.type()

          if rendererType in [ "categorizedSymbol", "Unique Value" ]:
            fieldName = renderer.classAttribute()
            fieldIndex = utils.fieldIndexByName( vProvider, fieldName )
          elif rendererType in [ "singleSymbol", "Single Symbol" ]:
            fieldIndex = 0
            fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          else:
            print "Invalid renderer type! Skip this layer..."
            item.setCheckState( 0, Qt.Unchecked )
            return
        else:
          renderer = vLayer.renderer()
          rendererType = renderer.name()

          if rendererType in [ "categorizedSymbol", "Unique Value" ]:
            fieldIndex = renderer.classificationField()
            fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          elif rendererType in [ "singleSymbol", "Single Symbol" ]:
            fieldIndex = 0
            fieldName = utils.fieldNameByIndex( vProvider, fieldIndex )
          else:
            print "Invalid renderer type! Skip this layer..."
            item.setCheckState( 0, Qt.Unchecked )
            return

        d = layersettingsdialog.LayerSettingsDialog( self, vLayer )

        d.setAreasReport( utils.hasReport( layerElement, "area" ) )
        d.setObjectsReport( utils.hasReport( layerElement, "objects" ) )
        tmp = utils.labelFieldName( layerElement )
        if tmp.isEmpty():
          d.setLabelField( fieldName )
        else:
          d.setLabelField( tmp )

        d.setComment( utils.layerComment( layerElement ) )

        if not d.exec_() == QDialog.Accepted:
          item.setCheckState( 0, Qt.Unchecked )
          return

        # update layer config if necessary
        if d.areasReport():
          utils.addLayerReport( self.config, layerElement, "area" )
        else:
          utils.removeLayerReport( layerElement, "area" )

        if d.objectsReport():
          utils.addLayerReport( self.config, layerElement, "objects" )
        else:
          utils.removeLayerReport( layerElement, "objects" )

        utils.setLabelFieldName( self.config, layerElement, d.getLabelField() )
        utils.setLayerComment( self.config, layerElement, d.getComment() )
      else:
        utils.removeLayerFromConfig( self.cfgRoot, item.text( 0 ) )