void QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPoint* center ) { QgsRectangle r = mapSettings().extent(); r.scale( scaleFactor, center ); setExtent( r ); refresh(); }
QgsMapLayer* QgsMapCanvas::layer( int index ) { const QStringList& layers = mapSettings().layers(); if ( index >= 0 && index < ( int ) layers.size() ) return QgsMapLayerRegistry::instance()->mapLayer( layers[index] ); else return NULL; }
QgsMapLayer* QgsMapCanvas::layer( int index ) { QList<QgsMapLayer*> layers = mapSettings().layers(); if ( index >= 0 && index < ( int ) layers.size() ) return layers[index]; else return nullptr; }
QList<QgsMapLayer*> QgsMapCanvas::layers() const { QList<QgsMapLayer*> lst; Q_FOREACH ( const QString& layerID, mapSettings().layers() ) { QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID ); if ( layer ) lst.append( layer ); } return lst; }
void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn ) { double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor ); // transform the mouse pos to map coordinates QgsPoint center = getCoordinateTransform()->toMapPoint( x, y ); QgsRectangle r = mapSettings().visibleExtent(); r.scale( scaleFactor, ¢er ); setExtent( r ); refresh(); }
void QgsMapCanvas::setCenter( const QgsPoint& center ) { QgsRectangle r = mapSettings().extent(); double x = center.x(); double y = center.y(); setExtent( QgsRectangle( x - r.width() / 2.0, y - r.height() / 2.0, x + r.width() / 2.0, y + r.height() / 2.0 ) ); } // setCenter
void QgsQuickPositionKit::updateScreenPosition() { if ( !mMapSettings ) return; QPointF screenPosition = mapSettings()->coordinateToScreen( projectedPosition() ); if ( screenPosition != mScreenPosition ) { mScreenPosition = screenPosition; emit screenPositionChanged(); } }
DediArkMainWindow::DediArkMainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::DediArkMainWindow) { ui->setupUi(this); container = SettingContainer::DefaultSettings(); initMapping(); mapSettings(); ui->scrollAreaWidgetContents->setLayout(ui->verticalSettings); ui->tabServerSetting->setLayout(ui->layoutSettings); }
//the format defaults to "PNG" if not specified void QgsMapCanvas::saveAsImage( const QString& theFileName, QPixmap * theQPixmap, const QString& theFormat ) { // //check if the optional QPaintDevice was supplied // if ( theQPixmap != NULL ) { // render QPainter painter; painter.begin( theQPixmap ); QgsMapRendererCustomPainterJob job( mSettings, &painter ); job.start(); job.waitForFinished(); emit renderComplete( &painter ); painter.end(); theQPixmap->save( theFileName, theFormat.toLocal8Bit().data() ); } else //use the map view { mMap->contentImage().save( theFileName, theFormat.toLocal8Bit().data() ); } //create a world file to go with the image... QgsRectangle myRect = mapSettings().visibleExtent(); QString myHeader; // note: use 17 places of precision for all numbers output //Pixel XDim myHeader += qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n"; //Rotation on y axis - hard coded myHeader += "0 \r\n"; //Rotation on x axis - hard coded myHeader += "0 \r\n"; //Pixel YDim - almost always negative - see //http://en.wikipedia.org/wiki/World_file#cite_note-2 myHeader += '-' + qgsDoubleToString( mapUnitsPerPixel() ) + "\r\n"; //Origin X (center of top left cell) myHeader += qgsDoubleToString( myRect.xMinimum() + ( mapUnitsPerPixel() / 2 ) ) + "\r\n"; //Origin Y (center of top left cell) myHeader += qgsDoubleToString( myRect.yMaximum() - ( mapUnitsPerPixel() / 2 ) ) + "\r\n"; QFileInfo myInfo = QFileInfo( theFileName ); // allow dotted names QString myWorldFileName = myInfo.absolutePath() + '/' + myInfo.completeBaseName() + '.' + theFormat + 'w'; QFile myWorldFile( myWorldFileName ); if ( !myWorldFile.open( QIODevice::WriteOnly ) ) //don't use QIODevice::Text { return; } QTextStream myStream( &myWorldFile ); myStream << myHeader; } // saveAsImage
void QgsMapCanvas::zoomToSelected( QgsVectorLayer* layer ) { if ( layer == NULL ) { // use current layer by default layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer ); } if ( layer == NULL ) { return; } if ( layer->selectedFeatureCount() == 0 ) { return; } QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, layer->boundingBoxOfSelected() ); // no selected features, only one selected point feature //or two point features with the same x- or y-coordinates if ( rect.isEmpty() ) { // zoom in QgsPoint c = rect.center(); rect = extent(); rect.scale( 1.0, &c ); } //zoom to an area else { // Expand rect to give a bit of space around the selected // objects so as to keep them clear of the map boundaries // The same 5% should apply to all margins. rect.scale( 1.05 ); } setExtent( rect ); refresh(); } // zoomToSelected
void QgsMapCanvas::panToSelected( QgsVectorLayer* layer ) { if ( layer == NULL ) { // use current layer by default layer = qobject_cast<QgsVectorLayer *>( mCurrentLayer ); } if ( layer == NULL ) { return; } if ( layer->selectedFeatureCount() == 0 ) { return; } QgsRectangle rect = mapSettings().layerExtentToOutputExtent( layer, layer->boundingBoxOfSelected() ); setExtent( QgsRectangle( rect.center(), rect.center() ) ); refresh(); } // panToSelected
void QgsMapCanvas::setLayerSet( QList<QgsMapCanvasLayer> &layers ) { // create layer set QStringList layerSet, layerSetOverview; int i; for ( i = 0; i < layers.size(); i++ ) { QgsMapCanvasLayer &lyr = layers[i]; if ( !lyr.layer() ) { continue; } if ( lyr.isVisible() ) { layerSet.push_back( lyr.layer()->id() ); } if ( lyr.isInOverview() ) { layerSetOverview.push_back( lyr.layer()->id() ); } } const QStringList& layerSetOld = mapSettings().layers(); bool layerSetChanged = layerSetOld != layerSet; // update only if needed if ( layerSetChanged ) { QgsDebugMsg( "Layers changed to: " + layerSet.join( ", " ) ); for ( i = 0; i < layerCount(); i++ ) { // Add check if vector layer when disconnecting from selectionChanged slot // Ticket #811 - racicot QgsMapLayer *currentLayer = layer( i ); if ( !currentLayer ) continue; disconnect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) ); disconnect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) ); QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer ); if ( isVectLyr ) { disconnect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) ); } } mSettings.setLayers( layerSet ); for ( i = 0; i < layerCount(); i++ ) { // Add check if vector layer when connecting to selectionChanged slot // Ticket #811 - racicot QgsMapLayer *currentLayer = layer( i ); connect( currentLayer, SIGNAL( repaintRequested() ), this, SLOT( refresh() ) ); connect( currentLayer, SIGNAL( layerCrsChanged() ), this, SLOT( layerCrsChange() ) ); QgsVectorLayer *isVectLyr = qobject_cast<QgsVectorLayer *>( currentLayer ); if ( isVectLyr ) { connect( currentLayer, SIGNAL( selectionChanged() ), this, SLOT( selectionChangedSlot() ) ); } } updateDatumTransformEntries(); QgsDebugMsg( "Layers have changed, refreshing" ); emit layersChanged(); refresh(); } if ( mMapOverview ) { const QStringList& layerSetOvOld = mMapOverview->layerSet(); if ( layerSetOvOld != layerSetOverview ) { mMapOverview->setLayerSet( layerSetOverview ); } // refresh overview maplayers even if layer set is the same // because full extent might have changed updateOverview(); } } // setLayerSet
double QgsMapCanvas::mapUnitsPerPixel() const { return mapSettings().mapUnitsPerPixel(); } // mapUnitsPerPixel
int QgsMapCanvas::layerCount() const { return mapSettings().layers().size(); } // layerCount
double QgsMapCanvas::rotation() const { return mapSettings().rotation(); } // rotation
void QgsMapCanvas::updateScale() { emit scaleChanged( mapSettings().scale() ); }
QGis::UnitType QgsMapCanvas::mapUnits() const { return mapSettings().mapUnits(); }
QgsPoint QgsMapCanvas::center() const { QgsRectangle r = mapSettings().extent(); return r.center(); }
QgsRectangle QgsMapCanvas::fullExtent() const { return mapSettings().fullExtent(); } // extent
QgsRectangle QgsMapCanvas::extent() const { return mapSettings().visibleExtent(); } // extent
void QgsMapCanvas::keyPressEvent( QKeyEvent * e ) { if ( mCanvasProperties->mouseButtonDown || mCanvasProperties->panSelectorDown ) { emit keyPressed( e ); return; } QPainter paint; QPen pen( Qt::gray ); QgsPoint ll, ur; if ( ! mCanvasProperties->mouseButtonDown ) { // Don't want to interfer with mouse events QgsRectangle currentExtent = mapSettings().visibleExtent(); double dx = qAbs(( currentExtent.xMaximum() - currentExtent.xMinimum() ) / 4 ); double dy = qAbs(( currentExtent.yMaximum() - currentExtent.yMinimum() ) / 4 ); switch ( e->key() ) { case Qt::Key_Left: QgsDebugMsg( "Pan left" ); currentExtent.setXMinimum( currentExtent.xMinimum() - dx ); currentExtent.setXMaximum( currentExtent.xMaximum() - dx ); setExtent( currentExtent ); refresh(); break; case Qt::Key_Right: QgsDebugMsg( "Pan right" ); currentExtent.setXMinimum( currentExtent.xMinimum() + dx ); currentExtent.setXMaximum( currentExtent.xMaximum() + dx ); setExtent( currentExtent ); refresh(); break; case Qt::Key_Up: QgsDebugMsg( "Pan up" ); currentExtent.setYMaximum( currentExtent.yMaximum() + dy ); currentExtent.setYMinimum( currentExtent.yMinimum() + dy ); setExtent( currentExtent ); refresh(); break; case Qt::Key_Down: QgsDebugMsg( "Pan down" ); currentExtent.setYMaximum( currentExtent.yMaximum() - dy ); currentExtent.setYMinimum( currentExtent.yMinimum() - dy ); setExtent( currentExtent ); refresh(); break; case Qt::Key_Space: QgsDebugMsg( "Pressing pan selector" ); //mCanvasProperties->dragging = true; if ( ! e->isAutoRepeat() ) { mCanvasProperties->panSelectorDown = true; mCanvasProperties->rubberStartPoint = mCanvasProperties->mouseLastXY; } break; case Qt::Key_PageUp: QgsDebugMsg( "Zoom in" ); zoomIn(); break; case Qt::Key_PageDown: QgsDebugMsg( "Zoom out" ); zoomOut(); break; #if 0 case Qt::Key_P: mUseParallelRendering = !mUseParallelRendering; refresh(); break; case Qt::Key_S: mDrawRenderingStats = !mDrawRenderingStats; refresh(); break; #endif default: // Pass it on if ( mMapTool ) { mMapTool->keyPressEvent( e ); } else e->ignore(); QgsDebugMsg( "Ignoring key: " + QString::number( e->key() ) ); } } emit keyPressed( e ); } //keyPressEvent()
bool QgsMapCanvas::hasCrsTransformEnabled() { return mapSettings().hasCrsTransformEnabled(); }
double QgsMapCanvas::scale() { return mapSettings().scale(); } // scale
// return the current coordinate transform based on the extents and // device size const QgsMapToPixel * QgsMapCanvas::getCoordinateTransform() { return &mapSettings().mapToPixel(); }
void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale ) { //Lock render method for concurrent threads (e.g. from globe) QMutexLocker renderLock( &mRenderMutex ); 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 ); } if ( mRenderContext.scaleFactor() != scaleFactor ) { mRenderContext.setScaleFactor( scaleFactor ); } if ( mRenderContext.rendererScale() != mScale ) { //add map scale to render context mRenderContext.setRendererScale( mScale ); } if ( mLastExtent != mExtent ) { mLastExtent = mExtent; } mRenderContext.setLabelingEngine( mLabelingEngine ); if ( mLabelingEngine ) mLabelingEngine->init( mapSettings() ); // 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; } QSettings mySettings; // 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 ((( 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 ( 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 ) ) ); } else // layer not visible due to scale {