RgExportDlg::RgExportDlg( QWidget* parent, Qt::WFlags fl ) : QDialog( parent, fl ) { // create base widgets; setWindowTitle( tr( "Export feature" ) ); QVBoxLayout *v = new QVBoxLayout( this ); QHBoxLayout *h = new QHBoxLayout(); QLabel *l = new QLabel( tr( "Select destination layer" ), this ); h->addWidget( l ); mcbLayers = new QComboBox( this ); h->addWidget( mcbLayers ); v->addLayout( h ); QDialogButtonBox *bb = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this ); connect( bb, SIGNAL( accepted() ), this, SLOT( on_buttonBox_accepted() ) ); connect( bb, SIGNAL( rejected() ), this, SLOT( on_buttonBox_rejected() ) ); v->addWidget( bb ); //fill list of layers mcbLayers->insertItem( 0, tr( "New temporary layer" ), QVariant( "-1" ) ); QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); QMap<QString, QgsMapLayer*>::iterator layer_it = mapLayers.begin(); for ( ; layer_it != mapLayers.end(); ++layer_it ) { QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer_it.value() ); if ( !vl ) continue; if ( vl->geometryType() != QGis::Line ) continue; mcbLayers->insertItem( 0, vl->name(), QVariant( vl->id() ) ); } } // RgSettingsDlg::RgSettingsDlg()
void QgsComposerAttributeTableWidget::changeLayer( QgsMapLayer *layer ) { if ( !mComposerTable ) { return; } QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer ); if ( !vl ) { return; } QgsComposition* composition = mComposerTable->composition(); if ( composition ) { composition->beginMultiFrameCommand( mComposerTable, tr( "Table layer changed" ) ); } mComposerTable->setVectorLayer( vl ); mComposerTable->update(); if ( composition ) { composition->endMultiFrameCommand(); } if ( vl->geometryType() == QGis::NoGeometry ) { //layer has no geometry, so uncheck & disable controls which require geometry mShowOnlyVisibleFeaturesCheckBox->setChecked( false ); mShowOnlyVisibleFeaturesCheckBox->setEnabled( false ); } else { mShowOnlyVisibleFeaturesCheckBox->setEnabled( true ); } }
void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo ) { //memory cache not required or already done if ( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 ) { return; } QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) ); if ( cacheLayer ) { int joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName ); joinInfo.cachedAttributes.clear(); QgsFeatureIterator fit = cacheLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) ); QgsFeature f; while ( fit.nextFeature( f ) ) { const QgsAttributes& attrs = f.attributes(); joinInfo.cachedAttributes.insert( attrs[joinFieldIndex].toString(), attrs ); } } }
void QgsComposerAttributeTableV2::resetColumns() { QgsVectorLayer* source = sourceLayer(); if ( !source ) { return; } //remove existing columns qDeleteAll( mColumns ); mColumns.clear(); //rebuild columns list from vector layer fields int idx = 0; Q_FOREACH ( const QgsField& field, source->fields() ) { QString currentAlias = source->attributeDisplayName( idx ); QgsComposerTableColumn* col = new QgsComposerTableColumn; col->setAttribute( field.name() ); col->setHeading( currentAlias ); mColumns.append( col ); idx++; } }
void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QDomDocument& doc, QgsMapLayer* currentLayer ) const { if ( !currentLayer ) { return; } if ( currentLayer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( currentLayer ); const QSet<QString>& excludedAttributes = vLayer->excludeAttributesWMS(); QString displayField = vLayer->displayField(); //attributes QDomElement attributesElem = doc.createElement( "Attributes" ); const QgsFields& layerFields = vLayer->pendingFields(); for ( int idx = 0; idx < layerFields.count(); ++idx ) { const QgsField& field = layerFields[idx]; if ( excludedAttributes.contains( field.name() ) ) { continue; } // field alias in case of displayField if ( field.name() == displayField ) { displayField = vLayer->attributeDisplayName( idx ); } QDomElement attributeElem = doc.createElement( "Attribute" ); attributeElem.setAttribute( "name", field.name() ); attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) ); attributeElem.setAttribute( "typeName", field.typeName() ); QString alias = vLayer->attributeAlias( idx ); if ( !alias.isEmpty() ) { attributeElem.setAttribute( "alias", alias ); } //edit type to text attributeElem.setAttribute( "editType", vLayer->editorWidgetV2( idx ) ); attributeElem.setAttribute( "comment", field.comment() ); attributeElem.setAttribute( "length", field.length() ); attributeElem.setAttribute( "precision", field.precision() ); attributesElem.appendChild( attributeElem ); } //displayfield layerElem.setAttribute( "displayField", displayField ); layerElem.appendChild( attributesElem ); } }
int QgsSymbol::readFieldName( QDomNode &synode, QString name, const QgsVectorLayer &vl ) { QDomNode node = synode.namedItem( name + "name" ); if ( !node.isNull() ) { const QgsFieldMap &fields = vl.pendingFields(); QString name = node.toElement().text(); for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); it++ ) if ( it->name() == name ) return it.key(); return -1; } node = synode.namedItem( name ); return node.isNull() ? -1 : node.toElement().text().toInt(); }
void QgsSymbolLegendNode::toggleAllItems() { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayerNode->layer() ); if ( !vlayer || !vlayer->renderer() ) return; const QgsLegendSymbolList symbolList = vlayer->renderer()->legendSymbolItems(); for ( const auto &item : symbolList ) { vlayer->renderer()->checkLegendSymbolItem( item.ruleKey(), ! vlayer->renderer()->legendSymbolItemChecked( item.ruleKey() ) ); } emit dataChanged(); vlayer->triggerRepaint(); }
bool QgsMapLayerProxyModel::filterAcceptsRow( int source_row, const QModelIndex &source_parent ) const { if ( mFilters.testFlag( All ) && mExceptList.isEmpty() ) return true; QModelIndex index = sourceModel()->index( source_row, 0, source_parent ); QgsMapLayer* layer = static_cast<QgsMapLayer*>( index.internalPointer() ); if ( !layer ) return false; if ( mExceptList.contains( layer ) ) return false; // layer type if (( mFilters.testFlag( RasterLayer ) && layer->type() == QgsMapLayer::RasterLayer ) || ( mFilters.testFlag( VectorLayer ) && layer->type() == QgsMapLayer::VectorLayer ) || ( mFilters.testFlag( PluginLayer ) && layer->type() == QgsMapLayer::PluginLayer ) ) return true; // geometry type bool detectGeometry = mFilters.testFlag( NoGeometry ) || mFilters.testFlag( PointLayer ) || mFilters.testFlag( LineLayer ) || mFilters.testFlag( PolygonLayer ) || mFilters.testFlag( HasGeometry ); if ( detectGeometry && layer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer ); if ( vl ) { if ( mFilters.testFlag( HasGeometry ) && vl->hasGeometryType() ) return true; if ( mFilters.testFlag( NoGeometry ) && vl->geometryType() == QGis::NoGeometry ) return true; if ( mFilters.testFlag( PointLayer ) && vl->geometryType() == QGis::Point ) return true; if ( mFilters.testFlag( LineLayer ) && vl->geometryType() == QGis::Line ) return true; if ( mFilters.testFlag( PolygonLayer ) && vl->geometryType() == QGis::Polygon ) return true; } } return false; }
int QgsMapToolCapture::fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); QgsVectorLayer *sourceLayer = match.layer(); if ( match.isValid() && match.hasVertex() && sourceLayer && ( sourceLayer->crs() == vlayer->crs() ) ) { QgsFeature f; QgsFeatureRequest request; request.setFilterFid( match.featureId() ); bool fetched = match.layer()->getFeatures( request ).nextFeature( f ); if ( fetched ) { QgsVertexId vId; if ( !f.geometry().vertexIdFromVertexNr( match.vertexIndex(), vId ) ) return 2; layerPoint = f.geometry().constGet()->vertexAt( vId ); // ZM support depends on the target layer if ( !QgsWkbTypes::hasZ( vlayer->wkbType() ) ) { layerPoint.dropZValue(); } if ( !QgsWkbTypes::hasM( vlayer->wkbType() ) ) { layerPoint.dropMValue(); } return 0; } else { return 2; } } else { return 1; } }
bool QgsMapToolLabel::createAuxiliaryFields( LabelDetails &details, QgsPalIndexes &indexes ) const { bool newAuxiliaryLayer = false; QgsVectorLayer *vlayer = details.layer; QString providerId = details.pos.providerID; if ( !vlayer || !vlayer->labelsEnabled() ) return false; if ( !vlayer->auxiliaryLayer() ) { QgsNewAuxiliaryLayerDialog dlg( vlayer ); dlg.exec(); newAuxiliaryLayer = true; } if ( !vlayer->auxiliaryLayer() ) return false; for ( const QgsPalLayerSettings::Property &p : qgis::as_const( mPalProperties ) ) { int index = -1; // always use the default activated property QgsProperty prop = details.settings.dataDefinedProperties().property( p ); if ( prop.propertyType() == QgsProperty::FieldBasedProperty && prop.isActive() ) { index = vlayer->fields().lookupField( prop.field() ); } else { index = QgsAuxiliaryLayer::createProperty( p, vlayer ); } indexes[p] = index; } details.settings = vlayer->labeling()->settings( providerId ); return newAuxiliaryLayer; }
bool QgsMapRendererJob::needTemporaryImage( QgsMapLayer* ml ) { if ( ml->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml ); if ( vl->rendererV2() && vl->rendererV2()->forceRasterRender() ) { //raster rendering is forced for this layer return true; } if ( mSettings.testFlag( QgsMapSettings::UseAdvancedEffects ) && (( vl->blendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver ) || ( vl->layerTransparency() != 0 ) ) ) { //layer properties require rasterisation return true; } } return false; }
void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QDomDocument& doc, QgsMapLayer* currentLayer ) const { if ( !currentLayer ) { return; } // Layer tree name QDomElement treeNameElem = doc.createElement( "TreeName" ); QDomText treeNameText = doc.createTextNode( currentLayer->name() ); treeNameElem.appendChild( treeNameText ); layerElem.appendChild( treeNameElem ); if ( currentLayer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( currentLayer ); const QSet<QString>& excludedAttributes = vLayer->excludeAttributesWms(); int displayFieldIdx = -1; QString displayField = "maptip"; QgsExpression exp( vLayer->displayExpression() ); if ( exp.isField() ) { displayField = static_cast<const QgsExpression::NodeColumnRef*>( exp.rootNode() )->name(); displayFieldIdx = vLayer->fieldNameIndex( displayField ); } //attributes QDomElement attributesElem = doc.createElement( "Attributes" ); const QgsFields& layerFields = vLayer->pendingFields(); for ( int idx = 0; idx < layerFields.count(); ++idx ) { QgsField field = layerFields.at( idx ); if ( excludedAttributes.contains( field.name() ) ) { continue; } // field alias in case of displayField if ( idx == displayFieldIdx ) { displayField = vLayer->attributeDisplayName( idx ); } QDomElement attributeElem = doc.createElement( "Attribute" ); attributeElem.setAttribute( "name", field.name() ); attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) ); attributeElem.setAttribute( "typeName", field.typeName() ); QString alias = vLayer->attributeAlias( idx ); if ( !alias.isEmpty() ) { attributeElem.setAttribute( "alias", alias ); } //edit type to text attributeElem.setAttribute( "editType", vLayer->editFormConfig()->widgetType( idx ) ); attributeElem.setAttribute( "comment", field.comment() ); attributeElem.setAttribute( "length", field.length() ); attributeElem.setAttribute( "precision", field.precision() ); attributesElem.appendChild( attributeElem ); } //displayfield layerElem.setAttribute( "displayField", displayField ); //geometry type layerElem.setAttribute( "geometryType", QgsWkbTypes::displayString( vLayer->wkbType() ) ); layerElem.appendChild( attributesElem ); } }
void QgsQuickPrint::scalePointSymbols( int theScaleFactor, SymbolScalingType theDirection ) { if ( 0 >= theScaleFactor ) { QgsDebugMsg( "invalid scale factor" ); return; } QStringList myLayerSet = mpMapRenderer->layerSet(); QStringListIterator myLayerIterator( myLayerSet ); while ( myLayerIterator.hasNext() ) { QString myLayerId = myLayerIterator.next(); QgsDebugMsg( "Scaling point symbols for print for " + myLayerId ); QgsMapLayer * mypLayer = QgsMapLayerRegistry::instance()->mapLayer( myLayerId ); if ( mypLayer ) { QgsVectorLayer *mypVectorLayer = qobject_cast<QgsVectorLayer *>( mypLayer ); if ( mypVectorLayer ) { const QgsRenderer* mypRenderer = mypVectorLayer->renderer(); const QList<QgsSymbol*> mySymbolList = mypRenderer->symbols(); // // Single symbol // if ( 1 == mySymbolList.size() ) { QgsSymbol * mypSymbol = mySymbolList.at( 0 ); if ( mypSymbol->type() == QGis::Point ) { if ( theDirection == ScaleUp ) { mypSymbol->setPointSize( mypSymbol->pointSize() * theScaleFactor ); } else //Scale Down { mypSymbol->setPointSize( mypSymbol->pointSize() / theScaleFactor ); } } } else //class breaks { QListIterator<QgsSymbol *> myIterator( mySymbolList ); while ( myIterator.hasNext() ) { QgsSymbol * mypSymbol = myIterator.next(); if ( mypSymbol->type() == QGis::Point ) { if ( theDirection == ScaleUp ) { mypSymbol->setPointSize( mypSymbol->pointSize() * theScaleFactor ); } else //Scale Down { mypSymbol->setPointSize( mypSymbol->pointSize() / theScaleFactor ); } } } //symbol loop } //class breaks } //if vectorlayer } //if maplayer } //layer iterator }
void QgsQuickPrint::printMap() { if ( mOutputFileName.isEmpty() ) { return; } if ( mpMapRenderer == NULL ) { return; } //ensure the user never omitted the extension from the file name if ( !mOutputFileName.toUpper().endsWith( ".PDF" ) ) { mOutputFileName += ".pdf"; } // Initialising the printer this way lets us find out what // the screen resolution is which we store and then // reset the resolution of the printer after that... QPrinter myPrinter( QPrinter::ScreenResolution ); // Try to force the printer resolution to 300dpi // to get past platform specific defaults in printer // resolution... // int myPrintResolutionDpi = 300; myPrinter.setResolution( myPrintResolutionDpi ); myPrinter.setOutputFormat( QPrinter::PdfFormat ); QgsDebugMsg( QString( "Printing to page size %1" ).arg( pageSizeToString( mPageSize ) ) ); myPrinter.setPageSize( mPageSize ); myPrinter.setOutputFileName( mOutputFileName ); myPrinter.setOrientation( QPrinter::Landscape ); myPrinter.setDocName( "quickprint Report" ); QPainter myPrintPainter( &myPrinter ); myPrintPainter.setPen( Qt::gray ); myPrintPainter.setBrush( Qt::white ); // This is what we are aiming for: // a // +-(1)------ Acme Maps (2) --------------------------------------+ // |b 12/01/2007 (3) | // | Earthquakes (4) | // | +--(5)--------------------------------------------------------+ | // | |c | | // | | +-(6)---------------------------------------+ +~(7)~~~~~~+ | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | | | | | | | // | | +-------------------------------------------+ +~~~~~~~~~~+ | | // | | | | // | +-------------------------------------------------------------+ | // | | // | +-(8)-----+ +-(9-)----+ +-(10)----+ /|\ | // | | | |Copyright| | | / | \ | // | | | | 2008 | | | |(11) | // | +---------+ +---------+ +---------+ | // | +~(12)~~~~~~+ | // +-----------------------------------------------------------------+ // // 1) PageBorder 8) Logo1 // 2) PageTitle 9) CopyrightText // 3) MapDate 10) Logo2 // 4) MapTitle 11) NorthArrow // 5) MapFrame 12) ScaleBar // 6) MapPixmap // 7) LegendPixmap // a OriginXY // b HorizontalSpacing // c VerticalSpacing // // Note: Different operating systems will use different // page resolutions for QPrinter::HighResolution so I'm // working all coordinates out as percentages of page // size so that we can hopefully get comarable print // results on all platforms. // // // Note #2: Im defining all measurements here as my plan // is to later support templates with different page // layouts and paper sizes etc. // //set the top left origin for the print layout int myOriginX = myPrinter.pageRect().left(); int myOriginY = myPrinter.pageRect().top(); int myDrawableWidth = myPrinter.pageRect().width() - myOriginX; int myDrawableHeight = myPrinter.pageRect().height() - myOriginY; //define the spacing between layout elements int myHorizontalSpacing = myDrawableWidth / 100; // 1% int myVerticalSpacing = myDrawableHeight / 100; // 1% //define the proportions for the page layout int myMapWidthPercent = 65; int myMapHeightPercent = 71; int myLegendWidthPercent = 25; int myLegendHeightPercent = 65; int myLogoWidthPercent = 23; int myLogoHeightPercent = 17; // // Remember the size and dpi of the maprender // so we can restore it properly // int myOriginalDpi = mpMapRenderer->outputDpi(); //sensible default to prevent divide by zero if ( 0 == myOriginalDpi ) myOriginalDpi = 96; QSize myOriginalSize = mpMapRenderer->outputSize(); //define the font sizes and family int myMapTitleFontSize = 24; int myMapDateFontSize = 16; int myMapNameFontSize = 32; int myLegendFontSize = 12; #ifdef Q_OS_LINUX//this sucks... myLegendFontSize -= 2; #endif #ifdef WIN32 //this sucks too... myMapTitleFontSize /= 2; myMapDateFontSize /= 2; myMapNameFontSize /= 2; myLegendFontSize /= 2; #endif QString myFontFamily = "Arial"; // // Draw the PageBorder // myPrintPainter.drawRect( myOriginX, myOriginY, myDrawableWidth, myDrawableHeight ); // // Draw the PageTitle // QFont myTitleFont( myFontFamily, myMapTitleFontSize ); myPrintPainter.setFont( myTitleFont ); QFontMetrics myTitleMetrics( myTitleFont, &myPrinter ); int myPageTitleHeight = myTitleMetrics.height(); int myPageTitleWidth = myTitleMetrics.width( mTitleText ); myOriginX += myHorizontalSpacing; myOriginY -= ( myPageTitleHeight / 2 ); QRect myPageTitleRect( myOriginX, myOriginY, myPageTitleWidth, myPageTitleHeight ); // make sure the title goes onto a white background myPrintPainter.setPen( Qt::white ); myPrintPainter.drawRect( myPageTitleRect ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawText( myPageTitleRect, Qt::AlignCenter, mTitleText ); // // Draw the MapDate // QFont myDateFont( myFontFamily, myMapDateFontSize ); QString myDateText( QDate::currentDate().toString( Qt::LocalDate ) ); myPrintPainter.setFont( myDateFont ); QFontMetrics myDateMetrics( myDateFont, &myPrinter ); int myDateHeight = myDateMetrics.height(); //int myDateWidth = myDateMetrics.width(myDateText); myOriginX += myHorizontalSpacing; myOriginY += myPageTitleHeight + myVerticalSpacing ; QRect myDateRect( myOriginX, myOriginY, myPageTitleWidth, //use same width as page title for centering myDateHeight ); // make sure the title goes onto a white background myPrintPainter.setPen( Qt::white ); myPrintPainter.drawRect( myDateRect ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawText( myDateRect, Qt::AlignCenter, myDateText ); // // Draw the MapName // QFont myNameFont( myFontFamily, myMapNameFontSize ); myPrintPainter.setFont( myNameFont ); QFontMetrics myNameMetrics( myNameFont, &myPrinter ); int myNameHeight = myNameMetrics.height(); int myNameWidth = myNameMetrics.width( mNameText ); myOriginX = myPrinter.pageRect().left() + myDrawableWidth / 2; //page center myOriginX -= myNameWidth / 2; myOriginY = myPrinter.pageRect().top() + ( myPageTitleHeight / 2 ) + myVerticalSpacing ; QRect myNameRect( myOriginX, myOriginY, myNameWidth, myNameHeight ); // make sure the title goes onto a white background myPrintPainter.setPen( Qt::white ); myPrintPainter.drawRect( myNameRect ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawText( myNameRect, Qt::AlignCenter, mNameText ); // // Draw the MapFrame (top) // int myMapFrameWidth = myDrawableWidth ; myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing; myOriginY += myNameHeight + myVerticalSpacing; QLine myMapFrameTopLine( myOriginX, myOriginY, myMapFrameWidth, myOriginY ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawLine( myMapFrameTopLine ); // Draw the map onto a pixmap // @TODO: we need to save teh extent of the screen map and // then set them again for the print map so that the map scales // properly in the print int myMapDimensionX = ( myDrawableWidth / 100 ) * myMapHeightPercent; int myMapDimensionY = ( myDrawableHeight / 100 ) * myMapWidthPercent; QImage myMapImage( QSize( myMapDimensionX, myMapDimensionY ), QImage::Format_ARGB32 ); myMapImage.setDotsPerMeterX(( double )( myPrinter.logicalDpiX() ) / 25.4 * 1000.0 ); myMapImage.setDotsPerMeterY(( double )( myPrinter.logicalDpiY() ) / 25.4 * 1000.0 ); myMapImage.fill( 0 ); QPainter myMapPainter; myMapPainter.begin( &myMapImage ); // Now resize for print mpMapRenderer->setOutputSize( QSize( myMapDimensionX, myMapDimensionY ), ( myPrinter.logicalDpiX() + myPrinter.logicalDpiY() ) / 2 ); mpMapRenderer->render( &myMapPainter ); myMapPainter.end(); //draw the map pixmap onto our pdf print device myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing; myOriginY += myVerticalSpacing * 2; myPrintPainter.drawImage( myOriginX, myOriginY, myMapImage ); // // Draw the legend // QFont myLegendFont( myFontFamily, myLegendFontSize ); //myPrintPainter.setFont(myLegendFont); int myLegendDimensionX = ( myDrawableWidth / 100 ) * myLegendWidthPercent; int myLegendDimensionY = ( myDrawableHeight / 100 ) * myLegendHeightPercent; // Create a viewport to make coordinate conversions easier // The viewport has the same dimensions as the page(otherwise items // drawn into it will appear squashed), but a different origin. QRect myOriginalViewport = myPrintPainter.viewport(); //for restoring later myOriginX += myMapDimensionX + myHorizontalSpacing; myPrintPainter.setViewport( myOriginX, myOriginY, myOriginalViewport.width(), myOriginalViewport.height() ); //draw a rectangale around the legend frame //@TODO make this user settable if ( 0 == 1 ) //put some real logic here { myPrintPainter.drawRect( 0, 0, myLegendDimensionX, myLegendDimensionY ); } //get font metric and other vars needed QFontMetrics myLegendFontMetrics( myLegendFont, &myPrinter ); int myLegendFontHeight = myLegendFontMetrics.height(); int myLegendXPos = 0; int myLegendYPos = 0; int myLegendSpacer = myLegendFontHeight / 2; //for vertical and horizontal spacing int myLegendVerticalSpacer = myLegendFontHeight / 3; //for vertical between rows int myIconWidth = myLegendFontHeight; myPrintPainter.setFont( myLegendFont ); QStringList myLayerSet = mpMapRenderer->layerSet(); QStringListIterator myLayerIterator( myLayerSet ); //second clause below is to prevent legend spilling out the bottom while ( myLayerIterator.hasNext() && myLegendYPos < myLegendDimensionY ) { QString myLayerId = myLayerIterator.next(); QgsMapLayer * mypLayer = QgsMapLayerRegistry::instance()->mapLayer( myLayerId ); if ( mypLayer ) { QgsVectorLayer *mypVectorLayer = qobject_cast<QgsVectorLayer *>( mypLayer ); // TODO: add support for symbology-ng renderers if ( mypVectorLayer && mypVectorLayer->renderer() ) { QString myLayerName = mypVectorLayer->name(); QIcon myIcon; QPixmap myPixmap( QSize( myIconWidth, myIconWidth ) ); //square //based on code from qgslegendlayer.cpp - see that file for more info const QgsRenderer* mypRenderer = mypVectorLayer->renderer(); const QList<QgsSymbol*> mySymbolList = mypRenderer->symbols(); // // Single symbol // double widthScale = ( myPrinter.logicalDpiX() + myPrinter.logicalDpiY() ) / 2.0 / 25.4; if ( 1 == mySymbolList.size() ) { QgsSymbol * mypSymbol = mySymbolList.at( 0 ); myPrintPainter.setPen( mypSymbol->pen() ); myPrintPainter.setBrush( mypSymbol->brush() ); myLegendXPos = 0 ; if ( mypSymbol->type() == QGis::Point ) { QImage myImage; myImage = mypSymbol->getPointSymbolAsImage( widthScale ); myPrintPainter.drawImage( myLegendXPos, myLegendYPos, myImage ); } else if ( mypSymbol->type() == QGis::Line ) { myPrintPainter.drawLine( myLegendXPos, myLegendYPos, myLegendXPos + myIconWidth, myLegendYPos + myIconWidth ); } else //polygon { myPrintPainter.drawRect( myLegendXPos, myLegendYPos, myIconWidth, myIconWidth ); } myLegendXPos += myIconWidth + myLegendSpacer; myPrintPainter.setPen( Qt::black ); QStringList myWrappedLayerNameList = wordWrap( myLayerName, myLegendFontMetrics, myLegendDimensionX - myIconWidth ); // // Loop through wrapped legend label lines // QStringListIterator myLineWrapIterator( myWrappedLayerNameList ); while ( myLineWrapIterator.hasNext() ) { QString myLine = myLineWrapIterator.next(); QRect myLegendItemRect( myLegendXPos, myLegendYPos, myLegendDimensionX - myIconWidth, myLegendFontHeight ); myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine ); myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; } } else //class breaks { // draw in the layer name first, after we loop for the class breaks QStringList myWrappedLayerNameList = wordWrap( myLayerName, myLegendFontMetrics, myLegendDimensionX - myIconWidth ); // Check the wrapped layer name wont overrun the space we have // for the legend ... int myLabelHeight = myLegendFontHeight * myWrappedLayerNameList.count(); if ( myLegendYPos + myLabelHeight > myLegendDimensionY ) { continue; } // // Loop through wrapped legend label lines // QStringListIterator myLineWrapIterator( myWrappedLayerNameList ); while ( myLineWrapIterator.hasNext() ) { QString myLine = myLineWrapIterator.next(); myLegendXPos = myIconWidth; QRect myLegendItemRect( myLegendXPos, myLegendYPos, myLegendFontMetrics.width( myLine ), myLegendFontHeight ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine ); myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; } // // Loop through the class breaks // QListIterator<QgsSymbol *> myIterator( mySymbolList ); while ( myIterator.hasNext() && myLegendYPos < myLegendDimensionY ) { QgsSymbol * mypSymbol = myIterator.next(); myPrintPainter.setPen( mypSymbol->pen() ); myPrintPainter.setBrush( mypSymbol->brush() ); myLegendXPos = myLegendSpacer * 3; //extra indent for class breaks if ( mypSymbol->type() == QGis::Point ) { QImage myImage; myImage = mypSymbol->getPointSymbolAsImage( widthScale ); myPrintPainter.drawImage( myLegendXPos, myLegendYPos, myImage ); } else if ( mypSymbol->type() == QGis::Line ) { myPrintPainter.drawLine( myLegendXPos, myLegendYPos, myLegendXPos + myIconWidth, myLegendYPos + myIconWidth ); } else //polygon { myPrintPainter.drawRect( myLegendXPos, myLegendYPos, myIconWidth, myIconWidth ); } // // Now work out the class break label // QString myLabel; QString myLower = mypSymbol->lowerValue(); if ( !myLower.isEmpty() ) { myLabel = myLower; } QString myUpper = mypSymbol->upperValue(); if ( !myUpper.isEmpty() ) { myLabel += " - "; myLabel += myUpper; } QString myText = mypSymbol->label(); if ( !myText.isEmpty() ) { myLabel += " "; myLabel += myText; } myLabel = myLabel.trimmed(); myLegendXPos += myIconWidth + myLegendSpacer; myPrintPainter.setPen( Qt::black ); QStringList myWrappedLayerNameList = wordWrap( myLabel, myLegendFontMetrics, myLegendDimensionX - myLegendXPos ); // // Loop through wrapped legend label lines // QStringListIterator myLineWrapIterator( myWrappedLayerNameList ); while ( myLineWrapIterator.hasNext() ) { QString myLine = myLineWrapIterator.next(); // check if the text will overflow the space we have QRect myLegendItemRect( myLegendXPos, myLegendYPos, myLegendDimensionX - myIconWidth, myLegendFontHeight ); myPrintPainter.drawText( myLegendItemRect, Qt::AlignLeft, myLine ); myLegendYPos += myLegendVerticalSpacer + myLegendFontHeight; } //wordwrap loop } //symbol loop } //class breaks } //if vectorlayer } //if maplayer } //layer iterator //reinstate the viewport myPrintPainter.setViewport( myOriginalViewport ); // // Draw the MapFrame (bottom) // myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing; myOriginY += myMapDimensionY + ( myVerticalSpacing * 2 ); QLine myMapFrameBottomLine( myOriginX, myOriginY, myMapFrameWidth, myOriginY ); myPrintPainter.setPen( Qt::black ); myPrintPainter.drawLine( myMapFrameBottomLine ); // // Draw logo 1 // int myLogoXDim = ( myDrawableWidth / 100 ) * myLogoWidthPercent; int myLogoYDim = ( myDrawableHeight / 100 ) * myLogoHeightPercent; QPixmap myLogo1; QgsDebugMsg( QString( "Logo1: %1" ).arg( mLogo1File ) ); myLogo1.fill( Qt::white ); myLogo1.load( mLogo1File ); myLogo1 = myLogo1.scaled( myLogoXDim, myLogoYDim, Qt::KeepAspectRatio ); myOriginX = myPrinter.pageRect().left() + myHorizontalSpacing; myOriginY += myVerticalSpacing ; myPrintPainter.drawPixmap( myOriginX, myOriginY, myLogo1 ); // // Draw Copyright Text // myOriginX += myHorizontalSpacing + myLogoXDim; QRect myCopyrightRect( myOriginX, myOriginY, myLogoXDim, myLogoYDim ); myPrintPainter.setPen( Qt::black ); QFont myCopyrightFont( myFontFamily, myMapDateFontSize ); myPrintPainter.setFont( myCopyrightFont ); //myPrintPainter.drawRect( myCopyrightRect ); myPrintPainter.drawText( myCopyrightRect, Qt::AlignCenter | Qt::TextWordWrap, mCopyrightText ); // // Draw logo 2 // QPixmap myLogo2; myLogo2.fill( Qt::white ); myLogo2.load( mLogo2File ); myLogo2 = myLogo2.scaled( myLogoXDim, myLogoYDim, Qt::KeepAspectRatio ); myOriginX += myHorizontalSpacing + myLogoXDim; myPrintPainter.drawPixmap( myOriginX, myOriginY, myLogo2 ); // // Draw the north arrow // myOriginX += myHorizontalSpacing + myLogoXDim; // use half the available space for the n.arrow // and the rest for the scale bar (see below) QPixmap myNorthArrow( myLogoYDim / 2, myLogoYDim / 2 ); myNorthArrow.fill( Qt::white ); QPainter myNorthPainter( &myNorthArrow ); QSvgRenderer mySvgRenderer( mNorthArrowFile ); mySvgRenderer.render( &myNorthPainter ); myPrintPainter.drawPixmap( myOriginX + (( myLogoXDim / 2 ) ), myOriginY, myNorthArrow ); // // Draw the scale bar // myOriginY += myLogoYDim / 2 + myVerticalSpacing; myPrintPainter.setViewport( myOriginX, myOriginY, myOriginalViewport.width(), myOriginalViewport.height() ); renderPrintScaleBar( &myPrintPainter, mpMapRenderer, myLogoXDim ); myPrintPainter.setViewport( myOriginalViewport ); // // Finish up // myPrintPainter.end(); #if 0 mProgressDialog.setValue( 0 ); mProgressDialog.setLabelText( tr( "Please wait while your report is generated", "COMMENTED OUT" ) ); mProgressDialog.show(); mProgressDialog.setWindowModality( Qt::WindowModal ); mProgressDialog.setAutoClose( true ); #endif // // Restore the map render to its former glory // mpMapRenderer->setOutputSize( myOriginalSize, myOriginalDpi ); }
void QgsLineVectorLayerDirector::makeGraph( QgsGraphBuilderInterface *builder, const QVector< QgsPoint >& additionalPoints, QVector< QgsPoint >& tiedPoint ) const { QgsVectorLayer *vl = mVectorLayer; if ( vl == NULL ) return; int featureCount = ( int ) vl->featureCount() * 2; int step = 0; QgsCoordinateTransform ct; ct.setSourceCrs( vl->crs() ); if ( builder->coordinateTransformationEnabled() ) { ct.setDestCRS( builder->destinationCrs() ); } else { ct.setDestCRS( vl->crs() ); } tiedPoint = QVector< QgsPoint >( additionalPoints.size(), QgsPoint( 0.0, 0.0 ) ); TiePointInfo tmpInfo; tmpInfo.mLength = std::numeric_limits<double>::infinity(); QVector< TiePointInfo > pointLengthMap( additionalPoints.size(), tmpInfo ); QVector< TiePointInfo >::iterator pointLengthIt; //Graph's points; QVector< QgsPoint > points; QgsFeatureIterator fit = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) ); // begin: tie points to the graph QgsAttributeList la; QgsFeature feature; while ( fit.nextFeature( feature ) ) { QgsMultiPolyline mpl; if ( feature.constGeometry()->wkbType() == QGis::WKBMultiLineString ) mpl = feature.constGeometry()->asMultiPolyline(); else if ( feature.constGeometry()->wkbType() == QGis::WKBLineString ) mpl.push_back( feature.constGeometry()->asPolyline() ); QgsMultiPolyline::iterator mplIt; for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt ) { QgsPoint pt1, pt2; bool isFirstPoint = true; QgsPolyline::iterator pointIt; for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt ) { pt2 = ct.transform( *pointIt ); points.push_back( pt2 ); if ( !isFirstPoint ) { int i = 0; for ( i = 0; i != additionalPoints.size(); ++i ) { TiePointInfo info; if ( pt1 == pt2 ) { info.mLength = additionalPoints[ i ].sqrDist( pt1 ); info.mTiedPoint = pt1; } else { info.mLength = additionalPoints[ i ].sqrDistToSegment( pt1.x(), pt1.y(), pt2.x(), pt2.y(), info.mTiedPoint ); } if ( pointLengthMap[ i ].mLength > info.mLength ) { Q_UNUSED( info.mTiedPoint ); info.mFirstPoint = pt1; info.mLastPoint = pt2; pointLengthMap[ i ] = info; tiedPoint[ i ] = info.mTiedPoint; } } } pt1 = pt2; isFirstPoint = false; } } emit buildProgress( ++step, featureCount ); } // end: tie points to graph // add tied point to graph int i = 0; for ( i = 0; i < tiedPoint.size(); ++i ) { if ( tiedPoint[ i ] != QgsPoint( 0.0, 0.0 ) ) { points.push_back( tiedPoint [ i ] ); } } QgsPointCompare pointCompare( builder->topologyTolerance() ); qSort( points.begin(), points.end(), pointCompare ); QVector< QgsPoint >::iterator tmp = std::unique( points.begin(), points.end() ); points.resize( tmp - points.begin() ); for ( i = 0;i < points.size();++i ) builder->addVertex( i, points[ i ] ); for ( i = 0; i < tiedPoint.size() ; ++i ) tiedPoint[ i ] = *( my_binary_search( points.begin(), points.end(), tiedPoint[ i ], pointCompare ) ); qSort( pointLengthMap.begin(), pointLengthMap.end(), TiePointInfoCompare ); { // fill attribute list 'la' QgsAttributeList tmpAttr; if ( mDirectionFieldId != -1 ) { tmpAttr.push_back( mDirectionFieldId ); } QList< QgsArcProperter* >::const_iterator it; QgsAttributeList::const_iterator it2; for ( it = mProperterList.begin(); it != mProperterList.end(); ++it ) { QgsAttributeList tmp = ( *it )->requiredAttributes(); for ( it2 = tmp.begin(); it2 != tmp.end(); ++it2 ) { tmpAttr.push_back( *it2 ); } } qSort( tmpAttr.begin(), tmpAttr.end() ); int lastAttrId = -1; for ( it2 = tmpAttr.begin(); it2 != tmpAttr.end(); ++it2 ) { if ( *it2 == lastAttrId ) { continue; } la.push_back( *it2 ); lastAttrId = *it2; } } // end fill attribute list 'la' // begin graph construction fit = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( la ) ); while ( fit.nextFeature( feature ) ) { int directionType = mDefaultDirection; // What direction have feature? QString str = feature.attribute( mDirectionFieldId ).toString(); if ( str == mBothDirectionValue ) { directionType = 3; } else if ( str == mDirectDirectionValue ) { directionType = 1; } else if ( str == mReverseDirectionValue ) { directionType = 2; } // begin features segments and add arc to the Graph; QgsMultiPolyline mpl; if ( feature.constGeometry()->wkbType() == QGis::WKBMultiLineString ) mpl = feature.constGeometry()->asMultiPolyline(); else if ( feature.constGeometry()->wkbType() == QGis::WKBLineString ) mpl.push_back( feature.constGeometry()->asPolyline() ); QgsMultiPolyline::iterator mplIt; for ( mplIt = mpl.begin(); mplIt != mpl.end(); ++mplIt ) { QgsPoint pt1, pt2; bool isFirstPoint = true; QgsPolyline::iterator pointIt; for ( pointIt = mplIt->begin(); pointIt != mplIt->end(); ++pointIt ) { pt2 = ct.transform( *pointIt ); if ( !isFirstPoint ) { std::map< double, QgsPoint > pointsOnArc; pointsOnArc[ 0.0 ] = pt1; pointsOnArc[ pt1.sqrDist( pt2 )] = pt2; TiePointInfo t; t.mFirstPoint = pt1; t.mLastPoint = pt2; pointLengthIt = my_binary_search( pointLengthMap.begin(), pointLengthMap.end(), t, TiePointInfoCompare ); if ( pointLengthIt != pointLengthMap.end() ) { QVector< TiePointInfo >::iterator it; for ( it = pointLengthIt; it - pointLengthMap.begin() >= 0; --it ) { if ( it->mFirstPoint == pt1 && it->mLastPoint == pt2 ) { pointsOnArc[ pt1.sqrDist( it->mTiedPoint )] = it->mTiedPoint; } } for ( it = pointLengthIt + 1; it != pointLengthMap.end(); ++it ) { if ( it->mFirstPoint == pt1 && it->mLastPoint == pt2 ) { pointsOnArc[ pt1.sqrDist( it->mTiedPoint )] = it->mTiedPoint; } } } std::map< double, QgsPoint >::iterator pointsIt; QgsPoint pt1; QgsPoint pt2; int pt1idx = -1, pt2idx = -1; bool isFirstPoint = true; for ( pointsIt = pointsOnArc.begin(); pointsIt != pointsOnArc.end(); ++pointsIt ) { pt2 = pointsIt->second; tmp = my_binary_search( points.begin(), points.end(), pt2, pointCompare ); pt2 = *tmp; pt2idx = tmp - points.begin(); if ( !isFirstPoint && pt1 != pt2 ) { double distance = builder->distanceArea()->measureLine( pt1, pt2 ); QVector< QVariant > prop; QList< QgsArcProperter* >::const_iterator it; for ( it = mProperterList.begin(); it != mProperterList.end(); ++it ) { prop.push_back(( *it )->property( distance, feature ) ); } if ( directionType == 1 || directionType == 3 ) { builder->addArc( pt1idx, pt1, pt2idx, pt2, prop ); } if ( directionType == 2 || directionType == 3 ) { builder->addArc( pt2idx, pt2, pt1idx, pt1, prop ); } } pt1idx = pt2idx; pt1 = pt2; isFirstPoint = false; } } // if ( !isFirstPoint ) pt1 = pt2; isFirstPoint = false; } // for (it = pl.begin(); it != pl.end(); ++it) } emit buildProgress( ++step, featureCount ); } // while( vl->nextFeature(feature) ) } // makeGraph( QgsGraphBuilderInterface *builder, const QVector< QgsPoint >& additionalPoints, QVector< QgsPoint >& tiedPoint )
void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { //check if we operate on a vector layer QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } bool isGeometryEmpty = false; QgsFeatureList selectedFeatures = vlayer->selectedFeatures(); if ( !selectedFeatures.isEmpty() && selectedFeatures.at( 0 ).geometry().isNull() ) isGeometryEmpty = true; if ( !checkSelection() ) { stopCapturing(); return; } int errorCode = 0; switch ( mode() ) { case CapturePoint: { QgsPoint layerPoint; QgsPointXY mapPoint = e->mapPoint(); if ( nextPoint( QgsPoint( mapPoint ), layerPoint ) != 0 ) { QgsDebugMsg( "nextPoint failed" ); return; } vlayer->beginEditCommand( tr( "Part added" ) ); errorCode = vlayer->addPart( QgsPointSequence() << layerPoint ); } break; case CaptureLine: case CapturePolygon: { //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { QgsDebugMsg( "current layer is not a vector layer" ); return; } else if ( error == 2 ) { //problem with coordinate transformation emit messageEmitted( tr( "Coordinate transform error. Cannot transform the point to the layers coordinate system" ), Qgis::Warning ); return; } startCapturing(); return; } else if ( e->button() != Qt::RightButton ) { deleteTempRubberBand(); return; } if ( !isCapturing() ) return; if ( mode() == CapturePolygon ) { closePolygon(); } //does compoundcurve contain circular strings? //does provider support circular strings? bool hasCurvedSegments = captureCurve()->hasCurvedSegments(); bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries; QgsCurve *curveToAdd = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); } vlayer->beginEditCommand( tr( "Part added" ) ); if ( mode() == CapturePolygon ) { //avoid intersections QgsCurvePolygon *cp = new QgsCurvePolygon(); cp->setExteriorRing( curveToAdd ); QgsGeometry *geom = new QgsGeometry( cp ); geom->avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); const QgsCurvePolygon *cpGeom = qgsgeometry_cast<const QgsCurvePolygon *>( geom->constGet() ); if ( !cpGeom ) { stopCapturing(); delete geom; vlayer->destroyEditCommand(); return; } errorCode = vlayer->addPart( cpGeom->exteriorRing()->clone() ); delete geom; } else { errorCode = vlayer->addPart( curveToAdd ); } stopCapturing(); } break; default: Q_ASSERT( !"invalid capture mode" ); errorCode = 6; break; } QString errorMessage; switch ( errorCode ) { case 0: { // remove previous message emit messageDiscarded(); //add points to other features to keep topology up-to-date bool topologicalEditing = QgsProject::instance()->topologicalEditing(); if ( topologicalEditing ) { addTopologicalPoints( points() ); } vlayer->endEditCommand(); vlayer->triggerRepaint(); if ( ( !isGeometryEmpty ) && QgsWkbTypes::isSingleType( vlayer->wkbType() ) ) { emit messageEmitted( tr( "Add part: Feature geom is single part and you've added more than one" ), Qgis::Warning ); } return; } case 1: errorMessage = tr( "Selected feature is not multi part." ); break; case 2: errorMessage = tr( "New part's geometry is not valid." ); break; case 3: errorMessage = tr( "New polygon ring not disjoint with existing polygons." ); break; case 4: errorMessage = tr( "No feature selected. Please select a feature with the selection tool or in the attribute table" ); break; case 5: errorMessage = tr( "Several features are selected. Please select only one feature to which an island should be added." ); break; case 6: errorMessage = tr( "Selected geometry could not be found" ); break; } emit messageEmitted( errorMessage, Qgis::Warning ); vlayer->destroyEditCommand(); }
QgsAbstractGeometryV2* QgsGeometryEditUtils::avoidIntersections( const QgsAbstractGeometryV2& geom, QMap<QgsVectorLayer*, QSet<QgsFeatureId> > ignoreFeatures ) { QScopedPointer<QgsGeometryEngine> geomEngine( QgsGeometry::createGeometryEngine( &geom ) ); if ( geomEngine.isNull() ) { return nullptr; } QgsWKBTypes::Type geomTypeBeforeModification = geom.wkbType(); //check if g has polygon type if ( QgsWKBTypes::geometryType( geomTypeBeforeModification ) != QgsWKBTypes::PolygonGeometry ) { return nullptr; } //read avoid intersections list from project properties bool listReadOk; QStringList avoidIntersectionsList = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList", QStringList(), &listReadOk ); if ( !listReadOk ) return nullptr; //no intersections stored in project does not mean error QList< QgsAbstractGeometryV2* > nearGeometries; //go through list, convert each layer to vector layer and call QgsVectorLayer::removePolygonIntersections for each QgsVectorLayer* currentLayer = nullptr; QStringList::const_iterator aIt = avoidIntersectionsList.constBegin(); for ( ; aIt != avoidIntersectionsList.constEnd(); ++aIt ) { currentLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( *aIt ) ); if ( currentLayer ) { QgsFeatureIds ignoreIds; QMap<QgsVectorLayer*, QSet<qint64> >::const_iterator ignoreIt = ignoreFeatures.find( currentLayer ); if ( ignoreIt != ignoreFeatures.constEnd() ) ignoreIds = ignoreIt.value(); QgsFeatureIterator fi = currentLayer->getFeatures( QgsFeatureRequest( geom.boundingBox() ) .setFlags( QgsFeatureRequest::ExactIntersect ) .setSubsetOfAttributes( QgsAttributeList() ) ); QgsFeature f; while ( fi.nextFeature( f ) ) { if ( ignoreIds.contains( f.id() ) ) continue; if ( !f.hasGeometry() ) continue; nearGeometries << f.geometry().geometry()->clone(); } } } if ( nearGeometries.isEmpty() ) { return nullptr; } QgsAbstractGeometryV2* combinedGeometries = geomEngine.data()->combine( nearGeometries ); qDeleteAll( nearGeometries ); if ( !combinedGeometries ) { return nullptr; } QgsAbstractGeometryV2* diffGeom = geomEngine.data()->difference( *combinedGeometries ); delete combinedGeometries; return diffGeom; }
QVariant QgsSymbolV2LegendNode::data( int role ) const { if ( role == Qt::DisplayRole ) { return mLabel; } else if ( role == Qt::EditRole ) { return mUserLabel.isEmpty() ? mItem.label() : mUserLabel; } else if ( role == Qt::DecorationRole ) { if ( mPixmap.isNull() || mPixmap.size() != mIconSize ) { QPixmap pix; if ( mItem.symbol() ) { QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() ); pix = QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), mIconSize, context.data() ); } else { pix = QPixmap( mIconSize ); pix.fill( Qt::transparent ); } if ( mItem.level() == 0 || ( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) ) mPixmap = pix; else { // ident the symbol icon to make it look like a tree structure QPixmap pix2( pix.width() + mItem.level() * indentSize, pix.height() ); pix2.fill( Qt::transparent ); QPainter p( &pix2 ); p.drawPixmap( mItem.level() * indentSize, 0, pix ); p.end(); mPixmap = pix2; } } return mPixmap; } else if ( role == Qt::CheckStateRole ) { if ( !mItem.isCheckable() ) return QVariant(); QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( mLayerNode->layer() ); if ( !vlayer || !vlayer->rendererV2() ) return QVariant(); return vlayer->rendererV2()->legendSymbolItemChecked( mItem.ruleKey() ) ? Qt::Checked : Qt::Unchecked; } else if ( role == RuleKeyRole ) { return mItem.ruleKey(); } else if ( role == SymbolV2LegacyRuleKeyRole ) { return QVariant::fromValue<void*>( mItem.legacyRuleKey() ); } else if ( role == ParentRuleKeyRole ) { return mItem.parentRuleKey(); } return QVariant(); }
void QgsMapToolSplitFeatures::cadCanvasReleaseEvent( QgsMapMouseEvent * e ) { //check if we operate on a vector layer QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } bool split = false; //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { //If we snap the first point on a vertex of a line layer, we directly split the feature at this point if ( vlayer->geometryType() == QgsWkbTypes::LineGeometry && points().isEmpty() ) { QgsPointLocator::Match m = mCanvas->snappingUtils()->snapToCurrentLayer( e->pos(), QgsPointLocator::Vertex ); if ( m.isValid() ) { split = true; } } int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation QgisApp::instance()->messageBar()->pushMessage( tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ), QgsMessageBar::INFO, QgisApp::instance()->messageTimeout() ); return; } startCapturing(); } else if ( e->button() == Qt::RightButton ) { split = true; } if ( split ) { deleteTempRubberBand(); //bring up dialog if a split was not possible (polygon) or only done once (line) int topologicalEditing = QgsProject::instance()->topologicalEditing(); vlayer->beginEditCommand( tr( "Features split" ) ); int returnCode = vlayer->splitFeatures( points(), topologicalEditing ); vlayer->endEditCommand(); if ( returnCode == 4 ) { QgisApp::instance()->messageBar()->pushMessage( tr( "No features were split" ), tr( "If there are selected features, the split tool only applies to those. If you would like to split all features under the split line, clear the selection." ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); } else if ( returnCode == 3 ) { QgisApp::instance()->messageBar()->pushMessage( tr( "No feature split done" ), tr( "Cut edges detected. Make sure the line splits features into multiple parts." ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); } else if ( returnCode == 7 ) { QgisApp::instance()->messageBar()->pushMessage( tr( "No feature split done" ), tr( "The geometry is invalid. Please repair before trying to split it." ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); } else if ( returnCode != 0 ) { //several intersections but only one split (most likely line) QgisApp::instance()->messageBar()->pushMessage( tr( "No feature split done" ), tr( "An error occurred during splitting." ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); } stopCapturing(); } }
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 ); } }
void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e ) { QgsDebugMsg( "entered." ); QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { notifyNotVectorLayer(); return; } QGis::WkbType layerWKBType = vlayer->wkbType(); QgsVectorDataProvider* provider = vlayer->dataProvider(); if ( !( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { QMessageBox::information( 0, tr( "Layer cannot be added to" ), tr( "The data provider for this layer does not support the addition of features." ) ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } // POINT CAPTURING if ( mode() == CapturePoint ) { //check we only use this tool for point/multipoint layers if ( vlayer->geometryType() != QGis::Point ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture point' tool on this vector layer" ) ); return; } QgsPoint idPoint; //point in map coordinates QList<QgsSnappingResult> snapResults; QgsPoint savePoint; //point in layer coordinates if ( mSnapper.snapToBackgroundLayers( e->pos(), snapResults ) == 0 ) { idPoint = snapPointFromResults( snapResults, e->pos() ); try { savePoint = toLayerCoordinates( vlayer, idPoint ); QgsDebugMsg( "savePoint = " + savePoint.toString() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); return; } } //only do the rest for provider with feature addition support //note that for the grass provider, this will return false since //grass provider has its own mechanism of feature addition if ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) { QgsFeature* f = new QgsFeature( 0, "WKBPoint" ); QgsGeometry *g = 0; if ( layerWKBType == QGis::WKBPoint || layerWKBType == QGis::WKBPoint25D ) { g = QgsGeometry::fromPoint( savePoint ); } else if ( layerWKBType == QGis::WKBMultiPoint || layerWKBType == QGis::WKBMultiPoint25D ) { g = QgsGeometry::fromMultiPoint( QgsMultiPoint() << savePoint ); } f->setGeometry( g ); vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } mCanvas->refresh(); } } else if ( mode() == CaptureLine || mode() == CapturePolygon ) { //check we only use the line tool for line/multiline layers if ( mode() == CaptureLine && vlayer->geometryType() != QGis::Line ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture line' tool on this vector layer" ) ); return; } //check we only use the polygon tool for polygon/multipolygon layers if ( mode() == CapturePolygon && vlayer->geometryType() != QGis::Polygon ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture polygon' tool on this vector layer" ) ); return; } //add point to list and to rubber band int error = addVertex( e->pos() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); return; } if ( e->button() == Qt::LeftButton ) { startCapturing(); } else if ( e->button() == Qt::RightButton ) { // End of string //lines: bail out if there are not at least two vertices if ( mode() == CaptureLine && size() < 2 ) { stopCapturing(); return; } //polygons: bail out if there are not at least two vertices if ( mode() == CapturePolygon && size() < 3 ) { stopCapturing(); return; } //create QgsFeature with wkb representation QgsFeature* f = new QgsFeature( 0, "WKBLineString" ); QgsGeometry *g; if ( mode() == CaptureLine ) { if ( layerWKBType == QGis::WKBLineString || layerWKBType == QGis::WKBLineString25D ) { g = QgsGeometry::fromPolyline( points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiLineString || layerWKBType == QGis::WKBMultiLineString25D ) { g = QgsGeometry::fromMultiPolyline( QgsMultiPolyline() << points().toVector() ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } f->setGeometry( g ); } else // polygon { if ( layerWKBType == QGis::WKBPolygon || layerWKBType == QGis::WKBPolygon25D ) { g = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiPolygon || layerWKBType == QGis::WKBMultiPolygon25D ) { g = QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << points().toVector() ) ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } if ( !g ) { stopCapturing(); delete f; return; // invalid geometry; one possibility is from duplicate points } f->setGeometry( g ); int avoidIntersectionsReturn = f->geometry()->avoidIntersections(); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } #if 0 else if ( avoidIntersectionsReturn == 2 ) //MH120131: disable this error message until there is a better way to cope with the single type / multi type problem { //bail out... QMessageBox::critical( 0, tr( "Error" ), tr( "The feature could not be added because removing the polygon intersections would change the geometry type" ) ); delete f; stopCapturing(); return; } #endif else if ( avoidIntersectionsReturn == 3 ) { QMessageBox::critical( 0, tr( "Error" ), tr( "An error was reported during intersection removal" ) ); } } vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { //add points to other features to keep topology up-to-date int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); if ( topologicalEditing ) { vlayer->addTopologicalPoints( f->geometry() ); } vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } stopCapturing(); } } }
QFont QgsMapToolLabel::labelFontCurrentFeature() { QFont font; QgsVectorLayer* vlayer = currentLayer(); bool labelSettingsOk; QgsPalLayerSettings& labelSettings = currentLabelSettings( &labelSettingsOk ); if ( labelSettingsOk && vlayer ) { font = labelSettings.textFont; QgsFeature f; if ( vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mCurrentLabelPos.featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) ) { //size int sizeIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Size, vlayer ); if ( sizeIndx != -1 ) { if ( labelSettings.fontSizeInMapUnits ) { font.setPixelSize( labelSettings.sizeToPixel( f.attribute( sizeIndx ).toDouble(), QgsRenderContext(), QgsPalLayerSettings::MapUnits, true ) ); } else { font.setPointSizeF( f.attribute( sizeIndx ).toDouble() ); } } //family int fmIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Family, vlayer ); if ( fmIndx != -1 ) { font.setFamily( f.attribute( fmIndx ).toString() ); } //underline int ulIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Underline, vlayer ); if ( ulIndx != -1 ) { font.setUnderline( f.attribute( ulIndx ).toBool() ); } //strikeout int soIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Strikeout, vlayer ); if ( soIndx != -1 ) { font.setStrikeOut( f.attribute( soIndx ).toBool() ); } //bold int boIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Bold, vlayer ); if ( boIndx != -1 ) { font.setBold( f.attribute( boIndx ).toBool() ); } //italic int itIndx = dataDefinedColumnIndex( QgsPalLayerSettings::Italic, vlayer ); if ( itIndx != -1 ) { font.setItalic( f.attribute( itIndx ).toBool() ); } // TODO: Add other font data defined values (word spacing, etc.) } } return font; }
void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayer ); if ( !vlayer ) //if no given layer take the current from canvas vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } QgsWkbTypes::Type layerWKBType = vlayer->wkbType(); QgsVectorDataProvider *provider = vlayer->dataProvider(); if ( !( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { emit messageEmitted( tr( "The data provider for this layer does not support the addition of features." ), Qgis::Warning ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } // POINT CAPTURING if ( mode() == CapturePoint ) { if ( e->button() != Qt::LeftButton ) return; //check we only use this tool for point/multipoint layers if ( vlayer->geometryType() != QgsWkbTypes::PointGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture point' tool on this vector layer" ), Qgis::Warning ); return; } QgsPointXY savePoint; //point in layer coordinates try { QgsPoint fetchPoint; int res; res = fetchLayerPoint( e->mapPointMatch(), fetchPoint ); if ( res == 0 ) { savePoint = QgsPointXY( fetchPoint.x(), fetchPoint.y() ); } else { savePoint = toLayerCoordinates( vlayer, e->mapPoint() ); } QgsDebugMsg( "savePoint = " + savePoint.toString() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), Qgis::Warning ); return; } //only do the rest for provider with feature addition support //note that for the grass provider, this will return false since //grass provider has its own mechanism of feature addition if ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) { QgsFeature f( vlayer->fields(), 0 ); QgsGeometry g; if ( layerWKBType == QgsWkbTypes::Point ) { g = QgsGeometry::fromPointXY( savePoint ); } else if ( !QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) ) { g = QgsGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) ); } else if ( QgsWkbTypes::isMultiType( layerWKBType ) && !QgsWkbTypes::hasZ( layerWKBType ) ) { g = QgsGeometry::fromMultiPointXY( QgsMultiPointXY() << savePoint ); } else if ( QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) ) { QgsMultiPoint *mp = new QgsMultiPoint(); mp->addGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) ); g = QgsGeometry( mp ); } else { // if layer supports more types (mCheckGeometryType is false) g = QgsGeometry::fromPointXY( savePoint ); } if ( QgsWkbTypes::hasM( layerWKBType ) ) { g.get()->addMValue(); } f.setGeometry( g ); f.setValid( true ); digitized( f ); // we are done with digitizing for now so instruct advanced digitizing dock to reset its CAD points cadDockWidget()->clearPoints(); } } // LINE AND POLYGON CAPTURING else if ( mode() == CaptureLine || mode() == CapturePolygon ) { //check we only use the line tool for line/multiline layers if ( mode() == CaptureLine && vlayer->geometryType() != QgsWkbTypes::LineGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture line' tool on this vector layer" ), Qgis::Warning ); return; } //check we only use the polygon tool for polygon/multipolygon layers if ( mode() == CapturePolygon && vlayer->geometryType() != QgsWkbTypes::PolygonGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture polygon' tool on this vector layer" ), Qgis::Warning ); return; } //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), Qgis::Warning ); return; } startCapturing(); } else if ( e->button() == Qt::RightButton ) { // End of string deleteTempRubberBand(); //lines: bail out if there are not at least two vertices if ( mode() == CaptureLine && size() < 2 ) { stopCapturing(); return; } //polygons: bail out if there are not at least two vertices if ( mode() == CapturePolygon && size() < 3 ) { stopCapturing(); return; } if ( mode() == CapturePolygon ) { closePolygon(); } //create QgsFeature with wkb representation std::unique_ptr< QgsFeature > f( new QgsFeature( vlayer->fields(), 0 ) ); //does compoundcurve contain circular strings? //does provider support circular strings? bool hasCurvedSegments = captureCurve()->hasCurvedSegments(); bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries; QList<QgsPointLocator::Match> snappingMatchesList; QgsCurve *curveToAdd = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); snappingMatchesList = snappingMatches(); } if ( mode() == CaptureLine ) { QgsGeometry g( curveToAdd ); f->setGeometry( g ); } else { QgsCurvePolygon *poly = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { poly = new QgsCurvePolygon(); } else { poly = new QgsPolygon(); } poly->setExteriorRing( curveToAdd ); QgsGeometry g( poly ); f->setGeometry( g ); QgsGeometry featGeom = f->geometry(); int avoidIntersectionsReturn = featGeom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); f->setGeometry( featGeom ); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } if ( f->geometry().isEmpty() ) //avoid intersection might have removed the whole geometry { emit messageEmitted( tr( "The feature cannot be added because it's geometry collapsed due to intersection avoidance" ), Qgis::Critical ); stopCapturing(); return; } } f->setValid( true ); digitized( *f ); stopCapturing(); } } }
void CDTMapToolSelectTrainingSamples::canvasReleaseEvent(QgsMapMouseEvent *e) { if ( e->button() == Qt::LeftButton ) { if ( mDragging ) { mCanvas->panActionEnd( e->pos() ); mDragging = false; } else // add pan to mouse cursor { // transform the mouse pos to map coordinates QgsPoint center = mCanvas->getCoordinateTransform()->toMapPoint( e->x(), e->y() ); mCanvas->setExtent( QgsRectangle( center, center ) ); mCanvas->refresh(); } } else if (e->button()==Qt::RightButton) { QgsVectorLayer* vlayer = NULL; if ( !mapCanvas->currentLayer() || ( vlayer = qobject_cast<QgsVectorLayer *>( mapCanvas->currentLayer() ) ) == NULL ) return; QRect selectRect( 0, 0, 0, 0 ); int boxSize = 1; selectRect.setLeft ( e->pos().x() - boxSize ); selectRect.setRight ( e->pos().x() + boxSize ); selectRect.setTop ( e->pos().y() - boxSize ); selectRect.setBottom( e->pos().y() + boxSize ); const QgsMapToPixel* transform = mapCanvas->getCoordinateTransform(); QgsPoint ll = transform->toMapCoordinates( selectRect.left(), selectRect.bottom() ); QgsPoint ur = transform->toMapCoordinates( selectRect.right(), selectRect.top() ); QgsPolyline points; points.push_back(ll); points.push_back(QgsPoint( ur.x(), ll.y() )); points.push_back(ur); points.push_back(QgsPoint( ll.x(), ur.y() )); QgsPolygon polygon; polygon.push_back(points); QgsGeometry selectGeom = *(QgsGeometry::fromPolygon(polygon) ); if ( mapCanvas->mapSettings().hasCrsTransformEnabled() ) { QgsCoordinateTransform ct( mapCanvas->mapSettings().destinationCrs(), vlayer->crs() ); selectGeom.transform( ct ); } QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectGeom.boundingBox() ).setFlags( QgsFeatureRequest::ExactIntersect ) ); QgsFeature f; qint64 closestFeatureId = 0; bool foundSingleFeature = false; double closestFeatureDist = std::numeric_limits<double>::max(); while ( fit.nextFeature( f ) ) { QgsGeometry* g = f.geometry(); if ( !selectGeom.intersects( g ) ) continue; foundSingleFeature = true; double distance = g->distance( selectGeom ); if ( distance <= closestFeatureDist ) { closestFeatureDist = distance; closestFeatureId = f.attribute("GridCode").toInt(); } } if ( foundSingleFeature ) addSingleSample( closestFeatureId ); } }
bool QgsGeoPackageCollectionItem::handleDrop( const QMimeData *data, Qt::DropAction ) { if ( !QgsMimeDataUtils::isUriList( data ) ) return false; QString uri; QStringList importResults; bool hasError = false; // Main task std::unique_ptr< QgsConcurrentFileWriterImportTask > mainTask( new QgsConcurrentFileWriterImportTask( tr( "GeoPackage import" ) ) ); QgsTaskList importTasks; const auto lst = QgsMimeDataUtils::decodeUriList( data ); for ( const QgsMimeDataUtils::Uri &dropUri : lst ) { // Check that we are not copying over self if ( dropUri.uri.startsWith( mPath ) ) { importResults.append( tr( "You cannot import layer %1 over itself!" ).arg( dropUri.name ) ); hasError = true; } else { QgsMapLayer *srcLayer = nullptr; bool owner; bool isVector = false; QString error; // Common checks for raster and vector // aspatial is treated like vector if ( dropUri.layerType == QStringLiteral( "vector" ) ) { // open the source layer srcLayer = dropUri.vectorLayer( owner, error ); isVector = true; } else if ( dropUri.layerType == QStringLiteral( "mesh" ) ) { // unsupported hasError = true; continue; } else { srcLayer = dropUri.rasterLayer( owner, error ); } if ( !srcLayer ) { importResults.append( tr( "%1: %2" ).arg( dropUri.name, error ) ); hasError = true; continue; } if ( srcLayer->isValid() ) { uri = mPath; QgsDebugMsgLevel( "URI " + uri, 3 ); // check if the destination layer already exists bool exists = false; const auto c( children() ); for ( const QgsDataItem *child : c ) { if ( child->name() == dropUri.name ) { exists = true; } } if ( exists && !isVector ) { QMessageBox::warning( nullptr, tr( "Cannot Overwrite Layer" ), tr( "Destination layer <b>%1</b> already exists. Overwriting with raster layers is not currently supported." ).arg( dropUri.name ) ); } else if ( ! exists || QMessageBox::question( nullptr, tr( "Overwrite Layer" ), tr( "Destination layer <b>%1</b> already exists. Do you want to overwrite it?" ).arg( dropUri.name ), QMessageBox::Yes | QMessageBox::No ) == QMessageBox::Yes ) { if ( isVector ) // Import vectors and aspatial { QgsVectorLayer *vectorSrcLayer = qobject_cast < QgsVectorLayer * >( srcLayer ); QVariantMap options; options.insert( QStringLiteral( "driverName" ), QStringLiteral( "GPKG" ) ); options.insert( QStringLiteral( "update" ), true ); options.insert( QStringLiteral( "overwrite" ), true ); options.insert( QStringLiteral( "layerName" ), dropUri.name ); options.insert( QStringLiteral( "forceSinglePartGeometryType" ), true ); QgsVectorLayerExporterTask *exportTask = new QgsVectorLayerExporterTask( vectorSrcLayer, uri, QStringLiteral( "ogr" ), vectorSrcLayer->crs(), options, owner ); mainTask->addSubTask( exportTask, importTasks ); importTasks << exportTask; // when export is successful: connect( exportTask, &QgsVectorLayerExporterTask::exportComplete, this, [ = ]() { // this is gross - TODO - find a way to get access to messageBar from data items QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) ); refreshConnections(); } ); // when an error occurs: connect( exportTask, &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage ) { if ( error != QgsVectorLayerExporter::ErrUserCanceled ) { QgsMessageOutput *output = QgsMessageOutput::createMessageOutput(); output->setTitle( tr( "Import to GeoPackage database" ) ); output->setMessage( tr( "Failed to import some vector layers!\n\n" ) + errorMessage, QgsMessageOutput::MessageText ); output->showMessage(); } } ); } else // Import raster { QgsGeoPackageRasterWriterTask *exportTask = new QgsGeoPackageRasterWriterTask( dropUri, mPath ); mainTask->addSubTask( exportTask, importTasks ); importTasks << exportTask; // when export is successful: connect( exportTask, &QgsGeoPackageRasterWriterTask::writeComplete, this, [ = ]() { // this is gross - TODO - find a way to get access to messageBar from data items QMessageBox::information( nullptr, tr( "Import to GeoPackage database" ), tr( "Import was successful." ) ); refreshConnections(); } ); // when an error occurs: connect( exportTask, &QgsGeoPackageRasterWriterTask::errorOccurred, this, [ = ]( QgsGeoPackageRasterWriter::WriterError error, const QString & errorMessage ) { if ( error != QgsGeoPackageRasterWriter::WriterError::ErrUserCanceled ) { QgsMessageOutput *output = QgsMessageOutput::createMessageOutput(); output->setTitle( tr( "Import to GeoPackage database" ) ); output->setMessage( tr( "Failed to import some raster layers!\n\n" ) + errorMessage, QgsMessageOutput::MessageText ); output->showMessage(); } // Always try to delete the imported raster, in case the gpkg has been left // in an inconsistent status. Ignore delete errors. QString deleteErr; deleteGeoPackageRasterLayer( QStringLiteral( "GPKG:%1:%2" ).arg( mPath, dropUri.name ), deleteErr ); } ); } } // do not overwrite } else { importResults.append( tr( "%1: Not a valid layer!" ).arg( dropUri.name ) ); hasError = true; } } // check for self copy } // for each if ( hasError ) { QgsMessageOutput *output = QgsMessageOutput::createMessageOutput(); output->setTitle( tr( "Import to GeoPackage database" ) ); output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText ); output->showMessage(); } if ( ! importTasks.isEmpty() ) { QgsApplication::taskManager()->addTask( mainTask.release() ); } return true; }
QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( int x, int y, IdentifyMode mode, QList<QgsMapLayer*> layerList, LayerType layerType ) { QList<IdentifyResult> results; mLastPoint = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y ); mLastExtent = mCanvas->extent(); mLastMapUnitsPerPixel = mCanvas->mapUnitsPerPixel(); if ( mode == DefaultQgsSetting ) { QSettings settings; mode = static_cast<IdentifyMode>( settings.value( "/Map/identifyMode", 0 ).toInt() ); } if ( mode == LayerSelection ) { // fill map of layer / identify results mLayerIdResults.clear(); QList<IdentifyResult> idResult = identify( x, y, TopDownAll ); QList<IdentifyResult>::const_iterator it = idResult.constBegin(); for ( ; it != idResult.constEnd(); ++it ) { QgsMapLayer *layer = it->mLayer; if ( mLayerIdResults.contains( layer ) ) { mLayerIdResults[layer].append( *it ); } else { mLayerIdResults.insert( layer, QList<IdentifyResult>() << *it ); } } //fill selection menu with entries from mmLayerIdResults QMenu layerSelectionMenu; QMap< QgsMapLayer*, QList<IdentifyResult> >::const_iterator resultIt = mLayerIdResults.constBegin(); for ( ; resultIt != mLayerIdResults.constEnd(); ++resultIt ) { QAction* action = new QAction( QString( "%1 (%2)" ).arg( resultIt.key()->name() ).arg( resultIt.value().size() ), 0 ); action->setData( resultIt.key()->id() ); //add point/line/polygon icon QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( resultIt.key() ); if ( vl ) { switch ( vl->geometryType() ) { case QGis::Point: action->setIcon( QgsApplication::getThemeIcon( "/mIconPointLayer.png" ) ); break; case QGis::Line: action->setIcon( QgsApplication::getThemeIcon( "/mIconLineLayer.png" ) ); break; case QGis::Polygon: action->setIcon( QgsApplication::getThemeIcon( "/mIconPolygonLayer.png" ) ); break; default: break; } } else if ( resultIt.key()->type() == QgsMapLayer::RasterLayer ) { action->setIcon( QgsApplication::getThemeIcon( "/mIconRaster.png" ) ); } connect( action, SIGNAL( hovered() ), this, SLOT( handleMenuHover() ) ); layerSelectionMenu.addAction( action ); } if ( mLayerIdResults.size() > 1 ) { QAction *action = new QAction( tr( "All (%1)" ).arg( idResult.size() ), 0 ); connect( action, SIGNAL( hovered() ), this, SLOT( handleMenuHover() ) ); layerSelectionMenu.addAction( action ); } // exec layer selection menu QPoint globalPos = mCanvas->mapToGlobal( QPoint( x + 5, y + 5 ) ); QAction* selectedAction = layerSelectionMenu.exec( globalPos ); if ( selectedAction ) { if ( selectedAction->data().toString().isEmpty() ) { results = idResult; } else { QgsMapLayer* selectedLayer = QgsMapLayerRegistry::instance()->mapLayer( selectedAction->data().toString() ); QMap< QgsMapLayer*, QList<IdentifyResult> >::const_iterator sIt = mLayerIdResults.find( selectedLayer ); if ( sIt != mLayerIdResults.constEnd() ) { results = sIt.value(); } } } deleteRubberBands(); } else if ( mode == ActiveLayer && layerList.isEmpty() ) { QgsMapLayer *layer = mCanvas->currentLayer(); if ( !layer ) { emit identifyMessage( tr( "No active layer. To identify features, you must choose an active layer." ) ); return results; } QApplication::setOverrideCursor( Qt::WaitCursor ); identifyLayer( &results, layer, mLastPoint, mLastExtent, mLastMapUnitsPerPixel, layerType ); } else { QApplication::setOverrideCursor( Qt::WaitCursor ); QStringList noIdentifyLayerIdList = QgsProject::instance()->readListEntry( "Identify", "/disabledLayers" ); int layerCount; if ( layerList.isEmpty() ) layerCount = mCanvas->layerCount(); else layerCount = layerList.count(); for ( int i = 0; i < layerCount; i++ ) { QgsMapLayer *layer ; if ( layerList.isEmpty() ) layer = mCanvas->layer( i ); else layer = layerList.value( i ); emit identifyProgress( i, mCanvas->layerCount() ); emit identifyMessage( tr( "Identifying on %1..." ).arg( layer->name() ) ); if ( noIdentifyLayerIdList.contains( layer->id() ) ) continue; if ( identifyLayer( &results, layer, mLastPoint, mLastExtent, mLastMapUnitsPerPixel, layerType ) ) { if ( mode == TopDownStopAtFirst ) break; } } emit identifyProgress( mCanvas->layerCount(), mCanvas->layerCount() ); emit identifyMessage( tr( "Identifying done." ) ); } QApplication::restoreOverrideCursor(); return results; }
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 ) ) ); }
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; }
void QgsLegendLayer::addToPopupMenu( QMenu& theMenu ) { QgsMapLayer *lyr = layer(); QAction *toggleEditingAction = QgisApp::instance()->actionToggleEditing(); QAction *saveLayerEditsAction = QgisApp::instance()->actionSaveActiveLayerEdits(); QAction *allEditsAction = QgisApp::instance()->actionAllEdits(); // zoom to layer extent theMenu.addAction( QgsApplication::getThemeIcon( "/mActionZoomToLayer.svg" ), tr( "&Zoom to Layer Extent" ), legend(), SLOT( legendLayerZoom() ) ); if ( lyr->type() == QgsMapLayer::RasterLayer ) { theMenu.addAction( tr( "&Zoom to Best Scale (100%)" ), legend(), SLOT( legendLayerZoomNative() ) ); QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( lyr ); if ( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette ) { theMenu.addAction( tr( "&Stretch Using Current Extent" ), legend(), SLOT( legendLayerStretchUsingCurrentExtent() ) ); } } // show in overview QAction* showInOverviewAction = theMenu.addAction( tr( "&Show in Overview" ), this, SLOT( showInOverview() ) ); showInOverviewAction->setCheckable( true ); showInOverviewAction->blockSignals( true ); showInOverviewAction->setChecked( mLyr.isInOverview() ); showInOverviewAction->blockSignals( false ); // remove from canvas theMenu.addAction( QgsApplication::getThemeIcon( "/mActionRemoveLayer.svg" ), tr( "&Remove" ), QgisApp::instance(), SLOT( removeLayer() ) ); // duplicate layer QAction* duplicateLayersAction = theMenu.addAction( QgsApplication::getThemeIcon( "/mActionDuplicateLayer.svg" ), tr( "&Duplicate" ), QgisApp::instance(), SLOT( duplicateLayers() ) ); // set layer crs theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetCRS.png" ), tr( "&Set Layer CRS" ), QgisApp::instance(), SLOT( setLayerCRS() ) ); // assign layer crs to project theMenu.addAction( QgsApplication::getThemeIcon( "/mActionSetProjectCRS.png" ), tr( "Set &Project CRS from Layer" ), QgisApp::instance(), SLOT( setProjectCRSFromLayer() ) ); theMenu.addSeparator(); if ( lyr->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( lyr ); // attribute table theMenu.addAction( QgsApplication::getThemeIcon( "/mActionOpenTable.png" ), tr( "&Open Attribute Table" ), QgisApp::instance(), SLOT( attributeTable() ) ); // allow editing int cap = vlayer->dataProvider()->capabilities(); if ( cap & QgsVectorDataProvider::EditingCapabilities ) { if ( toggleEditingAction ) { theMenu.addAction( toggleEditingAction ); toggleEditingAction->setChecked( vlayer->isEditable() ); } if ( saveLayerEditsAction && vlayer->isModified() ) { theMenu.addAction( saveLayerEditsAction ); } } if ( allEditsAction->isEnabled() ) { theMenu.addAction( allEditsAction ); } // disable duplication of memory layers if ( vlayer->storageType() == "Memory storage" && legend()->selectedLayers().count() == 1 ) { duplicateLayersAction->setEnabled( false ); } // save as vector file theMenu.addAction( tr( "Save As..." ), QgisApp::instance(), SLOT( saveAsFile() ) ); // save selection as vector file QAction* saveSelectionAsAction = theMenu.addAction( tr( "Save Selection As..." ), QgisApp::instance(), SLOT( saveSelectionAsVectorFile() ) ); if ( vlayer->selectedFeatureCount() == 0 ) { saveSelectionAsAction->setEnabled( false ); } if ( !vlayer->isEditable() && vlayer->dataProvider()->supportsSubsetString() && vlayer->vectorJoins().isEmpty() ) theMenu.addAction( tr( "&Filter..." ), QgisApp::instance(), SLOT( layerSubsetString() ) ); //show number of features in legend if requested QAction* showNFeaturesAction = new QAction( tr( "Show Feature Count" ), &theMenu ); showNFeaturesAction->setCheckable( true ); showNFeaturesAction->setChecked( mShowFeatureCount ); QObject::connect( showNFeaturesAction, SIGNAL( toggled( bool ) ), this, SLOT( setShowFeatureCount( bool ) ) ); theMenu.addAction( showNFeaturesAction ); theMenu.addSeparator(); }
void QgsBrowserLayerProperties::setItem( QgsDataItem* item ) { QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( item ); if ( !layerItem ) return; mNoticeLabel->clear(); QgsMapLayer::LayerType type = layerItem->mapLayerType(); QString layerMetadata = tr( "Error" ); QgsCoordinateReferenceSystem layerCrs; // temporarily override /Projections/defaultBehaviour to avoid dialog prompt QSettings settings; QString defaultProjectionOption = settings.value( "/Projections/defaultBehaviour", "prompt" ).toString(); if ( settings.value( "/Projections/defaultBehaviour", "prompt" ).toString() == "prompt" ) { settings.setValue( "/Projections/defaultBehaviour", "useProject" ); } // find root item // we need to create a temporary layer to get metadata // we could use a provider but the metadata is not as complete and "pretty" and this is easier QgsDebugMsg( QString( "creating temporary layer using path %1" ).arg( layerItem->path() ) ); if ( type == QgsMapLayer::RasterLayer ) { QgsDebugMsg( "creating raster layer" ); // should copy code from addLayer() to split uri ? QgsRasterLayer* layer = new QgsRasterLayer( layerItem->uri(), layerItem->uri(), layerItem->providerKey() ); if ( layer ) { if ( layer->isValid() ) { layerCrs = layer->crs(); layerMetadata = layer->metadata(); } delete layer; } } else if ( type == QgsMapLayer::VectorLayer ) { QgsDebugMsg( "creating vector layer" ); QgsVectorLayer* layer = new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() ); if ( layer ) { if ( layer->isValid() ) { layerCrs = layer->crs(); layerMetadata = layer->metadata(); } delete layer; } } else if ( type == QgsMapLayer::PluginLayer ) { // TODO: support display of properties for plugin layers return; } // restore /Projections/defaultBehaviour if ( defaultProjectionOption == "prompt" ) { settings.setValue( "/Projections/defaultBehaviour", defaultProjectionOption ); } mNameLabel->setText( layerItem->name() ); mUriLabel->setText( layerItem->uri() ); mProviderLabel->setText( layerItem->providerKey() ); QString myStyle = QgsApplication::reportStyleSheet(); mMetadataTextBrowser->document()->setDefaultStyleSheet( myStyle ); mMetadataTextBrowser->setHtml( layerMetadata ); // report if layer was set to to project crs without prompt (may give a false positive) if ( defaultProjectionOption == "prompt" ) { QgsCoordinateReferenceSystem defaultCrs = QgisApp::instance()->mapCanvas()->mapSettings().destinationCrs(); if ( layerCrs == defaultCrs ) mNoticeLabel->setText( "NOTICE: Layer srs set from project (" + defaultCrs.authid() + ')' ); } if ( mNoticeLabel->text().isEmpty() ) { mNoticeLabel->hide(); } }