QSet<QString> QgsGraduatedSymbolRenderer::usedAttributes( const QgsRenderContext &context ) const { QSet<QString> attributes; // mAttrName can contain either attribute name or an expression. // Sometimes it is not possible to distinguish between those two, // e.g. "a - b" can be both a valid attribute name or expression. // Since we do not have access to fields here, try both options. attributes << mAttrName; QgsExpression testExpr( mAttrName ); if ( !testExpr.hasParserError() ) attributes.unite( testExpr.referencedColumns() ); QgsRangeList::const_iterator range_it = mRanges.constBegin(); for ( ; range_it != mRanges.constEnd(); ++range_it ) { QgsSymbol *symbol = range_it->symbol(); if ( symbol ) { attributes.unite( symbol->usedAttributes( context ) ); } } return attributes; }
void QgsStyleManagerDialog::populateSymbols( const QStringList& symbolNames, bool check ) { QStandardItemModel* model = qobject_cast<QStandardItemModel*>( listItems->model() ); model->clear(); int type = currentItemType(); for ( int i = 0; i < symbolNames.count(); ++i ) { QString name = symbolNames[i]; QgsSymbol* symbol = mStyle->symbol( name ); if ( symbol && symbol->type() == type ) { QStandardItem* item = new QStandardItem( name ); QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, listItems->iconSize() ); item->setIcon( icon ); item->setData( name ); // used to find out original name when user edited the name item->setCheckable( check ); item->setToolTip( name ); // add to model model->appendRow( item ); } delete symbol; } selectedSymbolsChanged( QItemSelection(), QItemSelection() ); symbolSelected( listItems->currentIndex() ); }
void QgsUniqueValueDialog::applySymbologyChanges() { QgsDebugMsg( "called." ); QList<QListWidgetItem *> selection = mClassListWidget->selectedItems(); for ( int i = 0; i < selection.size(); i++ ) { QListWidgetItem* item = selection[i]; if ( !item ) { QgsDebugMsg( QString( "selected item %1 not found" ).arg( i ) ); continue; } QString value = item->text(); if ( !mValues.contains( value ) ) { QgsDebugMsg( QString( "value %1 not found" ).arg( value ) ); continue; } QgsSymbol *symbol = mValues[ value ]; symbol->setLowerValue( value ); sydialog.apply( symbol ); item->setToolTip( symbol->label() ); item->setData( Qt::UserRole, value ); updateEntryIcon( symbol, item ); } }
QgsSingleSymbolRenderer::QgsSingleSymbolRenderer( QGis::GeometryType type ) { mGeometryType = type; //initial setting based on random color QgsSymbol* sy = new QgsSymbol( mGeometryType ); //random fill colors for points and polygons and pen colors for lines int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); if ( type == QGis::Line ) { sy->setColor( QColor( red, green, blue ) ); } else { sy->setFillColor( QColor( red, green, blue ) ); sy->setFillStyle( Qt::SolidPattern ); sy->setColor( QColor( 0, 0, 0 ) ); } mSymbol = sy; updateSymbolAttributes(); }
int QgsUniqueValueRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) { mGeometryType = vl.geometryType(); QDomNode classnode = rnode.namedItem( "classificationfield" ); QString classificationField = classnode.toElement().text(); QgsVectorDataProvider* theProvider = vl.dataProvider(); if ( !theProvider ) { return 1; } int classificationId = vl.fieldNameIndex( classificationField ); if ( classificationId == -1 ) { //go on. Because with joins, it might be the joined layer is not loaded yet } setClassificationField( classificationId ); QDomNode symbolnode = rnode.namedItem( "symbol" ); while ( !symbolnode.isNull() ) { QgsSymbol* msy = new QgsSymbol( mGeometryType ); msy->readXML( symbolnode, &vl ); insertValue( msy->lowerValue(), msy ); symbolnode = symbolnode.nextSibling(); } updateSymbolAttributes(); vl.setRenderer( this ); return 0; }
void QgsSymbolSelectorWidget::changeLayer( QgsSymbolLayer *newLayer ) { SymbolLayerItem *item = currentLayerItem(); QgsSymbolLayer *layer = item->layer(); if ( layer->subSymbol() ) { item->removeRow( 0 ); } // update symbol layer item item->setLayer( newLayer ); // When it is a marker symbol if ( newLayer->subSymbol() ) { loadSymbol( newLayer->subSymbol(), item ); layersTree->setExpanded( item->index(), true ); } // Change the symbol at last to avoid deleting item's layer QgsSymbol *symbol = static_cast<SymbolLayerItem *>( item->parent() )->symbol(); int layerIdx = item->parent()->rowCount() - item->row() - 1; symbol->changeSymbolLayer( layerIdx, newLayer ); item->updatePreview(); updatePreview(); // Important: This lets the layer have its own layer properties widget layerChanged(); }
void QgsGraduatedSymbolRendererWidget::updateSymbolsFromWidget() { QgsSymbolSelectorWidget* dlg = qobject_cast<QgsSymbolSelectorWidget*>( sender() ); delete mGraduatedSymbol; mGraduatedSymbol = dlg->symbol()->clone(); mSizeUnitWidget->blockSignals( true ); mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() ); mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() ); mSizeUnitWidget->blockSignals( false ); QItemSelectionModel* m = viewGraduated->selectionModel(); QModelIndexList selectedIndexes = m->selectedRows( 1 ); if ( m && !selectedIndexes.isEmpty() ) { Q_FOREACH ( const QModelIndex& idx, selectedIndexes ) { if ( idx.isValid() ) { int rangeIdx = idx.row(); QgsSymbol* newRangeSymbol = mGraduatedSymbol->clone(); if ( selectedIndexes.count() > 1 ) { //if updating multiple ranges, retain the existing range colors newRangeSymbol->setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() ); } mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol ); } } }
void QgsSymbolSelectorWidget::moveLayerByOffset( int offset ) { SymbolLayerItem *item = currentLayerItem(); if ( !item ) return; int row = item->row(); SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() ); QgsSymbol *parentSymbol = parent->symbol(); int layerIdx = parent->rowCount() - row - 1; // switch layers QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx ); parentSymbol->insertSymbolLayer( layerIdx - offset, tmpLayer ); QList<QStandardItem *> rowItems = parent->takeRow( row ); parent->insertRows( row + offset, rowItems ); parent->updatePreview(); QModelIndex newIdx = rowItems[ 0 ]->index(); layersTree->setCurrentIndex( newIdx ); updatePreview(); updateUi(); }
void QgsGraduatedSymbolRendererWidget::applyChangeToSymbol() { mSizeUnitWidget->blockSignals( true ); mSizeUnitWidget->setUnit( mGraduatedSymbol->outputUnit() ); mSizeUnitWidget->setMapUnitScale( mGraduatedSymbol->mapUnitScale() ); mSizeUnitWidget->blockSignals( false ); QItemSelectionModel *m = viewGraduated->selectionModel(); QModelIndexList selectedIndexes = m->selectedRows( 1 ); if ( m && !selectedIndexes.isEmpty() ) { const auto constSelectedIndexes = selectedIndexes; for ( const QModelIndex &idx : constSelectedIndexes ) { if ( idx.isValid() ) { int rangeIdx = idx.row(); QgsSymbol *newRangeSymbol = mGraduatedSymbol->clone(); if ( selectedIndexes.count() > 1 ) { //if updating multiple ranges, retain the existing range colors newRangeSymbol->setColor( mRenderer->ranges().at( rangeIdx ).symbol()->color() ); } mRenderer->updateRangeSymbol( rangeIdx, newRangeSymbol ); } } } else { mRenderer->updateSymbols( mGraduatedSymbol.get() ); } refreshSymbolView(); emit widgetChanged(); }
int QgsContinuousColorRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) { mGeometryType = vl.geometryType(); QDomNode classnode = rnode.namedItem( "classificationfield" ); QString classificationField = classnode.toElement().text(); QgsVectorDataProvider* theProvider = vl.dataProvider(); if ( !theProvider ) { return 1; } int classificationId = vl.fieldNameIndex( classificationField ); if ( classificationId == -1 ) { //go on. Because with joins, it might be the joined layer is not loaded yet } setClassificationField( classificationId ); //polygon outline QDomNode polyoutlinenode = rnode.namedItem( "polygonoutline" ); QString polyoutline = polyoutlinenode.toElement().text(); if ( polyoutline == "0" ) { mDrawPolygonOutline = false; } else if ( polyoutline == "1" ) { mDrawPolygonOutline = true; } //read the settings for the renderitem of the minimum value QDomNode lowernode = rnode.namedItem( "lowestsymbol" ); QDomNode lsymbolnode = lowernode.namedItem( "symbol" ); if ( ! lsymbolnode.isNull() ) { QgsSymbol* lsy = new QgsSymbol( mGeometryType ); lsy->readXML( lsymbolnode, &vl ); setMinimumSymbol( lsy ); } QDomNode uppernode = rnode.namedItem( "highestsymbol" ); QDomNode usymbolnode = uppernode.namedItem( "symbol" ); if ( ! usymbolnode.isNull() ) { QgsSymbol* usy = new QgsSymbol( mGeometryType ); usy->readXML( usymbolnode, &vl ); setMaximumSymbol( usy ); } vl.setRenderer( this ); return 0; }
static QString _getLayerSvgMarkerPath( const QgsProject &prj, const QString &layerName ) { QList<QgsMapLayer *> layers = prj.mapLayersByName( layerName ); Q_ASSERT( layers.count() == 1 ); Q_ASSERT( layers[0]->type() == QgsMapLayerType::VectorLayer ); QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( layers[0] ); Q_ASSERT( layer->renderer() ); Q_ASSERT( layer->renderer()->type() == "singleSymbol" ); QgsSingleSymbolRenderer *r = static_cast<QgsSingleSymbolRenderer *>( layer->renderer() ); QgsSymbol *s = r->symbol(); Q_ASSERT( s && s->symbolLayerCount() == 1 ); Q_ASSERT( s->symbolLayer( 0 )->layerType() == "SvgMarker" ); QgsSvgMarkerSymbolLayer *sl = static_cast<QgsSvgMarkerSymbolLayer *>( s->symbolLayer( 0 ) ); return sl->path(); }
void QgsUniqueValueDialog::selectionChanged() { QgsDebugMsg( "called." ); sydialog.blockSignals( true );//block signal to prevent sydialog from changing the current QgsRenderItem QList<QListWidgetItem *> selection = mClassListWidget->selectedItems(); if ( selection.size() == 0 ) { mDeletePushButton->setEnabled( false ); sydialog.unset(); } else { mDeletePushButton->setEnabled( true ); if ( selection.size() == 1 || !mCommonPropertyLock->isChecked() ) { QListWidgetItem *item = selection[0]; if ( !item ) return; if ( !mValues.contains( item->text() ) ) return; QgsSymbol *symbol = mValues[ item->text()]; sydialog.set( symbol ); sydialog.setLabel( symbol->label() ); } else if ( selection.size() > 1 && mCommonPropertyLock->isChecked() ) { if ( !mValues.contains( selection[0]->text() ) ) return; sydialog.set( mValues[ selection[0]->text()] ); for ( int i = 1; i < selection.size(); i++ ) { if ( !mValues.contains( selection[i]->text() ) ) continue; sydialog.updateSet( mValues[ selection[i]->text()] ); } } } sydialog.blockSignals( false ); }
int QgsGraduatedSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) { mGeometryType = vl.geometryType(); QDomNode modeNode = rnode.namedItem( "mode" ); QString modeValue = modeNode.toElement().text(); QDomNode classnode = rnode.namedItem( "classificationfield" ); QString classificationField = classnode.toElement().text(); QgsVectorDataProvider* theProvider = vl.dataProvider(); if ( !theProvider ) { return 1; } if ( modeValue == "Empty" ) { mMode = QgsGraduatedSymbolRenderer::Empty; } else if ( modeValue == "Quantile" ) { mMode = QgsGraduatedSymbolRenderer::Quantile; } else //default { mMode = QgsGraduatedSymbolRenderer::EqualInterval; } int classificationId = theProvider->fieldNameIndex( classificationField ); if ( classificationId == -1 ) { return 2; //@todo: handle gracefully in gui situation where user needs to nominate field } setClassificationField( classificationId ); QDomNode symbolnode = rnode.namedItem( "symbol" ); while ( !symbolnode.isNull() ) { QgsSymbol* sy = new QgsSymbol( mGeometryType ); sy->readXML( symbolnode, &vl ); addSymbol( sy ); symbolnode = symbolnode.nextSibling(); } updateSymbolAttributes(); vl.setRenderer( this ); return 0; }
int QgsGraduatedSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) { mGeometryType = vl.geometryType(); QDomNode modeNode = rnode.namedItem( "mode" ); QString modeValue = modeNode.toElement().text(); QDomNode classnode = rnode.namedItem( "classificationfield" ); QString classificationField = classnode.toElement().text(); QgsVectorDataProvider* theProvider = vl.dataProvider(); if ( !theProvider ) { return 1; } if ( modeValue == "Empty" ) { mMode = QgsGraduatedSymbolRenderer::Empty; } else if ( modeValue == "Quantile" ) { mMode = QgsGraduatedSymbolRenderer::Quantile; } else //default { mMode = QgsGraduatedSymbolRenderer::EqualInterval; } int classificationId = vl.fieldNameIndex( classificationField ); if ( classificationId == -1 ) { //go on. Because with joins, it might be the joined layer is not loaded yet } setClassificationField( classificationId ); QDomNode symbolnode = rnode.namedItem( "symbol" ); while ( !symbolnode.isNull() ) { QgsSymbol* sy = new QgsSymbol( mGeometryType ); sy->readXML( symbolnode, &vl ); addSymbol( sy ); symbolnode = symbolnode.nextSibling(); } updateSymbolAttributes(); vl.setRenderer( this ); return 0; }
void QgsUniqueValueDialog::itemChanged( QListWidgetItem *item ) { QString oldValue = item->data( Qt::UserRole ).toString(); QString newValue = item->text(); if ( oldValue == newValue ) return; if ( !mValues.contains( newValue ) ) { QgsSymbol *sy = mValues[oldValue]; mValues.remove( oldValue ); mValues.insert( newValue, sy ); sy->setLowerValue( newValue ); item->setData( Qt::UserRole, newValue ); updateEntryIcon( sy, item ); } else item->setText( oldValue ); }
void QgsSymbolSelectorWidget::removeLayer() { SymbolLayerItem *item = currentLayerItem(); int row = item->row(); SymbolLayerItem *parent = static_cast<SymbolLayerItem *>( item->parent() ); int layerIdx = parent->rowCount() - row - 1; // IMPORTANT QgsSymbol *parentSymbol = parent->symbol(); QgsSymbolLayer *tmpLayer = parentSymbol->takeSymbolLayer( layerIdx ); parent->removeRow( row ); parent->updatePreview(); QModelIndex newIdx = parent->child( 0 )->index(); layersTree->setCurrentIndex( newIdx ); updateUi(); updatePreview(); //finally delete the removed layer pointer delete tmpLayer; }
void QgsUniqueValueDialog::addClass( QString value ) { QgsDebugMsg( "called." ); if ( mValues.contains( value ) ) { int i; for ( i = 0; mValues.contains( value + QString::number( i ) ); i++ ) ; value += QString::number( i ); } QgsSymbol *symbol = new QgsSymbol( mVectorLayer->geometryType(), value, value, value.isNull() ? tr( "default" ) : "" ); mValues.insert( value, symbol ); QListWidgetItem *item = new QListWidgetItem( value ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ); item->setData( Qt::UserRole, value ); item->setToolTip( symbol->label() ); mClassListWidget->addItem( item ); setSymbolColor( symbol, randomColor() ); updateEntryIcon( symbol, item ); }
int QgsSingleSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) { mGeometryType = vl.geometryType(); QgsSymbol* sy = new QgsSymbol( mGeometryType ); QDomNode synode = rnode.namedItem( "symbol" ); if ( synode.isNull() ) { QgsDebugMsg( "No symbol node in project file's renderitem Dom" ); // XXX abort? } else { sy->readXML( synode, &vl ); } updateSymbolAttributes(); //create a renderer and add it to the vector layer addSymbol( sy ); vl.setRenderer( this ); return 0; }
void QgsCategorizedSymbolRendererWidget::changeSelectedSymbols() { QList<int> selectedCats = selectedCategories(); if ( !selectedCats.isEmpty() ) { QgsSymbol *newSymbol = mCategorizedSymbol->clone(); QgsSymbolSelectorDialog dlg( newSymbol, mStyle, mLayer, this ); dlg.setContext( context() ); if ( !dlg.exec() ) { delete newSymbol; return; } Q_FOREACH ( int idx, selectedCats ) { QgsRendererCategory category = mRenderer->categories().value( idx ); QgsSymbol *newCatSymbol = newSymbol->clone(); newCatSymbol->setColor( mRenderer->categories()[idx].symbol()->color() ); mRenderer->updateCategorySymbol( idx, newCatSymbol ); }
void QgsSymbolSelectorWidget::duplicateLayer() { QModelIndex idx = layersTree->currentIndex(); if ( !idx.isValid() ) return; SymbolLayerItem *item = static_cast<SymbolLayerItem *>( model->itemFromIndex( idx ) ); if ( !item->isLayer() ) return; QgsSymbolLayer *source = item->layer(); int insertIdx = item->row(); item = static_cast<SymbolLayerItem *>( item->parent() ); QgsSymbol *parentSymbol = item->symbol(); QgsSymbolLayer *newLayer = source->clone(); if ( insertIdx == -1 ) parentSymbol->appendSymbolLayer( newLayer ); else parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer ); SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer ); item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem ); if ( newLayer->subSymbol() ) { loadSymbol( newLayer->subSymbol(), newLayerItem ); layersTree->setExpanded( newLayerItem->index(), true ); } item->updatePreview(); layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) ); updateUi(); updatePreview(); }
QgsSymbol *QgsGrassEditRenderer::symbolForFeature( const QgsFeature &feature, QgsRenderContext &context ) const { int symbolCode = feature.attribute( QStringLiteral( "topo_symbol" ) ).toInt(); QgsDebugMsgLevel( QString( "fid = %1 symbolCode = %2" ).arg( feature.id() ).arg( symbolCode ), 3 ); QgsSymbol *symbol = nullptr; if ( symbolCode == QgsGrassVectorMap::TopoPoint || symbolCode == QgsGrassVectorMap::TopoCentroidIn || symbolCode == QgsGrassVectorMap::TopoCentroidOut || symbolCode == QgsGrassVectorMap::TopoCentroidDupl || symbolCode == QgsGrassVectorMap::TopoNode0 || symbolCode == QgsGrassVectorMap::TopoNode1 || symbolCode == QgsGrassVectorMap::TopoNode2 ) { symbol = mMarkerRenderer->symbolForFeature( feature, context ); } else if ( symbolCode == QgsGrassVectorMap::TopoLine || symbolCode == QgsGrassVectorMap::TopoBoundaryError || symbolCode == QgsGrassVectorMap::TopoBoundaryErrorLeft || symbolCode == QgsGrassVectorMap::TopoBoundaryErrorRight || symbolCode == QgsGrassVectorMap::TopoBoundaryOk ) { symbol = mLineRenderer->symbolForFeature( feature, context ); } else { // should not happen QgsDebugMsg( "unknown symbol code" ); } if ( symbol ) { QgsDebugMsgLevel( "color = " + symbol->color().name(), 3 ); } else { QgsDebugMsgLevel( "no symbol", 3 ); } return symbol; }
void QgsSymbolSelectorWidget::addLayer() { QModelIndex idx = layersTree->currentIndex(); if ( !idx.isValid() ) return; int insertIdx = -1; SymbolLayerItem *item = static_cast<SymbolLayerItem *>( model->itemFromIndex( idx ) ); if ( item->isLayer() ) { insertIdx = item->row(); item = static_cast<SymbolLayerItem *>( item->parent() ); } QgsSymbol *parentSymbol = item->symbol(); // save data-defined values at marker level QgsProperty ddSize( parentSymbol->type() == QgsSymbol::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedSize() : QgsProperty() ); QgsProperty ddAngle( parentSymbol->type() == QgsSymbol::Marker ? static_cast<QgsMarkerSymbol *>( parentSymbol )->dataDefinedAngle() : QgsProperty() ); QgsProperty ddWidth( parentSymbol->type() == QgsSymbol::Line ? static_cast<QgsLineSymbol *>( parentSymbol )->dataDefinedWidth() : QgsProperty() ); QgsSymbolLayer *newLayer = QgsApplication::symbolLayerRegistry()->defaultSymbolLayer( parentSymbol->type() ); if ( insertIdx == -1 ) parentSymbol->appendSymbolLayer( newLayer ); else parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer ); // restore data-defined values at marker level if ( ddSize ) static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedSize( ddSize ); if ( ddAngle ) static_cast<QgsMarkerSymbol *>( parentSymbol )->setDataDefinedAngle( ddAngle ); if ( ddWidth ) static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth ); SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer ); item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem ); item->updatePreview(); layersTree->setCurrentIndex( model->indexFromItem( newLayerItem ) ); updateUi(); updatePreview(); }
void QgsComposerSymbolItem::readXML( const QDomElement& itemElem ) { if ( itemElem.isNull() ) { return; } setText( itemElem.attribute( "text", "" ) ); setLayerID( itemElem.attribute( "layerId", "" ) ); QgsVectorLayer* vLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( mLayerID ) ); if ( vLayer ) { QDomElement symbolElem = itemElem.firstChildElement( "symbol" ); if ( !symbolElem.isNull() ) { QgsSymbol* symbol = new QgsSymbol( vLayer->geometryType() ); symbol->readXML( symbolElem, vLayer ); setSymbol( symbol ); //add icon switch ( symbol->type() ) { case QGis::Point: setIcon( QIcon( QPixmap::fromImage( symbol->getPointSymbolAsImage() ) ) ); break; case QGis::Line: setIcon( QIcon( QPixmap::fromImage( symbol->getLineSymbolAsImage() ) ) ); break; case QGis::Polygon: setIcon( QIcon( QPixmap::fromImage( symbol->getPolygonSymbolAsImage() ) ) ); break; case QGis::NoGeometry: setIcon( QIcon( QgsApplication::activeThemePath() + "/mIconTableLayer.png" ) ); break; case QGis::UnknownGeometry: // should not occur break; } } } }
QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const { QgsSymbol *s = mItem.symbol(); if ( !s ) { return QSizeF(); } // setup temporary render context QgsRenderContext context; context.setScaleFactor( settings.dpi() / 25.4 ); context.setRendererScale( settings.mapScale() ); context.setMapToPixel( QgsMapToPixel( 1 / ( settings.mmPerMapUnit() * context.scaleFactor() ) ) ); context.setForceVectorOutput( true ); context.setPainter( ctx ? ctx->painter : nullptr ); if ( ctx && ctx->context ) { context.setExpressionContext( ctx->context->expressionContext() ); } else { // setup a minimal expression context QgsExpressionContext expContext; expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( nullptr ) ); context.setExpressionContext( expContext ); } //Consider symbol size for point markers double height = settings.symbolSize().height(); double width = settings.symbolSize().width(); //Center small marker symbols double widthOffset = 0; double heightOffset = 0; if ( QgsMarkerSymbol *markerSymbol = dynamic_cast<QgsMarkerSymbol *>( s ) ) { // allow marker symbol to occupy bigger area if necessary double size = markerSymbol->size( context ) / context.scaleFactor(); height = size; width = size; if ( width < settings.symbolSize().width() ) { widthOffset = ( settings.symbolSize().width() - width ) / 2.0; } if ( height < settings.symbolSize().height() ) { heightOffset = ( settings.symbolSize().height() - height ) / 2.0; } } if ( ctx && ctx->painter ) { double currentXPosition = ctx->point.x(); double currentYCoord = ctx->point.y() + ( itemHeight - settings.symbolSize().height() ) / 2; QPainter *p = ctx->painter; //setup painter scaling to dots so that raster symbology is drawn to scale double dotsPerMM = context.scaleFactor(); int opacity = 255; if ( QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layerNode()->layer() ) ) opacity = ( 255 * vectorLayer->opacity() ); p->save(); p->setRenderHint( QPainter::Antialiasing ); p->translate( currentXPosition + widthOffset, currentYCoord + heightOffset ); p->scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM ); if ( opacity != 255 && settings.useAdvancedEffects() ) { //semi transparent layer, so need to draw symbol to an image (to flatten it first) //create image which is same size as legend rect, in case symbol bleeds outside its alloted space QSize tempImageSize( width * dotsPerMM, height * dotsPerMM ); QImage tempImage = QImage( tempImageSize, QImage::Format_ARGB32 ); tempImage.fill( Qt::transparent ); QPainter imagePainter( &tempImage ); context.setPainter( &imagePainter ); s->drawPreviewIcon( &imagePainter, tempImageSize, &context ); context.setPainter( ctx->painter ); //reduce opacity of image imagePainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); imagePainter.fillRect( tempImage.rect(), QColor( 0, 0, 0, opacity ) ); imagePainter.end(); //draw rendered symbol image p->drawImage( 0, 0, tempImage ); } else { s->drawPreviewIcon( p, QSize( width * dotsPerMM, height * dotsPerMM ), &context ); } if ( !mTextOnSymbolLabel.isEmpty() ) { QFontMetricsF fm( mTextOnSymbolTextFormat.scaledFont( context ) ); qreal yBaselineVCenter = ( height * dotsPerMM + fm.ascent() - fm.descent() ) / 2; QgsTextRenderer::drawText( QPointF( width * dotsPerMM / 2, yBaselineVCenter ), 0, QgsTextRenderer::AlignCenter, QStringList() << mTextOnSymbolLabel, context, mTextOnSymbolTextFormat ); } p->restore(); } return QSizeF( std::max( width + 2 * widthOffset, static_cast< double >( settings.symbolSize().width() ) ), std::max( height + 2 * heightOffset, static_cast< double >( settings.symbolSize().height() ) ) ); }
void QgsUniqueValueRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature& f, QImage* img, bool selected, double opacity ) { QPainter *p = renderContext.painter(); QgsSymbol* symbol = symbolForFeature( &f ); if ( !symbol ) //no matching symbol { if ( img && mGeometryType == QGis::Point ) { img->fill( 0 ); } else if ( mGeometryType != QGis::Point ) { p->setPen( Qt::NoPen ); p->setBrush( Qt::NoBrush ); } return; } // Point if ( img && mGeometryType == QGis::Point ) { double fieldScale = 1.0; double rotation = 0.0; if ( symbol->scaleClassificationField() >= 0 ) { //first find out the value for the scale classification attribute fieldScale = sqrt( qAbs( f.attribute( symbol->scaleClassificationField() ).toDouble() ) ); } if ( symbol->rotationClassificationField() >= 0 ) { rotation = f.attribute( symbol->rotationClassificationField() ).toDouble(); } QString oldName; if ( symbol->symbolField() >= 0 ) { QString name = f.attribute( symbol->symbolField() ).toString(); oldName = symbol->pointSymbolName(); symbol->setNamedPointSymbol( name ); } double scale = renderContext.scaleFactor(); if ( symbol->pointSizeUnits() ) { scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel(); } *img = symbol->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale, rotation, renderContext.rasterScaleFactor(), opacity ); if ( !oldName.isNull() ) { symbol->setNamedPointSymbol( oldName ); } } // Line, polygon else if ( mGeometryType != QGis::Point ) { if ( !selected ) { QPen pen = symbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); p->setPen( pen ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = symbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout p->setBrush( brush ); } } else { QPen pen = symbol->pen(); pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); if ( mGeometryType == QGis::Polygon ) { QBrush brush = symbol->brush(); scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout brush.setColor( mSelectionColor ); p->setBrush( brush ); } else //don't draw outlines of polygons in selection color otherwise they appear merged { pen.setColor( mSelectionColor ); } p->setPen( pen ); } } }
QgsUniqueValueDialog::QgsUniqueValueDialog( QgsVectorLayer* vl ): QDialog(), mVectorLayer( vl ), sydialog( vl, true ) { setupUi( this ); setOrientation( Qt::Vertical ); //find out the fields of mVectorLayer if ( mVectorLayer ) { //we cannot use unique values for not-commited fields because QgsVectorLayer has no 'unique values' method... QgsVectorDataProvider* provider = mVectorLayer->dataProvider(); if ( provider ) { const QgsFieldMap & fields = provider->fields(); QString str; for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it ) { str = ( *it ).name(); str = mVectorLayer->attributeDisplayName( it.key() ); mClassificationComboBox->addItem( str, it.key() ); } } } mClassListWidget->setSelectionMode( QAbstractItemView::ExtendedSelection ); mClassListWidget->setEditTriggers( QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed | QAbstractItemView::AnyKeyPressed ); mClassListWidget->setSortingEnabled( true ); if ( mVectorLayer ) { const QgsUniqueValueRenderer* renderer = dynamic_cast<const QgsUniqueValueRenderer *>( mVectorLayer->renderer() ); if ( renderer ) { mClassListWidget->clear(); QString field = mVectorLayer->attributeDisplayName( renderer->classificationField() ); mOldClassificationAttribute = field; mClassificationComboBox->setCurrentIndex( mClassificationComboBox->findText( field ) ); const QList<QgsSymbol*> list = renderer->symbols(); //fill the items of the renderer into mValues for ( QList<QgsSymbol*>::const_iterator iter = list.begin(); iter != list.end(); ++iter ) { QgsSymbol* symbol = *iter; QString symbolvalue = symbol->lowerValue(); QgsSymbol* sym = new QgsSymbol( mVectorLayer->geometryType(), symbol->lowerValue(), symbol->upperValue(), symbol->label() ); sym->setPen( symbol->pen() ); sym->setCustomTexture( symbol->customTexture() ); sym->setBrush( symbol->brush() ); sym->setNamedPointSymbol( symbol->pointSymbolName() ); sym->setPointSize( symbol->pointSize() ); sym->setPointSizeUnits( symbol->pointSizeUnits() ); sym->setScaleClassificationField( symbol->scaleClassificationField() ); sym->setRotationClassificationField( symbol->rotationClassificationField() ); mValues.insert( symbolvalue, sym ); QListWidgetItem *item = new QListWidgetItem( symbolvalue ); mClassListWidget->addItem( item ); updateEntryIcon( symbol, item ); item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled ); item->setData( Qt::UserRole, symbol->lowerValue() ); item->setToolTip( symbol->label() ); } } } mDeletePushButton->setEnabled( false ); connect( mClassifyButton, SIGNAL( clicked() ), this, SLOT( changeClassificationAttribute() ) ); connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addClass() ) ); connect( mDeletePushButton, SIGNAL( clicked() ), this, SLOT( deleteSelectedClasses() ) ); connect( mRandomizeColors, SIGNAL( clicked() ), this, SLOT( randomizeColors() ) ); connect( mResetColors, SIGNAL( clicked() ), this, SLOT( resetColors() ) ); connect( mClassListWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( selectionChanged() ) ); connect( mCommonPropertyLock, SIGNAL( clicked() ), this, SLOT( selectionChanged() ) ); connect( mClassListWidget, SIGNAL( itemChanged( QListWidgetItem * ) ), this, SLOT( itemChanged( QListWidgetItem * ) ) ); connect( &sydialog, SIGNAL( settingsChanged() ), this, SLOT( applySymbologyChanges() ) ); mSymbolWidgetStack->addWidget( &sydialog ); mSymbolWidgetStack->setCurrentWidget( &sydialog ); }
void QgsUniqueValueDialog::apply() { QgsDebugMsg( "called." ); QgsUniqueValueRenderer *renderer = new QgsUniqueValueRenderer( mVectorLayer->geometryType() ); //go through mValues and add the entries to the renderer for ( QMap<QString, QgsSymbol*>::iterator it = mValues.begin(); it != mValues.end(); ++it ) { QgsSymbol* symbol = it.value(); QgsSymbol* newsymbol = new QgsSymbol( mVectorLayer->geometryType(), symbol->lowerValue(), symbol->upperValue(), symbol->label() ); newsymbol->setPen( symbol->pen() ); newsymbol->setCustomTexture( symbol->customTexture() ); newsymbol->setBrush( symbol->brush() ); newsymbol->setNamedPointSymbol( symbol->pointSymbolName() ); newsymbol->setPointSize( symbol->pointSize() ); newsymbol->setPointSizeUnits( symbol->pointSizeUnits() ); newsymbol->setScaleClassificationField( symbol->scaleClassificationField() ); newsymbol->setRotationClassificationField( symbol->rotationClassificationField() ); renderer->insertValue( it.key(), newsymbol ); } renderer->updateSymbolAttributes(); QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>( mVectorLayer->dataProvider() ); if ( provider ) { int fieldIndex = mClassificationComboBox->itemData( mClassificationComboBox->currentIndex() ).toInt(); if ( fieldIndex != -1 ) { renderer->setClassificationField( fieldIndex ); mVectorLayer->setRenderer( renderer ); return; } } delete renderer; //something went wrong }
void QgsVectorLayerRenderer::drawRendererLevels( QgsFeatureIterator &fit ) { QHash< QgsSymbol *, QList<QgsFeature> > features; // key = symbol, value = array of features QgsSingleSymbolRenderer *selRenderer = nullptr; if ( !mSelectedFeatureIds.isEmpty() ) { selRenderer = new QgsSingleSymbolRenderer( QgsSymbol::defaultSymbol( mGeometryType ) ); selRenderer->symbol()->setColor( mContext.selectionColor() ); selRenderer->setVertexMarkerAppearance( mVertexMarkerStyle, mVertexMarkerSize ); selRenderer->startRender( mContext, mFields ); } QgsExpressionContextScope *symbolScope = QgsExpressionContextUtils::updateSymbolScope( nullptr, new QgsExpressionContextScope() ); mContext.expressionContext().appendScope( symbolScope ); // 1. fetch features QgsFeature fet; while ( fit.nextFeature( fet ) ) { if ( mContext.renderingStopped() ) { qDebug( "rendering stop!" ); stopRenderer( selRenderer ); delete mContext.expressionContext().popScope(); return; } if ( !fet.hasGeometry() ) continue; // skip features without geometry mContext.expressionContext().setFeature( fet ); QgsSymbol *sym = mRenderer->symbolForFeature( fet, mContext ); if ( !sym ) { continue; } if ( !features.contains( sym ) ) { features.insert( sym, QList<QgsFeature>() ); } features[sym].append( fet ); // new labeling engine if ( mContext.labelingEngine() ) { QgsGeometry obstacleGeometry; QgsSymbolList symbols = mRenderer->originalSymbolsForFeature( fet, mContext ); if ( !symbols.isEmpty() && fet.geometry().type() == QgsWkbTypes::PointGeometry ) { obstacleGeometry = QgsVectorLayerLabelProvider::getPointObstacleGeometry( fet, mContext, symbols ); } if ( !symbols.isEmpty() ) { QgsExpressionContextUtils::updateSymbolScope( symbols.at( 0 ), symbolScope ); } if ( mLabelProvider ) { mLabelProvider->registerFeature( fet, mContext, obstacleGeometry ); } if ( mDiagramProvider ) { mDiagramProvider->registerFeature( fet, mContext, obstacleGeometry ); } } } delete mContext.expressionContext().popScope(); if ( features.empty() ) { // nothing to draw stopRenderer( selRenderer ); return; } // find out the order QgsSymbolLevelOrder levels; QgsSymbolList symbols = mRenderer->symbols( mContext ); for ( int i = 0; i < symbols.count(); i++ ) { QgsSymbol *sym = symbols[i]; for ( int j = 0; j < sym->symbolLayerCount(); j++ ) { int level = sym->symbolLayer( j )->renderingPass(); if ( level < 0 || level >= 1000 ) // ignore invalid levels continue; QgsSymbolLevelItem item( sym, j ); while ( level >= levels.count() ) // append new empty levels levels.append( QgsSymbolLevel() ); levels[level].append( item ); } } // 2. draw features in correct order for ( int l = 0; l < levels.count(); l++ ) { QgsSymbolLevel &level = levels[l]; for ( int i = 0; i < level.count(); i++ ) { QgsSymbolLevelItem &item = level[i]; if ( !features.contains( item.symbol() ) ) { QgsDebugMsg( QStringLiteral( "level item's symbol not found!" ) ); continue; } int layer = item.layer(); QList<QgsFeature> &lst = features[item.symbol()]; QList<QgsFeature>::iterator fit; for ( fit = lst.begin(); fit != lst.end(); ++fit ) { if ( mContext.renderingStopped() ) { stopRenderer( selRenderer ); return; } bool sel = mContext.showSelection() && mSelectedFeatureIds.contains( fit->id() ); // maybe vertex markers should be drawn only during the last pass... bool drawMarker = ( mDrawVertexMarkers && mContext.drawEditingInformation() && ( !mVertexMarkerOnlyForSelection || sel ) ); mContext.expressionContext().setFeature( *fit ); try { mRenderer->renderFeature( *fit, mContext, layer, sel, drawMarker ); } catch ( const QgsCsException &cse ) { Q_UNUSED( cse ); QgsDebugMsg( QStringLiteral( "Failed to transform a point while drawing a feature with ID '%1'. Ignoring this feature. %2" ) .arg( fet.id() ).arg( cse.what() ) ); } } } } stopRenderer( selRenderer ); }
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 ); }