void QgsOSMDownloadDialog::onCurrentLayerChanged( int index ) { if ( index < 0 ) return; QString layerId = cboLayers->itemData( index ).toString(); QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !layer ) return; QgsCoordinateReferenceSystem dst( GEOCRS_ID, QgsCoordinateReferenceSystem::InternalCrsId ); QgsCoordinateTransform ct( layer->crs(), dst ); QgsRectangle rect( ct.transformBoundingBox( layer->extent() ) ); if ( rect.isFinite() ) setRect( rect ); else QMessageBox::information( this, tr( "OpenStreetMap download" ), tr( "Could not transform layer extent." ) ); }
void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) { //Lock render method for concurrent threads (e.g. from globe) QMutexLocker renderLock( &mRenderMutex ); //flag to see if the render context has changed //since the last time we rendered. If it hasnt changed we can //take some shortcuts with rendering bool mySameAsLastFlag = true; QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; const QgsCoordinateTransform *ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); // set selection color QgsProject* prj = QgsProject::instance(); int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 ); int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 ); int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 ); int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 ); mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { if ( forceWidthScale ) { scaleFactor = *forceWidthScale; } else { scaleFactor = sceneDpi / 25.4; } } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); mySameAsLastFlag = false; } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; mySameAsLastFlag = false; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( this ); // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) { //clear the cache pixmap if we changed resolution / extent QSettings mySettings; if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { QgsMapLayerRegistry::instance()->clearAllLayerCaches(); } } // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); // Flattened image for drawing when a blending mode is set QImage * mypFlattenedImage = 0; QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" ) .arg( ml->name() ) .arg( ml->minimumScale() ) .arg( ml->maximumScale() ) .arg( ml->hasScaleBasedVisibility() ) .arg( ml->extent().toString() ) .arg( ml->blendMode() ) ); if ( mRenderContext.useAdvancedEffects() ) { // Set the QPainter composition mode so that this layer is rendered using // the desired blending mode mypContextPainter->setCompositionMode( ml->blendMode() ); } if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = transformation( ml ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) ) { ml->setCacheImage( 0 ); } } QSettings mySettings; bool useRenderCaching = false; if ( ! split )//render caching does not yet cater for split extents { if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { useRenderCaching = true; if ( !mySameAsLastFlag || ml->cacheImage() == 0 ) { QgsDebugMsg( "Caching enabled but layer redraw forced by extent change or empty cache" ); QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); if ( mypImage->isNull() ) { QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) ); emit drawError( ml ); painter->end(); // drawError is not caught by anyone, so we end painting to notify caller return; } mypImage->fill( 0 ); ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you QPainter * mypPainter = new QPainter( ml->cacheImage() ); // Changed to enable anti aliasing by default in QGIS 1.7 if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mRenderContext.setPainter( mypPainter ); } else if ( mySameAsLastFlag ) { //draw from cached image QgsDebugMsg( "Caching enabled --- drawing layer from cached image" ); mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); //short circuit as there is nothing else to do... continue; } } } // If we are drawing with an alternative blending mode then we need to render to a separate image // before compositing this on the map. This effectively flattens the layer and prevents // blending occuring between objects on the layer // (this is not required for raster layers or when layer caching is enabled, since that has the same effect) bool flattenedLayer = false; if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if (( !useRenderCaching ) && (( vl->blendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->layerTransparency() != 0 ) ) ) { flattenedLayer = true; mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); if ( mypFlattenedImage->isNull() ) { QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) ); emit drawError( ml ); painter->end(); // drawError is not caught by anyone, so we end painting to notify caller return; } mypFlattenedImage->fill( 0 ); QPainter * mypPainter = new QPainter( mypFlattenedImage ); if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mypPainter->scale( rasterScaleFactor, rasterScaleFactor ); mRenderContext.setPainter( mypPainter ); } } // Per feature blending mode if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) { // set the painter to the feature blend mode, so that features drawn // on this layer will interact and blend with each other mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() ); } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } //apply layer transparency for vector layers if (( mRenderContext.useAdvancedEffects() ) && ( ml->type() == QgsMapLayer::VectorLayer ) ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->layerTransparency() != 0 ) { // a layer transparency has been set, so update the alpha for the flattened layer // by combining it with the layer transparency QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) ); // use destination in composition mode to merge source's alpha with destination mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn ); mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), transparentFillColor ); } } if ( useRenderCaching ) { // composite the cached image into our view and then clean up from caching // by reinstating the painter as it was swapped out for caching renders delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); //draw from cached image that we created further up if ( ml->cacheImage() ) mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); } else if ( flattenedLayer ) { // If we flattened this layer for alternate blend modes, composite it now delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); mypContextPainter->save(); mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) ); mypContextPainter->restore(); delete mypFlattenedImage; mypFlattenedImage = 0; } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); }
void QgsWfsProjectParser::featureTypeList( QDomElement& parentElement, QDomDocument& doc ) const { const QList<QDomElement>& projectLayerElements = mProjectParser->projectLayerElements(); if ( projectLayerElements.size() < 1 ) { return; } QStringList wfsLayersId = mProjectParser->wfsLayers(); QSet<QString> wfstUpdateLayersId = wfstUpdateLayers(); QSet<QString> wfstInsertLayersId = wfstInsertLayers(); QSet<QString> wfstDeleteLayersId = wfstDeleteLayers(); QMap<QString, QgsMapLayer *> layerMap; Q_FOREACH ( const QDomElement &elem, projectLayerElements ) { QString type = elem.attribute( "type" ); if ( type == "vector" ) { QString layerId = mProjectParser->layerId( elem ); if ( !wfsLayersId.contains( layerId ) ) { continue; } QgsMapLayer *layer = mProjectParser->createLayerFromElement( elem ); if ( !layer ) { continue; } #ifdef HAVE_SERVER_PYTHON_PLUGINS if ( !mAccessControl->layerReadPermission( layer ) ) { continue; } #endif QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) ); layerMap.insert( layer->id(), layer ); QDomElement layerElem = doc.createElement( "FeatureType" ); QDomElement nameElem = doc.createElement( "Name" ); //We use the layer name even though it might not be unique. //Because the id sometimes contains user/pw information and the name is more descriptive QString typeName = layer->name(); if ( !layer->shortName().isEmpty() ) typeName = layer->shortName(); typeName = typeName.replace( " ", "_" ); QDomText nameText = doc.createTextNode( typeName ); nameElem.appendChild( nameText ); layerElem.appendChild( nameElem ); QDomElement titleElem = doc.createElement( "Title" ); QString titleName = layer->title(); if ( titleName.isEmpty() ) { titleName = layer->name(); } QDomText titleText = doc.createTextNode( titleName ); titleElem.appendChild( titleText ); layerElem.appendChild( titleElem ); QDomElement abstractElem = doc.createElement( "Abstract" ); QString abstractName = layer->abstract(); if ( abstractName.isEmpty() ) { abstractName = ""; } QDomText abstractText = doc.createTextNode( abstractName ); abstractElem.appendChild( abstractText ); layerElem.appendChild( abstractElem ); //keyword list if ( !layer->keywordList().isEmpty() ) { QDomElement keywordsElem = doc.createElement( "Keywords" ); QDomText keywordsText = doc.createTextNode( layer->keywordList() ); keywordsElem.appendChild( keywordsText ); layerElem.appendChild( keywordsElem ); } //appendExGeographicBoundingBox( layerElem, doc, layer->extent(), layer->crs() ); QDomElement srsElem = doc.createElement( "SRS" ); QDomText srsText = doc.createTextNode( layer->crs().authid() ); srsElem.appendChild( srsText ); layerElem.appendChild( srsElem ); //wfs:Operations element QDomElement operationsElement = doc.createElement( "Operations"/*wfs:Operations*/ ); //wfs:Query element QDomElement queryElement = doc.createElement( "Query"/*wfs:Query*/ ); operationsElement.appendChild( queryElement ); QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer ); QgsVectorDataProvider* provider = vlayer->dataProvider(); if (( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) ) { //wfs:Insert element QDomElement insertElement = doc.createElement( "Insert"/*wfs:Insert*/ ); operationsElement.appendChild( insertElement ); } if (( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) && ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) && wfstUpdateLayersId.contains( layer->id() ) ) { //wfs:Update element QDomElement updateElement = doc.createElement( "Update"/*wfs:Update*/ ); operationsElement.appendChild( updateElement ); } if (( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) ) { //wfs:Delete element QDomElement deleteElement = doc.createElement( "Delete"/*wfs:Delete*/ ); operationsElement.appendChild( deleteElement ); } layerElem.appendChild( operationsElement ); QgsRectangle layerExtent = layer->extent(); QDomElement bBoxElement = doc.createElement( "LatLongBoundingBox" ); bBoxElement.setAttribute( "minx", QString::number( layerExtent.xMinimum() ) ); bBoxElement.setAttribute( "miny", QString::number( layerExtent.yMinimum() ) ); bBoxElement.setAttribute( "maxx", QString::number( layerExtent.xMaximum() ) ); bBoxElement.setAttribute( "maxy", QString::number( layerExtent.yMaximum() ) ); layerElem.appendChild( bBoxElement ); // layer metadata URL QString metadataUrl = layer->metadataUrl(); if ( !metadataUrl.isEmpty() ) { QDomElement metaUrlElem = doc.createElement( "MetadataURL" ); QString metadataUrlType = layer->metadataUrlType(); metaUrlElem.setAttribute( "type", metadataUrlType ); QString metadataUrlFormat = layer->metadataUrlFormat(); if ( metadataUrlFormat == "text/xml" ) { metaUrlElem.setAttribute( "format", "XML" ); } else { metaUrlElem.setAttribute( "format", "TXT" ); } QDomText metaUrlText = doc.createTextNode( metadataUrl ); metaUrlElem.appendChild( metaUrlText ); layerElem.appendChild( metaUrlElem ); } parentElement.appendChild( layerElem ); } }
QDomElement getFeatureTypeListElement( QDomDocument &doc, QgsServerInterface *serverIface, const QgsProject *project ) { QgsAccessControl *accessControl = serverIface->accessControls(); //wfs:FeatureTypeList element QDomElement featureTypeListElement = doc.createElement( QStringLiteral( "FeatureTypeList" )/*wfs:FeatureTypeList*/ ); //wfs:Operations element QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ ); featureTypeListElement.appendChild( operationsElement ); //wfs:Query element QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ ); operationsElement.appendChild( queryElement ); QStringList wfsLayerIds = QgsServerProjectUtils::wfsLayerIds( *project ); QStringList wfstUpdateLayersId = QgsServerProjectUtils::wfstUpdateLayerIds( *project ); QStringList wfstInsertLayersId = QgsServerProjectUtils::wfstInsertLayerIds( *project ); QStringList wfstDeleteLayersId = QgsServerProjectUtils::wfstDeleteLayerIds( *project ); for ( int i = 0; i < wfsLayerIds.size(); ++i ) { QgsMapLayer *layer = project->mapLayer( wfsLayerIds.at( i ) ); if ( layer->type() != QgsMapLayer::LayerType::VectorLayer ) { continue; } if ( accessControl && !accessControl->layerReadPermission( layer ) ) { continue; } QDomElement layerElem = doc.createElement( QStringLiteral( "FeatureType" ) ); //create Name QDomElement nameElem = doc.createElement( QStringLiteral( "Name" ) ); QString typeName = layer->name(); if ( !layer->shortName().isEmpty() ) typeName = layer->shortName(); typeName = typeName.replace( QLatin1String( " " ), QLatin1String( "_" ) ); QDomText nameText = doc.createTextNode( typeName ); nameElem.appendChild( nameText ); layerElem.appendChild( nameElem ); //create Title QDomElement titleElem = doc.createElement( QStringLiteral( "Title" ) ); QString title = layer->title(); if ( title.isEmpty() ) { title = layer->name(); } QDomText titleText = doc.createTextNode( title ); titleElem.appendChild( titleText ); layerElem.appendChild( titleElem ); //create Abstract QString abstract = layer->abstract(); if ( !abstract.isEmpty() ) { QDomElement abstractElem = doc.createElement( QStringLiteral( "Abstract" ) ); QDomText abstractText = doc.createTextNode( abstract ); abstractElem.appendChild( abstractText ); layerElem.appendChild( abstractElem ); } //create keywords QString keywords = layer->keywordList(); if ( !keywords.isEmpty() ) { QDomElement keywordsElem = doc.createElement( QStringLiteral( "Keywords" ) ); QDomText keywordsText = doc.createTextNode( keywords ); keywordsElem.appendChild( keywordsText ); layerElem.appendChild( keywordsElem ); } //create SRS QDomElement srsElem = doc.createElement( QStringLiteral( "SRS" ) ); QDomText srsText = doc.createTextNode( layer->crs().authid() ); srsElem.appendChild( srsText ); layerElem.appendChild( srsElem ); //create LatLongBoundingBox QgsRectangle layerExtent = layer->extent(); QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) ); bBoxElement.setAttribute( QStringLiteral( "minx" ), QString::number( layerExtent.xMinimum() ) ); bBoxElement.setAttribute( QStringLiteral( "miny" ), QString::number( layerExtent.yMinimum() ) ); bBoxElement.setAttribute( QStringLiteral( "maxx" ), QString::number( layerExtent.xMaximum() ) ); bBoxElement.setAttribute( QStringLiteral( "maxy" ), QString::number( layerExtent.yMaximum() ) ); layerElem.appendChild( bBoxElement ); // layer metadata URL QString metadataUrl = layer->metadataUrl(); if ( !metadataUrl.isEmpty() ) { QDomElement metaUrlElem = doc.createElement( QStringLiteral( "MetadataURL" ) ); QString metadataUrlType = layer->metadataUrlType(); metaUrlElem.setAttribute( QStringLiteral( "type" ), metadataUrlType ); QString metadataUrlFormat = layer->metadataUrlFormat(); if ( metadataUrlFormat == QLatin1String( "text/xml" ) ) { metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "XML" ) ); } else { metaUrlElem.setAttribute( QStringLiteral( "format" ), QStringLiteral( "TXT" ) ); } QDomText metaUrlText = doc.createTextNode( metadataUrl ); metaUrlElem.appendChild( metaUrlText ); layerElem.appendChild( metaUrlElem ); } //wfs:Operations element QDomElement operationsElement = doc.createElement( QStringLiteral( "Operations" )/*wfs:Operations*/ ); //wfs:Query element QDomElement queryElement = doc.createElement( QStringLiteral( "Query" )/*wfs:Query*/ ); operationsElement.appendChild( queryElement ); if ( wfstUpdateLayersId.contains( layer->id() ) || wfstInsertLayersId.contains( layer->id() ) || wfstDeleteLayersId.contains( layer->id() ) ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer ); QgsVectorDataProvider *provider = vlayer->dataProvider(); if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) && wfstInsertLayersId.contains( layer->id() ) ) { //wfs:Insert element QDomElement insertElement = doc.createElement( QStringLiteral( "Insert" )/*wfs:Insert*/ ); operationsElement.appendChild( insertElement ); } if ( ( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) && ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) && wfstUpdateLayersId.contains( layer->id() ) ) { //wfs:Update element QDomElement updateElement = doc.createElement( QStringLiteral( "Update" )/*wfs:Update*/ ); operationsElement.appendChild( updateElement ); } if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) && wfstDeleteLayersId.contains( layer->id() ) ) { //wfs:Delete element QDomElement deleteElement = doc.createElement( QStringLiteral( "Delete" )/*wfs:Delete*/ ); operationsElement.appendChild( deleteElement ); } } layerElem.appendChild( operationsElement ); featureTypeListElement.appendChild( layerElem ); } return featureTypeListElement; }
LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine ) { LayerRenderJobs layerJobs; // render all layers in the stack, starting at the base QListIterator<QString> li( mSettings.layers() ); li.toBack(); if ( mCache ) { bool cacheValid = mCache->init( mSettings.visibleExtent(), mSettings.scale() ); QgsDebugMsg( QString( "CACHE VALID: %1" ).arg( cacheValid ) ); Q_UNUSED( cacheValid ); } mGeometryCaches.clear(); while ( li.hasPrevious() ) { QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { mErrors.append( Error( layerId, "Layer not found in registry." ) ); continue; } QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" ) .arg( ml->name() ) .arg( ml->minimumScale() ) .arg( ml->maximumScale() ) .arg( ml->hasScaleBasedVisibility() ) .arg( ml->extent().toString() ) .arg( ml->blendMode() ) ); if ( ml->hasScaleBasedVisibility() && ( mSettings.scale() < ml->minimumScale() || mSettings.scale() > ml->maximumScale() ) ) //|| mOverview ) { QgsDebugMsg( "Layer not rendered because it is not within the defined visibility scale range" ); continue; } QgsRectangle r1 = mSettings.visibleExtent(), r2; const QgsCoordinateTransform* ct = 0; if ( mSettings.hasCrsTransformEnabled() ) { ct = mSettings.layerTransfrom( ml ); if ( ct ) { reprojectToLayerExtent( ct, ml->crs().geographicFlag(), r1, r2 ); } QgsDebugMsg( "extent: " + r1.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) { mErrors.append( Error( layerId, "There was a problem transforming layer's' extent. Layer skipped." ) ); continue; } } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( mCache && ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( labelingEngine && labelingEngine->willUseLayer( vl ) ) ) mCache->clearCacheImage( ml->id() ); } layerJobs.append( LayerRenderJob() ); LayerRenderJob& job = layerJobs.last(); job.cached = false; job.img = 0; job.blendMode = ml->blendMode(); job.layerId = ml->id(); job.context = QgsRenderContext::fromMapSettings( mSettings ); job.context.setPainter( painter ); job.context.setLabelingEngine( labelingEngine ); job.context.setCoordinateTransform( ct ); job.context.setExtent( r1 ); // if we can use the cache, let's do it and avoid rendering! if ( mCache && !mCache->cacheImage( ml->id() ).isNull() ) { job.cached = true; job.img = new QImage( mCache->cacheImage( ml->id() ) ); job.renderer = 0; job.context.setPainter( 0 ); continue; } // If we are drawing with an alternative blending mode then we need to render to a separate image // before compositing this on the map. This effectively flattens the layer and prevents // blending occuring between objects on the layer if ( mCache || !painter || needTemporaryImage( ml ) ) { // Flattened image for drawing when a blending mode is set QImage * mypFlattenedImage = 0; mypFlattenedImage = new QImage( mSettings.outputSize().width(), mSettings.outputSize().height(), mSettings.outputImageFormat() ); if ( mypFlattenedImage->isNull() ) { mErrors.append( Error( layerId, "Insufficient memory for image " + QString::number( mSettings.outputSize().width() ) + "x" + QString::number( mSettings.outputSize().height() ) ) ); delete mypFlattenedImage; layerJobs.removeLast(); continue; } mypFlattenedImage->fill( 0 ); job.img = mypFlattenedImage; QPainter* mypPainter = new QPainter( job.img ); mypPainter->setRenderHint( QPainter::Antialiasing, mSettings.testFlag( QgsMapSettings::Antialiasing ) ); job.context.setPainter( mypPainter ); } job.renderer = ml->createMapRenderer( job.context ); if ( mRequestedGeomCacheForLayers.contains( ml->id() ) ) { if ( QgsVectorLayerRenderer* vlr = dynamic_cast<QgsVectorLayerRenderer*>( job.renderer ) ) { vlr->setGeometryCachePointer( &mGeometryCaches[ ml->id()] ); } } } // while (li.hasPrevious()) return layerJobs; }
QgsRectangle QgsMapSettings::fullExtent() const { QgsDebugMsg( "called." ); QgsMapLayerRegistry* registry = QgsMapLayerRegistry::instance(); // reset the map canvas extent since the extent may now be smaller // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction QgsRectangle fullExtent; fullExtent.setMinimal(); // iterate through the map layers and test each layers extent // against the current min and max values QStringList::const_iterator it = mLayers.begin(); QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayers.count() ) ); while ( it != mLayers.end() ) { QgsMapLayer * lyr = registry->mapLayer( *it ); if ( !lyr ) { QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) ); } else { QgsDebugMsg( "Updating extent using " + lyr->name() ); QgsDebugMsg( "Input extent: " + lyr->extent().toString() ); if ( lyr->extent().isNull() ) { ++it; continue; } // Layer extents are stored in the coordinate system (CS) of the // layer. The extent must be projected to the canvas CS QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() ); QgsDebugMsg( "Output extent: " + extent.toString() ); fullExtent.unionRect( extent ); } ++it; } if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 ) { // If all of the features are at the one point, buffer the // rectangle a bit. If they are all at zero, do something a bit // more crude. if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 && fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 ) { fullExtent.set( -1.0, -1.0, 1.0, 1.0 ); } else { const double padFactor = 1e-8; double widthPad = fullExtent.xMinimum() * padFactor; double heightPad = fullExtent.yMinimum() * padFactor; double xmin = fullExtent.xMinimum() - widthPad; double xmax = fullExtent.xMaximum() + widthPad; double ymin = fullExtent.yMinimum() - heightPad; double ymax = fullExtent.yMaximum() + heightPad; fullExtent.set( xmin, ymin, xmax, ymax ); } } QgsDebugMsg( "Full extent: " + fullExtent.toString() ); return fullExtent; }
void QgsWCSProjectParser::wcsContentMetadata( QDomElement& parentElement, QDomDocument& doc ) const { const QList<QDomElement>& projectLayerElements = mProjectParser.projectLayerElements(); if ( projectLayerElements.size() < 1 ) { return; } QStringList wcsLayersId = wcsLayers(); QMap<QString, QgsMapLayer *> layerMap; foreach ( const QDomElement &elem, projectLayerElements ) { QString type = elem.attribute( "type" ); if ( type == "raster" ) { QgsMapLayer *layer = mProjectParser.createLayerFromElement( elem ); if ( layer && wcsLayersId.contains( layer->id() ) ) { QgsDebugMsg( QString( "add layer %1 to map" ).arg( layer->id() ) ); layerMap.insert( layer->id(), layer ); QDomElement layerElem = doc.createElement( "CoverageOfferingBrief" ); QDomElement nameElem = doc.createElement( "name" ); //We use the layer name even though it might not be unique. //Because the id sometimes contains user/pw information and the name is more descriptive QString typeName = layer->name(); typeName = typeName.replace( " ", "_" ); QDomText nameText = doc.createTextNode( typeName ); nameElem.appendChild( nameText ); layerElem.appendChild( nameElem ); QDomElement labelElem = doc.createElement( "label" ); QString titleName = layer->title(); if ( titleName.isEmpty() ) { titleName = layer->name(); } QDomText labelText = doc.createTextNode( titleName ); labelElem.appendChild( labelText ); layerElem.appendChild( labelElem ); QDomElement descriptionElem = doc.createElement( "description" ); QString abstractName = layer->abstract(); if ( abstractName.isEmpty() ) { abstractName = ""; } QDomText descriptionText = doc.createTextNode( abstractName ); descriptionElem.appendChild( descriptionText ); layerElem.appendChild( descriptionElem ); //lonLatEnvelope const QgsCoordinateReferenceSystem& layerCrs = layer->crs(); QgsCoordinateTransform t( layerCrs, QgsCoordinateReferenceSystem( 4326 ) ); //transform QgsRectangle BBox = t.transformBoundingBox( layer->extent() ); QDomElement lonLatElem = doc.createElement( "lonLatEnvelope" ); lonLatElem.setAttribute( "srsName", "urn:ogc:def:crs:OGC:1.3:CRS84" ); QDomElement lowerPosElem = doc.createElement( "gml:pos" ); QDomText lowerPosText = doc.createTextNode( QString::number( BBox.xMinimum() ) + " " + QString::number( BBox.yMinimum() ) ); lowerPosElem.appendChild( lowerPosText ); lonLatElem.appendChild( lowerPosElem ); QDomElement upperPosElem = doc.createElement( "gml:pos" ); QDomText upperPosText = doc.createTextNode( QString::number( BBox.xMaximum() ) + " " + QString::number( BBox.yMaximum() ) ); upperPosElem.appendChild( upperPosText ); lonLatElem.appendChild( upperPosElem ); layerElem.appendChild( lonLatElem ); parentElement.appendChild( layerElem ); } } }
void QgsMapRenderer::render( QPainter* painter ) { //flag to see if the render context has changed //since the last time we rendered. If it hasnt changed we can //take some shortcuts with rendering bool mySameAsLastFlag = true; QgsDebugMsg( "========== Rendering ==========" ); if ( mExtent.isEmpty() ) { QgsDebugMsg( "empty extent... not rendering" ); return; } if ( mSize.width() == 1 && mSize.height() == 1 ) { QgsDebugMsg( "size 1x1... not rendering" ); return; } QPaintDevice* thePaintDevice = painter->device(); if ( !thePaintDevice ) { return; } // wait if ( mDrawing ) { QgsDebugMsg( "already rendering" ); QCoreApplication::processEvents(); } if ( mDrawing ) { QgsDebugMsg( "still rendering - skipping" ); return; } mDrawing = true; QgsCoordinateTransform* ct; #ifdef QGISDEBUG QgsDebugMsg( "Starting to render layer stack." ); QTime renderTime; renderTime.start(); #endif if ( mOverview ) mRenderContext.setDrawEditingInformation( !mOverview ); mRenderContext.setPainter( painter ); mRenderContext.setCoordinateTransform( 0 ); //this flag is only for stopping during the current rendering progress, //so must be false at every new render operation mRenderContext.setRenderingStopped( false ); //calculate scale factor //use the specified dpi and not those from the paint device //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene) double sceneDpi = mScaleCalculator->dpi(); double scaleFactor = 1.0; if ( mOutputUnits == QgsMapRenderer::Millimeters ) { scaleFactor = sceneDpi / 25.4; } double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi; if ( mRenderContext.rasterScaleFactor() != rasterScaleFactor ) { mRenderContext.setRasterScaleFactor( rasterScaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); mySameAsLastFlag = false; } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); mySameAsLastFlag = false; } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; mySameAsLastFlag = false; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( this ); // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) { //clear the cache pixmap if we changed resolution / extent QSettings mySettings; if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { QgsMapLayerRegistry::instance()->clearAllLayerCaches(); } } QgsOverlayObjectPositionManager* overlayManager = overlayManagerFromSettings(); QList<QgsVectorOverlay*> allOverlayList; //list of all overlays, used to draw them after layers have been rendered // render all layers in the stack, starting at the base QListIterator<QString> li( mLayerSet ); li.toBack(); QgsRectangle r1, r2; while ( li.hasPrevious() ) { if ( mRenderContext.renderingStopped() ) { break; } // Store the painter in case we need to swap it out for the // cache painter QPainter * mypContextPainter = mRenderContext.painter(); QString layerId = li.previous(); QgsDebugMsg( "Rendering at layer item " + layerId ); // This call is supposed to cause the progress bar to // advance. However, it seems that updating the progress bar is // incompatible with having a QPainter active (the one that is // passed into this function), as Qt produces a number of errors // when try to do so. I'm (Gavin) not sure how to fix this, but // added these comments and debug statement to help others... QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" ); //emit drawingProgress(myRenderCounter++, mLayerSet.size()); QgsMapLayer *ml = QgsMapLayerRegistry::instance()->mapLayer( layerId ); if ( !ml ) { QgsDebugMsg( "Layer not found in registry!" ); continue; } QgsDebugMsg( "Rendering layer " + ml->name() ); QgsDebugMsg( " Layer minscale " + QString( "%1" ).arg( ml->minimumScale() ) ); QgsDebugMsg( " Layer maxscale " + QString( "%1" ).arg( ml->maximumScale() ) ); QgsDebugMsg( " Scale dep. visibility enabled? " + QString( "%1" ).arg( ml->hasScaleBasedVisibility() ) ); QgsDebugMsg( " Input extent: " + ml->extent().toString() ); if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) || mOverview ) { connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); // // Now do the call to the layer that actually does // the rendering work! // bool split = false; if ( hasCrsTransformEnabled() ) { r1 = mExtent; split = splitLayersExtent( ml, r1, r2 ); ct = new QgsCoordinateTransform( ml->crs(), *mDestCRS ); mRenderContext.setExtent( r1 ); QgsDebugMsg( " extent 1: " + r1.toString() ); QgsDebugMsg( " extent 2: " + r2.toString() ); if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer { continue; } } else { ct = NULL; } mRenderContext.setCoordinateTransform( ct ); //decide if we have to scale the raster //this is necessary in case QGraphicsScene is used bool scaleRaster = false; QgsMapToPixel rasterMapToPixel; QgsMapToPixel bk_mapToPixel; if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 ) { scaleRaster = true; } //create overlay objects for features within the view extent if ( ml->type() == QgsMapLayer::VectorLayer && overlayManager ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl ) { QList<QgsVectorOverlay*> thisLayerOverlayList; vl->vectorOverlays( thisLayerOverlayList ); QList<QgsVectorOverlay*>::iterator overlayIt = thisLayerOverlayList.begin(); for ( ; overlayIt != thisLayerOverlayList.end(); ++overlayIt ) { if (( *overlayIt )->displayFlag() ) { ( *overlayIt )->createOverlayObjects( mRenderContext ); allOverlayList.push_back( *overlayIt ); } } overlayManager->addLayer( vl, thisLayerOverlayList ); } } // Force render of layers that are being edited // or if there's a labeling engine that needs the layer to register features if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->isEditable() || ( mRenderContext.labelingEngine() && mRenderContext.labelingEngine()->willUseLayer( vl ) ) ) { ml->setCacheImage( 0 ); } } QSettings mySettings; if ( ! split )//render caching does not yet cater for split extents { if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !mySameAsLastFlag || ml->cacheImage() == 0 ) { QgsDebugMsg( "\n\n\nCaching enabled but layer redraw forced by extent change or empty cache\n\n\n" ); QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(), mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 ); mypImage->fill( 0 ); ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you QPainter * mypPainter = new QPainter( ml->cacheImage() ); // Changed to enable anti aliasing by default in QGIS 1.7 if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() ) { mypPainter->setRenderHint( QPainter::Antialiasing ); } mRenderContext.setPainter( mypPainter ); } else if ( mySameAsLastFlag ) { //draw from cached image QgsDebugMsg( "\n\n\nCaching enabled --- drawing layer from cached image\n\n\n" ); mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); //short circuit as there is nothing else to do... continue; } } } if ( scaleRaster ) { bk_mapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel = mRenderContext.mapToPixel(); rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor ); rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor ); mRenderContext.setMapToPixel( rasterMapToPixel ); mRenderContext.painter()->save(); mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor ); } if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } else { QgsDebugMsg( "Layer rendered without issues" ); } if ( split ) { mRenderContext.setExtent( r2 ); if ( !ml->draw( mRenderContext ) ) { emit drawError( ml ); } } if ( scaleRaster ) { mRenderContext.setMapToPixel( bk_mapToPixel ); mRenderContext.painter()->restore(); } if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() ) { if ( !split ) { // composite the cached image into our view and then clean up from caching // by reinstating the painter as it was swapped out for caching renders delete mRenderContext.painter(); mRenderContext.setPainter( mypContextPainter ); //draw from cached image that we created further up mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) ); } } disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) ); } else // layer not visible due to scale {
void QgsProjectParser::addLayers( QDomDocument &doc, QDomElement &parentElem, const QDomElement &legendElem, const QMap<QString, QgsMapLayer *> &layerMap, const QStringList &nonIdentifiableLayers ) const { QDomNodeList legendChildren = legendElem.childNodes(); for ( int i = 0; i < legendChildren.size(); ++i ) { QDomElement currentChildElem = legendChildren.at( i ).toElement(); QDomElement layerElem = doc.createElement( "Layer" ); if ( currentChildElem.tagName() == "legendgroup" ) { layerElem.setAttribute( "queryable", "1" ); QString name = currentChildElem.attribute( "name" ); QDomElement nameElem = doc.createElement( "Name" ); QDomText nameText = doc.createTextNode( name ); nameElem.appendChild( nameText ); layerElem.appendChild( nameElem ); QDomElement titleElem = doc.createElement( "Title" ); QDomText titleText = doc.createTextNode( name ); titleElem.appendChild( titleText ); layerElem.appendChild( titleElem ); if ( currentChildElem.attribute( "embedded" ) == "1" ) { //add layers from other project files and embed into this group QString project = convertToAbsolutePath( currentChildElem.attribute( "project" ) ); QgsDebugMsg( QString( "Project path: %1" ).arg( project ) ); QString embeddedGroupName = currentChildElem.attribute( "name" ); QgsProjectParser* p = dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( project ) ); if ( p ) { QStringList pIdDisabled = p->identifyDisabledLayers(); QDomElement embeddedGroupElem; QList<QDomElement> pLegendElems = p->legendGroupElements(); QList<QDomElement>::const_iterator pLegendIt = pLegendElems.constBegin(); for ( ; pLegendIt != pLegendElems.constEnd(); ++pLegendIt ) { if ( pLegendIt->attribute( "name" ) == embeddedGroupName ) { embeddedGroupElem = *pLegendIt; break; } } QList<QDomElement> pLayerElems = p->projectLayerElements(); QMap<QString, QgsMapLayer *> pLayerMap; QList<QDomElement>::const_iterator pLayerIt = pLayerElems.constBegin(); for ( ; pLayerIt != pLayerElems.constEnd(); ++pLayerIt ) { pLayerMap.insert( layerId( *pLayerIt ), p->createLayerFromElement( *pLayerIt ) ); } p->addLayers( doc, layerElem, embeddedGroupElem, pLayerMap, pIdDisabled ); } } else //normal (not embedded) legend group { addLayers( doc, layerElem, currentChildElem, layerMap, nonIdentifiableLayers ); } // combine bounding boxes of children (groups/layers) combineExtentAndCrsOfGroupChildren( layerElem, doc ); } else if ( currentChildElem.tagName() == "legendlayer" ) { QString id = layerIdFromLegendLayer( currentChildElem ); if ( !layerMap.contains( id ) ) { QgsDebugMsg( QString( "layer %1 not found in map - layer cache to small?" ).arg( id ) ); continue; } QgsMapLayer *currentLayer = layerMap[ id ]; if ( !currentLayer ) { QgsDebugMsg( QString( "layer %1 not found" ).arg( id ) ); continue; } if ( nonIdentifiableLayers.contains( currentLayer->id() ) ) { layerElem.setAttribute( "queryable", "0" ); } else { layerElem.setAttribute( "queryable", "1" ); } QDomElement nameElem = doc.createElement( "Name" ); //We use the layer name even though it might not be unique. //Because the id sometimes contains user/pw information and the name is more descriptive QDomText nameText = doc.createTextNode( currentLayer->name() ); nameElem.appendChild( nameText ); layerElem.appendChild( nameElem ); QDomElement titleElem = doc.createElement( "Title" ); QDomText titleText = doc.createTextNode( currentLayer->name() ); titleElem.appendChild( titleText ); layerElem.appendChild( titleElem ); //CRS QStringList crsList = createCRSListForLayer( currentLayer ); appendCRSElementsToLayer( layerElem, doc, crsList ); //Ex_GeographicBoundingBox appendLayerBoundingBoxes( layerElem, doc, currentLayer->extent(), currentLayer->crs() ); //only one default style in project file mode QDomElement styleElem = doc.createElement( "Style" ); QDomElement styleNameElem = doc.createElement( "Name" ); QDomText styleNameText = doc.createTextNode( "default" ); styleNameElem.appendChild( styleNameText ); QDomElement styleTitleElem = doc.createElement( "Title" ); QDomText styleTitleText = doc.createTextNode( "default" ); styleTitleElem.appendChild( styleTitleText ); styleElem.appendChild( styleNameElem ); styleElem.appendChild( styleTitleElem ); layerElem.appendChild( styleElem ); } else { QgsDebugMsg( "unexpected child element" ); continue; } parentElem.appendChild( layerElem ); } }
QList< layerDef > getWmtsLayerList( QgsServerInterface *serverIface, const QgsProject *project ) { QList< layerDef > wmtsLayers; #ifdef HAVE_SERVER_PYTHON_PLUGINS QgsAccessControl *accessControl = serverIface->accessControls(); #else ( void )serverIface; #endif // WMTS Project configuration bool wmtsProject = project->readBoolEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Project" ) ); // Root Layer name QString rootLayerName = QgsServerProjectUtils::wmsRootName( *project ); if ( rootLayerName.isEmpty() && !project->title().isEmpty() ) { rootLayerName = project->title(); } if ( wmtsProject && !rootLayerName.isEmpty() ) { layerDef pLayer; pLayer.id = rootLayerName; if ( !project->title().isEmpty() ) { pLayer.title = project->title(); pLayer.abstract = project->title(); } //transform the project native CRS into WGS84 QgsRectangle projRect = QgsServerProjectUtils::wmsExtent( *project ); QgsCoordinateReferenceSystem projCrs = project->crs(); QgsCoordinateTransform exGeoTransform( projCrs, wgs84, project ); try { pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( projRect ); } catch ( const QgsCsException & ) { pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 ); } // Formats bool wmtsPngProject = project->readBoolEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Project" ) ); if ( wmtsPngProject ) pLayer.formats << QStringLiteral( "image/png" ); bool wmtsJpegProject = project->readBoolEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Project" ) ); if ( wmtsJpegProject ) pLayer.formats << QStringLiteral( "image/jpeg" ); // Project is not queryable in WMS //pLayer.queryable = ( nonIdentifiableLayers.count() != project->count() ); pLayer.queryable = false; wmtsLayers.append( pLayer ); } QStringList wmtsGroupNameList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Group" ) ); if ( !wmtsGroupNameList.isEmpty() ) { QgsLayerTreeGroup *treeRoot = project->layerTreeRoot(); QStringList wmtsPngGroupNameList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Group" ) ); QStringList wmtsJpegGroupNameList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Group" ) ); for ( const QString &gName : wmtsGroupNameList ) { QgsLayerTreeGroup *treeGroup = treeRoot->findGroup( gName ); if ( !treeGroup ) { continue; } layerDef pLayer; pLayer.id = treeGroup->customProperty( QStringLiteral( "wmsShortName" ) ).toString(); if ( pLayer.id.isEmpty() ) pLayer.id = gName; pLayer.title = treeGroup->customProperty( QStringLiteral( "wmsTitle" ) ).toString(); if ( pLayer.title.isEmpty() ) pLayer.title = gName; pLayer.abstract = treeGroup->customProperty( QStringLiteral( "wmsAbstract" ) ).toString(); QgsRectangle wgs84BoundingRect; bool queryable = false; double maxScale = 0.0; double minScale = 0.0; for ( QgsLayerTreeLayer *layer : treeGroup->findLayers() ) { QgsMapLayer *l = layer->layer(); if ( !l ) { continue; } //transform the layer native CRS into WGS84 QgsCoordinateReferenceSystem layerCrs = l->crs(); QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project ); try { wgs84BoundingRect.combineExtentWith( exGeoTransform.transformBoundingBox( l->extent() ) ); } catch ( const QgsCsException & ) { wgs84BoundingRect.combineExtentWith( QgsRectangle( -180, -90, 180, 90 ) ); } if ( !queryable && l->flags().testFlag( QgsMapLayer::Identifiable ) ) { queryable = true; } if ( l->hasScaleBasedVisibility() ) { double lMaxScale = l->maximumScale(); if ( lMaxScale > 0.0 && lMaxScale > maxScale ) { maxScale = lMaxScale; } double lMinScale = l->minimumScale(); if ( lMinScale > 0.0 && ( minScale == 0.0 || lMinScale < minScale ) ) { minScale = lMinScale; } } } pLayer.wgs84BoundingRect = wgs84BoundingRect; pLayer.queryable = queryable; pLayer.maxScale = maxScale; pLayer.minScale = minScale; // Formats if ( wmtsPngGroupNameList.contains( gName ) ) pLayer.formats << QStringLiteral( "image/png" ); if ( wmtsJpegGroupNameList.contains( gName ) ) pLayer.formats << QStringLiteral( "image/jpeg" ); wmtsLayers.append( pLayer ); } } QStringList wmtsLayerIdList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Layer" ) ); QStringList wmtsPngLayerIdList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Layer" ) ); QStringList wmtsJpegLayerIdList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Layer" ) ); for ( const QString &lId : wmtsLayerIdList ) { QgsMapLayer *l = project->mapLayer( lId ); if ( !l ) { continue; } #ifdef HAVE_SERVER_PYTHON_PLUGINS if ( !accessControl->layerReadPermission( l ) ) { continue; } #endif layerDef pLayer; pLayer.id = l->name(); if ( !l->shortName().isEmpty() ) pLayer.id = l->shortName(); pLayer.id = pLayer.id.replace( ' ', '_' ); pLayer.title = l->title(); pLayer.abstract = l->abstract(); //transform the layer native CRS into WGS84 QgsCoordinateReferenceSystem layerCrs = l->crs(); QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project ); try { pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( l->extent() ); } catch ( const QgsCsException & ) { pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 ); } // Formats if ( wmtsPngLayerIdList.contains( lId ) ) pLayer.formats << QStringLiteral( "image/png" ); if ( wmtsJpegLayerIdList.contains( lId ) ) pLayer.formats << QStringLiteral( "image/jpeg" ); pLayer.queryable = ( l->flags().testFlag( QgsMapLayer::Identifiable ) ); if ( l->hasScaleBasedVisibility() ) { pLayer.maxScale = l->maximumScale(); pLayer.minScale = l->minimumScale(); } else { pLayer.maxScale = 0.0; pLayer.minScale = 0.0; } wmtsLayers.append( pLayer ); } return wmtsLayers; }
void QgsSLDConfigParser::layersAndStylesCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& version, bool fullProjectSettings ) const { Q_UNUSED( version ); Q_UNUSED( fullProjectSettings ); //iterate over all <UserLayer> nodes if ( mXMLDoc ) { QDomNode sldNode = mXMLDoc->documentElement(); if ( !sldNode.isNull() ) { //create wgs84 to reproject the layer bounding boxes //QgsCoordinateReferenceSystem wgs84; //wgs84.createFromEpsg(4326); QDomNodeList layerNodeList = sldNode.toElement().elementsByTagName( QStringLiteral( "UserLayer" ) ); for ( int i = 0; i < layerNodeList.size(); ++i ) { QDomElement layerElement = doc.createElement( QStringLiteral( "Layer" ) ); layerElement.setAttribute( QStringLiteral( "queryable" ), QStringLiteral( "1" ) ); //support GetFeatureInfo for all layers parentElement.appendChild( layerElement ); //add name QDomNodeList nameList = layerNodeList.item( i ).toElement().elementsByTagName( QStringLiteral( "Name" ) ); if ( !nameList.isEmpty() ) { //layer name QDomElement layerNameElement = doc.createElement( QStringLiteral( "Name" ) ); QDomText layerNameText = doc.createTextNode( nameList.item( 0 ).toElement().text() ); layerNameElement.appendChild( layerNameText ); layerElement.appendChild( layerNameElement ); } //add title QDomNodeList titleList = layerNodeList.item( i ).toElement().elementsByTagName( QStringLiteral( "Title" ) ); if ( !titleList.isEmpty() ) { QDomElement layerTitleElement = doc.createElement( QStringLiteral( "Title" ) ); QDomText layerTitleText = doc.createTextNode( titleList.item( 0 ).toElement().text() ); layerTitleElement.appendChild( layerTitleText ); layerElement.appendChild( layerTitleElement ); } //add abstract QDomNodeList abstractList = layerNodeList.item( i ).toElement().elementsByTagName( QStringLiteral( "Abstract" ) ); if ( !abstractList.isEmpty() ) { QDomElement layerAbstractElement = doc.createElement( QStringLiteral( "Abstract" ) ); QDomText layerAbstractText = doc.createTextNode( abstractList.item( 0 ).toElement().text() ); layerAbstractElement.appendChild( layerAbstractText ); layerElement.appendChild( layerAbstractElement ); } //get QgsMapLayer object to add Ex_GeographicalBoundingBox, Bounding Box QList<QgsMapLayer*> layerList = mapLayerFromStyle( nameList.item( 0 ).toElement().text(), QLatin1String( "" ) ); if ( layerList.size() < 1 )//error while generating the layer { QgsDebugMsg( "Error, no maplayer in layer list" ); continue; } //get only the first layer since we don't want to have the other ones in the capabilities document QgsMapLayer* theMapLayer = layerList.at( 0 ); if ( !theMapLayer )//error while generating the layer { QgsDebugMsg( "Error, QgsMapLayer object is 0" ); continue; } //append geographic bbox and the CRS elements QStringList crsNumbers = QgsConfigParserUtils::createCrsListForLayer( theMapLayer ); QStringList crsRestriction; //no crs restrictions in SLD parser QgsConfigParserUtils::appendCrsElementsToLayer( layerElement, doc, crsNumbers, crsRestriction ); QgsConfigParserUtils::appendLayerBoundingBoxes( layerElement, doc, theMapLayer->extent(), theMapLayer->crs(), crsNumbers, crsRestriction ); //iterate over all <UserStyle> nodes within a user layer QDomNodeList userStyleList = layerNodeList.item( i ).toElement().elementsByTagName( QStringLiteral( "UserStyle" ) ); for ( int j = 0; j < userStyleList.size(); ++j ) { QDomElement styleElement = doc.createElement( QStringLiteral( "Style" ) ); layerElement.appendChild( styleElement ); //Name QDomNodeList nameList = userStyleList.item( j ).toElement().elementsByTagName( QStringLiteral( "Name" ) ); if ( !nameList.isEmpty() ) { QDomElement styleNameElement = doc.createElement( QStringLiteral( "Name" ) ); QDomText styleNameText = doc.createTextNode( nameList.item( 0 ).toElement().text() ); styleNameElement.appendChild( styleNameText ); styleElement.appendChild( styleNameElement ); QDomElement styleTitleElement = doc.createElement( QStringLiteral( "Title" ) ); QDomText styleTitleText = doc.createTextNode( nameList.item( 0 ).toElement().text() ); styleTitleElement.appendChild( styleTitleText ); styleElement.appendChild( styleTitleElement ); } //Title QDomNodeList titleList = userStyleList.item( j ).toElement().elementsByTagName( QStringLiteral( "Title" ) ); if ( !titleList.isEmpty() ) { QDomElement styleTitleElement = doc.createElement( QStringLiteral( "Title" ) ); QDomText styleTitleText = doc.createTextNode( titleList.item( 0 ).toElement().text() ); styleTitleElement.appendChild( styleTitleText ); styleElement.appendChild( styleTitleElement ); } //Abstract QDomNodeList abstractList = userStyleList.item( j ).toElement().elementsByTagName( QStringLiteral( "Abstract" ) ); if ( !abstractList.isEmpty() ) { QDomElement styleAbstractElement = doc.createElement( QStringLiteral( "Abstract" ) ); QDomText styleAbstractText = doc.createTextNode( abstractList.item( 0 ).toElement().text() ); styleAbstractElement.appendChild( styleAbstractText ); styleElement.appendChild( styleAbstractElement ); } } } } } }