Exemple #1
0
void QgsComposerLabel::refreshExpressionContext()
{
  if ( !mComposition )
    return;

  QgsVectorLayer *layer = nullptr;
  if ( mComposition->atlasComposition().enabled() )
  {
    layer = mComposition->atlasComposition().coverageLayer();
  }

  //setup distance area conversion
  if ( layer )
  {
    mDistanceArea->setSourceCrs( layer->crs() );
  }
  else
  {
    //set to composition's reference map's crs
    QgsComposerMap *referenceMap = mComposition->referenceMap();
    if ( referenceMap )
      mDistanceArea->setSourceCrs( referenceMap->crs() );
  }
  mDistanceArea->setEllipsoid( mComposition->project()->ellipsoid() );
  contentChanged();

  update();
}
Exemple #2
0
/*
 * Estimate a good default radius for the heatmap, based on the
 * bounding box size of the layer
 */
double HeatmapGui::estimateRadius()
{

  QgsVectorLayer *inputLayer = inputVectorLayer();

  // No input layer? Default to radius of 100
  if ( !inputLayer )
    return 100;

  // Find max dimension of layer bounding box
  QgsRectangle mExtent = inputLayer->extent();
  double maxExtent = max( mExtent.width(), mExtent.height() );

  // Return max dimension divided by 30. This is fairly arbitrary
  // but approximately corresponds to the default value chosen by ArcMap
  // TODO - a better solution is to let the data define the radius
  // choice by setting the radius equal to the average Nearest
  // Neighbour Index for the closest n points

  double estimate = maxExtent / 30;

  if ( mBufferUnitCombo->currentIndex() == HeatmapGui::LayerUnits )
  {
    // layer units selected, so convert estimate from map units
    QgsCoordinateReferenceSystem layerCrs = inputLayer->crs();
    estimate /= mapUnitsOf( 1, layerCrs );
  }

  // Make estimate pretty by rounding off to first digit only (eg 356->300, 0.567->0.5)
  double tens = pow( 10, floor( log10( estimate ) ) );
  return floor( estimate / tens + 0.5 ) * tens;
}
void RgShortestPathWidget::exportPath()
{
  RgExportDlg dlg( this );
  if ( !dlg.exec() )
    return;

  QgsVectorLayer *vl = dlg.mapLayer();
  if ( vl == NULL )
    return;

  QgsPoint p1, p2;
  QgsGraph *path = getPath( p1, p2 );
  if ( path == NULL )
    return;

  QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(),
                             vl->crs() );

  int startVertexIdx = path->findVertex( p1 );
  int stopVertexIdx  = path->findVertex( p2 );

  double time = 0.0;
  double cost = 0.0;

  Unit timeUnit = Unit::byName( mPlugin->timeUnitName() );
  Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() );

  QgsPolyline p;
  while ( startVertexIdx != stopVertexIdx )
  {
    if ( stopVertexIdx < 0 )
      break;

    QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc();
    if ( l.empty() )
      break;
    const QgsGraphArc& e = path->arc( l.front() );

    cost += e.property( 0 ).toDouble();
    time += e.property( 1 ).toDouble();

    p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) );
    stopVertexIdx = e.outVertex();
  }
  p.push_front( ct.transform( p1 ) );

  QgsFeature f;
  f.initAttributes( vl->pendingFields().count() );
  f.setGeometry( QgsGeometry::fromPolyline( p ) );
  f.setAttribute( 0, cost / distanceUnit.multipler() );
  f.setAttribute( 1, time / timeUnit.multipler() );
  QgsFeatureList features;
  features << f;
  vl->dataProvider()->addFeatures( features );
  vl->updateExtents();

  mPlugin->iface()->mapCanvas()->update();
  delete path;
}
Exemple #4
0
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;
  }
}
Exemple #5
0
void HeatmapGui::updateBBox()
{
  // Set the row/cols and cell sizes here
  QgsVectorLayer *inputLayer = inputVectorLayer();
  if ( !inputLayer )
    return;

  mBBox = inputLayer->extent();
  QgsCoordinateReferenceSystem layerCrs = inputLayer->crs();

  double radiusInMapUnits = 0.0;
  if ( mRadiusFieldCheckBox->isChecked() )
  {
    int idx = inputLayer->fields().indexFromName( mRadiusFieldCombo->currentField() );
    double maxInField = inputLayer->maximumValue( idx ).toDouble();

    if ( mRadiusFieldUnitCombo->currentIndex() == HeatmapGui::LayerUnits )
    {
      radiusInMapUnits = mapUnitsOf( maxInField, layerCrs );
    }
    else if ( mRadiusFieldUnitCombo->currentIndex() == HeatmapGui::MapUnits )
    {
      radiusInMapUnits = maxInField;
    }
  }
  else
  {
    double radiusValue = mBufferSizeLineEdit->text().toDouble();
    if ( mBufferUnitCombo->currentIndex() == HeatmapGui::LayerUnits )
    {
      radiusInMapUnits = mapUnitsOf( radiusValue, layerCrs );
    }
    else if ( mBufferUnitCombo->currentIndex() == HeatmapGui::MapUnits )
    {
      radiusInMapUnits = radiusValue;
    }
  }
  // get the distance converted into map units
  mBBox.setXMinimum( mBBox.xMinimum() - radiusInMapUnits );
  mBBox.setYMinimum( mBBox.yMinimum() - radiusInMapUnits );
  mBBox.setXMaximum( mBBox.xMaximum() + radiusInMapUnits );
  mBBox.setYMaximum( mBBox.yMaximum() + radiusInMapUnits );

  // Leave number of rows the same, and calculate new corresponding cell size and number of columns
  mYcellsize = mBBox.height() / ( mRows - 1 );
  mXcellsize = mYcellsize;
  mColumns = max( mBBox.width() / mXcellsize + 1, 1 );
  updateSize();
}
QSGNode* FeatureListModelHighlight::updatePaintNode( QSGNode* n, QQuickItem::UpdatePaintNodeData* )
{
  if ( mDirty && mMapSettings )
  {
    delete n;
    n = new QSGNode;

    int count = mModel->rowCount( QModelIndex() );
    QgsSGGeometry* sn = 0;

    QModelIndex firstIndex = mModel->index( 0, 0, QModelIndex() );
    QgsVectorLayer* layer = mModel->data( firstIndex, MultiFeatureListModel::LayerRole ).value<QgsVectorLayer*>();
    if ( layer )
    {
      QgsCoordinateTransform transf( layer->crs(), mMapSettings->destinationCrs() );

      for ( int i = 0; i < count; ++i )
      {
        QgsSGGeometry* gn;

        QModelIndex index = mModel->index( i, 0, QModelIndex() );
        QgsFeature feature = mModel->data( index, MultiFeatureListModel::FeatureRole ).value<QgsFeature>();

        QgsGeometry geom( feature.geometry() );
        geom.transform( transf );

        if ( mSelection && mSelection->selection() == i )
        {
          sn = new QgsSGGeometry( geom, mSelectionColor, mWidth );
          sn->setFlag( QSGNode::OwnedByParent );
        }
        else
        {
          gn = new QgsSGGeometry( geom, mColor, mWidth );
          gn->setFlag( QSGNode::OwnedByParent );
          n->appendChildNode( gn );
        }
      }

      if ( sn )
        n->appendChildNode( sn );
    }
    mDirty = false;
  }

  return n;
}
void RgShortestPathWidget::exportPath()
{
  RgExportDlg dlg( this );
  if ( !dlg.exec() )
    return;

  QgsVectorLayer *vl = dlg.mapLayer();
  if ( vl == NULL )
    return;

  QgsPoint p1, p2;
  QgsGraph *path = getPath( p1, p2 );
  if ( path == NULL )
    return;

  QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapRenderer()->destinationCrs(),
                             vl->crs() );

  int startVertexIdx = path->findVertex( p1 );
  int stopVertexIdx  = path->findVertex( p2 );

  QgsPolyline p;
  while ( startVertexIdx != stopVertexIdx )
  {
    QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc();
    if ( l.empty() )
      break;
    const QgsGraphArc& e = path->arc( l.front() );
    p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) );
    stopVertexIdx = e.outVertex();
  }
  p.push_front( ct.transform( p1 ) );

  vl->startEditing();
  QgsFeature f;
  f.setGeometry( QgsGeometry::fromPolyline( p ) );
  vl->addFeature( f );
  vl->updateExtents();

  mPlugin->iface()->mapCanvas()->update();
  delete path;
}
QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check,
    const QgsGeometryCheckerUtils::LayerFeature &layerFeature,
    const QgsPointXY &errorLocation,
    QgsVertexId vidx,
    const QVariant &value,
    ValueType valueType )
  : mCheck( check )
  , mLayerId( layerFeature.layerId() )
  , mFeatureId( layerFeature.feature().id() )
  , mErrorLocation( errorLocation )
  , mVidx( vidx )
  , mValue( value )
  , mValueType( valueType )
  , mStatus( StatusPending )
{
  if ( vidx.part != -1 )
  {
    mGeometry = QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( layerFeature.geometry().constGet(), vidx.part )->clone() );
  }
  else
  {
    mGeometry = layerFeature.geometry();
  }
  if ( !layerFeature.useMapCrs() )
  {
    QgsVectorLayer *vl = layerFeature.layer().data();
    if ( vl )
    {
      QgsCoordinateTransform ct( vl->crs(), check->context()->mapCrs, check->context()->transformContext );
      try
      {
        mGeometry.transform( ct );
        mErrorLocation = ct.transform( mErrorLocation );
      }
      catch ( const QgsCsException &e )
      {
        QgsDebugMsg( QStringLiteral( "Can not show error in current map coordinate reference system" ) );
      }
    }
  }
}
void QgsLayoutItemLabel::refreshExpressionContext()
{
  if ( !mLayout )
    return;

  QgsVectorLayer *layer = mLayout->reportContext().layer();
  //setup distance area conversion
  if ( layer )
  {
    mDistanceArea->setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
  }
  else
  {
    //set to composition's reference map's crs
    QgsLayoutItemMap *referenceMap = mLayout->referenceMap();
    if ( referenceMap )
      mDistanceArea->setSourceCrs( referenceMap->crs(), mLayout->project()->transformContext() );
  }
  mDistanceArea->setEllipsoid( mLayout->project()->ellipsoid() );
  contentChanged();

  update();
}
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 QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &contents )
{
  contents.clear();

  if (( mSource == QgsComposerAttributeTableV2::AtlasFeature || mSource == QgsComposerAttributeTableV2::RelationChildren )
      && !mComposition->atlasComposition().enabled() )
  {
    //source mode requires atlas, but atlas disabled
    return false;
  }

  QgsVectorLayer* layer = sourceLayer();

  if ( !layer )
  {
    //no source layer
    return false;
  }

  //prepare filter expression
  std::auto_ptr<QgsExpression> filterExpression;
  bool activeFilter = false;
  if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
  {
    filterExpression = std::auto_ptr<QgsExpression>( new QgsExpression( mFeatureFilter ) );
    if ( !filterExpression->hasParserError() )
    {
      activeFilter = true;
    }
  }

  QgsRectangle selectionRect;
  if ( mComposerMap && mShowOnlyVisibleFeatures )
  {
    selectionRect = *mComposerMap->currentMapExtent();
    if ( layer && mComposition->mapSettings().hasCrsTransformEnabled() )
    {
      //transform back to layer CRS
      QgsCoordinateTransform coordTransform( layer->crs(), mComposition->mapSettings().destinationCrs() );
      try
      {
        selectionRect = coordTransform.transformBoundingBox( selectionRect, QgsCoordinateTransform::ReverseTransform );
      }
      catch ( QgsCsException &cse )
      {
        Q_UNUSED( cse );
        return false;
      }
    }
  }

  QgsFeatureRequest req;

  if ( mSource == QgsComposerAttributeTableV2::RelationChildren )
  {
    QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId );
    QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
    if ( atlasFeature )
    {
      req = relation.getRelatedFeaturesRequest( *atlasFeature );
    }
    else
    {
      //no atlas feature, so empty table
      return true;
    }
  }

  if ( !selectionRect.isEmpty() )
    req.setFilterRect( selectionRect );

  req.setFlags( mShowOnlyVisibleFeatures ? QgsFeatureRequest::ExactIntersect : QgsFeatureRequest::NoFlags );

  if ( mSource == QgsComposerAttributeTableV2::AtlasFeature
       && mComposition->atlasComposition().enabled() )
  {
    //source mode is current atlas feature
    QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
    if ( atlasFeature )
    {
      req.setFilterFid( atlasFeature->id() );
    }
    else
    {
      //no atlas feature, so empty table
      return true;
    }
  }

  QgsFeature f;
  int counter = 0;
  QgsFeatureIterator fit = layer->getFeatures( req );

  while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
  {
    //check feature against filter
    if ( activeFilter )
    {
      QVariant result = filterExpression->evaluate( &f, layer->pendingFields() );
      // skip this feature if the filter evaluation is false
      if ( !result.toBool() )
      {
        continue;
      }
    }
    //check against atlas feature intersection
    if ( mFilterToAtlasIntersection )
    {
      if ( !f.geometry() || ! mComposition->atlasComposition().enabled() )
      {
        continue;
      }
      QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
      if ( !atlasFeature || !atlasFeature->geometry() ||
           !f.geometry()->intersects( atlasFeature->geometry() ) )
      {
        //feature falls outside current atlas feature
        continue;
      }
    }

    QgsComposerTableRow currentRow;

    QList<QgsComposerTableColumn*>::const_iterator columnIt = mColumns.constBegin();
    for ( ; columnIt != mColumns.constEnd(); ++columnIt )
    {
      int idx = layer->fieldNameIndex(( *columnIt )->attribute() );
      if ( idx != -1 )
      {
        currentRow << f.attributes()[idx];
      }
      else
      {
        // Lets assume it's an expression
        QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() );
        expression->setCurrentRowNumber( counter + 1 );
        expression->prepare( layer->pendingFields() );
        QVariant value = expression->evaluate( f ) ;
        currentRow << value;
      }
    }

    if ( !mShowUniqueRowsOnly || !contentsContainsRow( contents, currentRow ) )
    {
      contents << currentRow;
      ++counter;
    }
  }

  //sort the list, starting with the last attribute
  QgsComposerAttributeTableCompareV2 c;
  QList< QPair<int, bool> > sortColumns = sortAttributes();
  for ( int i = sortColumns.size() - 1; i >= 0; --i )
  {
    c.setSortColumn( sortColumns.at( i ).first );
    c.setAscending( sortColumns.at( i ).second );
    qStableSort( contents.begin(), contents.end(), c );
  }

  recalculateTableSize();
  return true;
}
Exemple #12
0
void QgsMapToolSelectUtils::setSelectFeatures( QgsMapCanvas* canvas,
    QgsGeometry* selectGeometry,
    bool doContains,
    bool doDifference,
    bool singleSelect )
{
  if ( selectGeometry->type() != QGis::Polygon )
  {
    return;
  }
  QgsVectorLayer* vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas );
  if ( vlayer == NULL )
  {
    return;
  }

  // toLayerCoordinates will throw an exception for any 'invalid' points in
  // the rubber band.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  QgsGeometry selectGeomTrans( *selectGeometry );

  if ( canvas->mapSettings().hasCrsTransformEnabled() )
  {
    try
    {
      QgsCoordinateTransform ct( canvas->mapSettings().destinationCrs(), vlayer->crs() );
      selectGeomTrans.transform( ct );
    }
    catch ( QgsCsException &cse )
    {
      Q_UNUSED( cse );
      // catch exception for 'invalid' point and leave existing selection unchanged
      QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) );
      QgisApp::instance()->messageBar()->pushMessage(
        QObject::tr( "CRS Exception" ),
        QObject::tr( "Selection extends beyond layer's coordinate system" ),
        QgsMessageBar::WARNING,
        QgisApp::instance()->messageTimeout() );
      return;
    }
  }

  QApplication::setOverrideCursor( Qt::WaitCursor );

  QgsDebugMsg( "Selection layer: " + vlayer->name() );
  QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() );
  QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) );
  QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) );

  QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectGeomTrans.boundingBox() ).setFlags( QgsFeatureRequest::ExactIntersect ).setSubsetOfAttributes( QgsAttributeList() ) );

  QgsFeatureIds newSelectedFeatures;
  QgsFeature f;
  QgsFeatureId closestFeatureId = 0;
  bool foundSingleFeature = false;
  double closestFeatureDist = std::numeric_limits<double>::max();
  while ( fit.nextFeature( f ) )
  {
    QgsGeometry* g = f.geometry();
    if ( doContains )
    {
      if ( !selectGeomTrans.contains( g ) )
        continue;
    }
    else
    {
      if ( !selectGeomTrans.intersects( g ) )
        continue;
    }
    if ( singleSelect )
    {
      foundSingleFeature = true;
      double distance = g->distance( selectGeomTrans );
      if ( distance <= closestFeatureDist )
      {
        closestFeatureDist = distance;
        closestFeatureId = f.id();
      }
    }
    else
    {
      newSelectedFeatures.insert( f.id() );
    }
  }
  if ( singleSelect && foundSingleFeature )
  {
    newSelectedFeatures.insert( closestFeatureId );
  }

  QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) );

  if ( doDifference )
  {
    QgsFeatureIds layerSelectedFeatures = vlayer->selectedFeaturesIds();

    QgsFeatureIds selectedFeatures;
    QgsFeatureIds deselectedFeatures;

    QgsFeatureIds::const_iterator i = newSelectedFeatures.constEnd();
    while ( i != newSelectedFeatures.constBegin() )
    {
      --i;
      if ( layerSelectedFeatures.contains( *i ) )
      {
        deselectedFeatures.insert( *i );
      }
      else
      {
        selectedFeatures.insert( *i );
      }
    }

    vlayer->modifySelection( selectedFeatures, deselectedFeatures );
  }
  else
  {
    vlayer->setSelectedFeatures( newSelectedFeatures );
  }

  QApplication::restoreOverrideCursor();
}
void QgsBrowserDockWidget::showProperties( )
{
  QgsDebugMsg( "Entered" );
  QgsDataItem* dataItem = mModel->dataItem( mBrowserView->currentIndex() );

  if ( dataItem != NULL && dataItem->type() == QgsDataItem::Layer )
  {
    QgsLayerItem *layerItem = qobject_cast<QgsLayerItem*>( dataItem );
    if ( layerItem != NULL )
    {
      QgsMapLayer::LayerType type = layerItem->mapLayerType();
      QString layerMetadata = tr( "Error" );
      QgsCoordinateReferenceSystem layerCrs;
      QString notice;

      // 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 != NULL )
        {
          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 != NULL )
        {
          layerCrs = layer->crs();
          layerMetadata = layer->metadata();
          delete layer;
        }
      }

      // restore /Projections/defaultBehaviour
      if ( defaultProjectionOption == "prompt" )
      {
        settings.setValue( "/Projections/defaultBehaviour", defaultProjectionOption );
      }

      // initialize dialog
      QDialog *dialog = new QDialog( this );
      Ui::QgsBrowserLayerPropertiesBase ui;
      ui.setupUi( dialog );

      dialog->setWindowTitle( tr( "Layer Properties" ) );
      ui.leName->setText( layerItem->name() );
      ui.leSource->setText( layerItem->path() );
      ui.leProvider->setText( layerItem->providerKey() );
      QString myStyle = QgsApplication::reportStyleSheet();
      ui.txtbMetadata->document()->setDefaultStyleSheet( myStyle );
      ui.txtbMetadata->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()->mapRenderer()->destinationCrs();
        if ( layerCrs == defaultCrs )
          ui.lblNotice->setText( "NOTICE: Layer srs set from project (" + defaultCrs.authid() + ")" );
      }

      dialog->show();
    }
  }
}
QgsFeatureIds QgsMapToolSelectUtils::getMatchingFeatures( QgsMapCanvas *canvas, const QgsGeometry &selectGeometry, bool doContains, bool singleSelect )
{
  QgsFeatureIds newSelectedFeatures;

  if ( selectGeometry.type() != QgsWkbTypes::PolygonGeometry )
    return newSelectedFeatures;

  QgsVectorLayer *vlayer = QgsMapToolSelectUtils::getCurrentVectorLayer( canvas );
  if ( !vlayer )
    return newSelectedFeatures;

  // toLayerCoordinates will throw an exception for any 'invalid' points in
  // the rubber band.
  // For example, if you project a world map onto a globe using EPSG 2163
  // and then click somewhere off the globe, an exception will be thrown.
  QgsGeometry selectGeomTrans = selectGeometry;

  try
  {
    QgsCoordinateTransform ct( canvas->mapSettings().destinationCrs(), vlayer->crs(), QgsProject::instance() );

    if ( !ct.isShortCircuited() && selectGeomTrans.type() == QgsWkbTypes::PolygonGeometry )
    {
      // convert add more points to the edges of the rectangle
      // improve transformation result
      QgsPolygonXY poly( selectGeomTrans.asPolygon() );
      if ( poly.size() == 1 && poly.at( 0 ).size() == 5 )
      {
        const QgsPolylineXY &ringIn = poly.at( 0 );

        QgsPolygonXY newpoly( 1 );
        newpoly[0].resize( 41 );
        QgsPolylineXY &ringOut = newpoly[0];

        ringOut[ 0 ] = ringIn.at( 0 );

        int i = 1;
        for ( int j = 1; j < 5; j++ )
        {
          QgsVector v( ( ringIn.at( j ) - ringIn.at( j - 1 ) ) / 10.0 );
          for ( int k = 0; k < 9; k++ )
          {
            ringOut[ i ] = ringOut[ i - 1 ] + v;
            i++;
          }
          ringOut[ i++ ] = ringIn.at( j );
        }
        selectGeomTrans = QgsGeometry::fromPolygonXY( newpoly );
      }
    }

    selectGeomTrans.transform( ct );
  }
  catch ( QgsCsException &cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and leave existing selection unchanged
    QgsDebugMsg( QStringLiteral( "Caught CRS exception " ) );
    QgisApp::instance()->messageBar()->pushMessage(
      QObject::tr( "CRS Exception" ),
      QObject::tr( "Selection extends beyond layer's coordinate system" ),
      Qgis::Warning,
      QgisApp::instance()->messageTimeout() );
    return newSelectedFeatures;
  }

  QgsDebugMsgLevel( "Selection layer: " + vlayer->name(), 3 );
  QgsDebugMsgLevel( "Selection polygon: " + selectGeomTrans.asWkt(), 3 );
  QgsDebugMsgLevel( "doContains: " + QString( doContains ? "T" : "F" ), 3 );

  QgsRenderContext context = QgsRenderContext::fromMapSettings( canvas->mapSettings() );
  context.expressionContext() << QgsExpressionContextUtils::layerScope( vlayer );
  std::unique_ptr< QgsFeatureRenderer > r;
  if ( vlayer->renderer() )
  {
    r.reset( vlayer->renderer()->clone() );
    r->startRender( context, vlayer->fields() );
  }

  QgsFeatureRequest request;
  request.setFilterRect( selectGeomTrans.boundingBox() );
  request.setFlags( QgsFeatureRequest::ExactIntersect );
  if ( r )
    request.setSubsetOfAttributes( r->usedAttributes( context ), vlayer->fields() );
  else
    request.setNoAttributes();

  QgsFeatureIterator fit = vlayer->getFeatures( request );

  QgsFeature f;
  QgsFeatureId closestFeatureId = 0;
  bool foundSingleFeature = false;
  double closestFeatureDist = std::numeric_limits<double>::max();
  while ( fit.nextFeature( f ) )
  {
    context.expressionContext().setFeature( f );
    // make sure to only use features that are visible
    if ( r && !r->willRenderFeature( f, context ) )
      continue;

    QgsGeometry g = f.geometry();
    if ( doContains )
    {
      if ( !selectGeomTrans.contains( g ) )
        continue;
    }
    else
    {
      if ( !selectGeomTrans.intersects( g ) )
        continue;
    }
    if ( singleSelect )
    {
      foundSingleFeature = true;
      double distance = g.distance( selectGeomTrans );
      if ( distance <= closestFeatureDist )
      {
        closestFeatureDist = distance;
        closestFeatureId = f.id();
      }
    }
    else
    {
      newSelectedFeatures.insert( f.id() );
    }
  }
  if ( singleSelect && foundSingleFeature )
  {
    newSelectedFeatures.insert( closestFeatureId );
  }

  if ( r )
    r->stopRender( context );

  QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) );

  return newSelectedFeatures;
}
bool QgsPGConnectionItem::handleDrop( const QMimeData *data, const QString &toSchema )
{
  if ( !QgsMimeDataUtils::isUriList( data ) )
    return false;

  // TODO: probably should show a GUI with settings etc
  QgsDataSourceUri uri = QgsPostgresConn::connUri( mName );

  QStringList importResults;
  bool hasError = false;

  QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
  const auto constLst = lst;
  for ( const QgsMimeDataUtils::Uri &u : constLst )
  {
    // open the source layer
    bool owner;
    QString error;
    QgsVectorLayer *srcLayer = u.vectorLayer( owner, error );
    if ( !srcLayer )
    {
      importResults.append( tr( "%1: %2" ).arg( u.name, error ) );
      hasError = true;
      continue;
    }

    if ( srcLayer->isValid() )
    {
      uri.setDataSource( QString(), u.name,  srcLayer->geometryType() != QgsWkbTypes::NullGeometry ? QStringLiteral( "geom" ) : QString() );
      QgsDebugMsg( "URI " + uri.uri( false ) );

      if ( !toSchema.isNull() )
      {
        uri.setSchema( toSchema );
      }

      QVariantMap options;
      options.insert( QStringLiteral( "forceSinglePartGeometryType" ), true );
      std::unique_ptr< QgsVectorLayerExporterTask > exportTask( new QgsVectorLayerExporterTask( srcLayer, uri.uri( false ), QStringLiteral( "postgres" ), srcLayer->crs(), options, owner ) );

      // when export is successful:
      connect( exportTask.get(), &QgsVectorLayerExporterTask::exportComplete, this, [ = ]()
      {
        // this is gross - TODO - find a way to get access to messageBar from data items
        QMessageBox::information( nullptr, tr( "Import to PostGIS database" ), tr( "Import was successful." ) );
        refreshSchema( toSchema );
      } );

      // when an error occurs:
      connect( exportTask.get(), &QgsVectorLayerExporterTask::errorOccurred, this, [ = ]( int error, const QString & errorMessage )
      {
        if ( error != QgsVectorLayerExporter::ErrUserCanceled )
        {
          QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
          output->setTitle( tr( "Import to PostGIS database" ) );
          output->setMessage( tr( "Failed to import some layers!\n\n" ) + errorMessage, QgsMessageOutput::MessageText );
          output->showMessage();
        }
        refreshSchema( toSchema );
      } );

      QgsApplication::taskManager()->addTask( exportTask.release() );
    }
    else
    {
      importResults.append( tr( "%1: Not a valid layer!" ).arg( u.name ) );
      hasError = true;
    }
  }

  if ( hasError )
  {
    QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
    output->setTitle( tr( "Import to PostGIS database" ) );
    output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( QStringLiteral( "\n" ) ), QgsMessageOutput::MessageText );
    output->showMessage();
  }

  return true;
}
Exemple #16
0
int QgsGridFileWriter::writeFile( QgsFeedback *feedback )
{
  QFile outputFile( mOutputFilePath );

  if ( !outputFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
  {
    return 1;
  }

  if ( !mInterpolator )
  {
    outputFile.remove();
    return 2;
  }

  QTextStream outStream( &outputFile );
  outStream.setRealNumberPrecision( 8 );
  writeHeader( outStream );

  double currentYValue = mInterpolationExtent.yMaximum() - mCellSizeY / 2.0; //calculate value in the center of the cell
  double currentXValue;
  double interpolatedValue;

  for ( int i = 0; i < mNumRows; ++i )
  {
    currentXValue = mInterpolationExtent.xMinimum() + mCellSizeX / 2.0; //calculate value in the center of the cell
    for ( int j = 0; j < mNumColumns; ++j )
    {
      if ( mInterpolator->interpolatePoint( currentXValue, currentYValue, interpolatedValue ) == 0 )
      {
        outStream << interpolatedValue << ' ';
      }
      else
      {
        outStream << "-9999 ";
      }
      currentXValue += mCellSizeX;
    }
    outStream << endl;
    currentYValue -= mCellSizeY;

    if ( feedback )
    {
      if ( feedback->isCanceled() )
      {
        outputFile.remove();
        return 3;
      }
      feedback->setProgress( 100.0 * i / static_cast< double >( mNumRows ) );
    }
  }

  // create prj file
  QgsInterpolator::LayerData ld;
  ld = mInterpolator->layerData().at( 0 );
  QgsVectorLayer *vl = ld.vectorLayer;
  QString crs = vl->crs().toWkt();
  QFileInfo fi( mOutputFilePath );
  QString fileName = fi.absolutePath() + '/' + fi.completeBaseName() + ".prj";
  QFile prjFile( fileName );
  if ( !prjFile.open( QFile::WriteOnly | QIODevice::Truncate ) )
  {
    return 1;
  }
  QTextStream prjStream( &prjFile );
  prjStream << crs;
  prjStream << endl;
  prjFile.close();

  return 0;
}
void RgLineVectorLayerDirector::makeGraph( RgGraphBuilder *builder, const QVector< QgsPoint >& additionalPoints,
    QVector< QgsPoint >& tiedPoint ) const
{
  QgsVectorLayer *vl = myLayer();

  if ( vl == NULL )
    return;

  int featureCount = ( int ) vl->featureCount() * 2;
  int step = 0;

  QgsCoordinateTransform ct;
  QgsDistanceArea da;
  ct.setSourceCrs( vl->crs() );

  if ( builder->coordinateTransformEnabled() )
  {
    ct.setDestCRS( builder->destinationCrs() );
    da.setProjectionsEnabled( true );
    //
    //da.setSourceCrs( builder->destinationCrs().srsid() );
    //
  }
  else
  {
    ct.setDestCRS( vl->crs() );
    da.setProjectionsEnabled( false );
  }

  tiedPoint = QVector< QgsPoint >( additionalPoints.size(), QgsPoint( 0.0, 0.0 ) );
  TiePointInfo tmpInfo;
  tmpInfo.mLength = infinity();

  QVector< TiePointInfo > pointLengthMap( additionalPoints.size(), tmpInfo );
  QVector< TiePointInfo >::iterator pointLengthIt;

  // begin: tie points to the graph
  QgsAttributeList la;
  vl->select( la );
  QgsFeature feature;
  while ( vl->nextFeature( feature ) )
  {
    QgsMultiPolyline mpl;
    if ( feature.geometry()->wkbType() == QGis::WKBLineString )
    {
      mpl.push_back( feature.geometry()->asPolyline() );
    }else if ( feature.geometry()->wkbType() == QGis::WKBMultiLineString )
    {
      mpl = feature.geometry()->asMultiPolyline();
    }

    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 = builder->addVertex( ct.transform( *pointIt ) );
        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 )
            {
              info.mTiedPoint = builder->addVertex( 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

  if ( mDirectionFieldId != -1 )
  {
    la.push_back( mDirectionFieldId );
  }
  if ( mSpeedFieldId != -1 )
  {
    la.push_back( mSpeedFieldId );
  }

  SpeedUnit su = SpeedUnit::byName( mSpeedUnitName );

  // begin graph construction
  vl->select( la );
  while ( vl->nextFeature( feature ) )
  {
    QgsAttributeMap attr = feature.attributeMap();
    int directionType = mDefaultDirection;
    QgsAttributeMap::const_iterator it;
    // What direction have feature?
    for ( it = attr.constBegin(); it != attr.constEnd(); ++it )
    {
      if ( it.key() != mDirectionFieldId )
      {
        continue;
      }
      QString str = it.value().toString();
      if ( str == mBothDirectionValue )
      {
        directionType = 3;
      }
      else if ( str == mDirectDirectionValue )
      {
        directionType = 1;
      }
      else if ( str == mReverseDirectionValue )
      {
        directionType = 2;
      }
    }
    // What speed have feature?
    double speed = 0.0;
    for ( it = attr.constBegin(); it != attr.constEnd(); ++it )
    {
      if ( it.key() != mSpeedFieldId )
      {
        continue;
      }
      speed = it.value().toDouble();
    }
    if ( speed <= 0.0 )
    {
      speed = mDefaultSpeed;
    }

    // begin features segments and add arc to the Graph;
    QgsMultiPolyline mpl;
    if ( feature.geometry()->wkbType() == QGis::WKBLineString )
    {
      mpl.push_back( feature.geometry()->asPolyline() );
    }else if ( feature.geometry()->wkbType() == QGis::WKBMultiLineString )
    {
      mpl = feature.geometry()->asMultiPolyline();
    }
    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 = builder->addVertex( ct.transform( *pointIt ) );

        std::map< double, QgsPoint > pointsOnArc;
        pointsOnArc[ 0.0 ] = pt1;
        pointsOnArc[ pt1.sqrDist( pt2 )] = pt2;

        for ( pointLengthIt = pointLengthMap.begin(); pointLengthIt != pointLengthMap.end(); ++pointLengthIt )
        {
          if ( pointLengthIt->mFirstPoint == pt1 && pointLengthIt->mLastPoint == pt2 )
          {
            QgsPoint tiedPoint = pointLengthIt->mTiedPoint;
            pointsOnArc[ pt1.sqrDist( tiedPoint )] = tiedPoint;
          }
        }

        if ( !isFirstPoint )
        {
          std::map< double, QgsPoint >::iterator pointsIt;
          QgsPoint pt1;
          QgsPoint pt2;
          bool isFirstPoint = true;
          for ( pointsIt = pointsOnArc.begin(); pointsIt != pointsOnArc.end(); ++pointsIt )
          {
            pt2 = pointsIt->second;
            if ( !isFirstPoint )
            {
              double cost = da.measureLine( pt1, pt2 );
              if ( directionType == 1 ||
                   directionType == 3 )
              {
                builder->addArc( pt1, pt2, cost, speed*su.multipler(), feature.id() );
              }
              if ( directionType == 2 ||
                   directionType == 3 )
              {
                builder->addArc( pt2, pt1, cost, speed*su.multipler(), feature.id() );
              }
            }
            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( RgGraphBuilder *builder, const QgsRectangle& rt )
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 )
Exemple #19
0
// Slot called when the menu item is triggered
// If you created more menu items / toolbar buttons in initiGui, you should
// create a separate handler for each action - this single run() method will
// not be enough
void Heatmap::run()
{
  HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings );

  //check that dialog found a suitable vector layer
  if ( !d.inputVectorLayer() )
  {
    mQGisIface->messageBar()->pushMessage( tr( "Layer not found" ), tr( "The heatmap plugin requires at least one point vector layer" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() );
    return;
  }

  if ( d.exec() != QDialog::Accepted )
  {
    return;
  }

  QgsVectorLayer* inputLayer = d.inputVectorLayer();

  // Get the required data from the dialog
  QgsRectangle myBBox = d.bbox();
  int columns = d.columns();
  int rows = d.rows();
  double cellsize = d.cellSizeX(); // or d.cellSizeY();  both have the same value
  mDecay = d.decayRatio();
  KernelShape kernelShape = d.kernelShape();
  OutputValues valueType = d.outputValues();

  //is input layer multipoint?
  bool isMultiPoint = inputLayer->wkbType() == Qgis::WKBMultiPoint || inputLayer->wkbType() == Qgis::WKBMultiPoint25D;

  // Getting the rasterdataset in place
  GDALAllRegister();

  GDALDriverH myDriver = GDALGetDriverByName( d.outputFormat().toUtf8() );
  if ( !myDriver )
  {
    mQGisIface->messageBar()->pushMessage( tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ), QgsMessageBar::WARNING, mQGisIface->messageTimeout() );
    return;
  }

  double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize };
  GDALDatasetH emptyDataset = GDALCreate( myDriver, d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, nullptr );
  GDALSetGeoTransform( emptyDataset, geoTransform );
  // Set the projection on the raster destination to match the input layer
  GDALSetProjection( emptyDataset, inputLayer->crs().toWkt().toLocal8Bit().data() );

  GDALRasterBandH poBand = GDALGetRasterBand( emptyDataset, 1 );
  GDALSetRasterNoDataValue( poBand, NO_DATA );

  float* line = ( float * ) CPLMalloc( sizeof( float ) * columns );
  for ( int i = 0; i < columns ; i++ )
  {
    line[i] = NO_DATA;
  }
  // Write the empty raster
  for ( int i = 0; i < rows ; i++ )
  {
    if ( GDALRasterIO( poBand, GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ) != CE_None )
    {
      QgsDebugMsg( "Raster IO Error" );
    }
  }

  CPLFree( line );
  //close the dataset
  GDALClose( emptyDataset );

  // open the raster in GA_Update mode
  GDALDatasetH heatmapDS = GDALOpen( TO8F( d.outputFilename() ), GA_Update );
  if ( !heatmapDS )
  {
    mQGisIface->messageBar()->pushMessage( tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ), QgsMessageBar::WARNING );
    return;
  }
  poBand = GDALGetRasterBand( heatmapDS, 1 );

  QgsAttributeList myAttrList;
  int rField = 0;
  int wField = 0;

  // Handle different radius options
  double radius;
  double radiusToMapUnits = 1;
  int myBuffer = 0;
  if ( d.variableRadius() )
  {
    rField = d.radiusField();
    myAttrList.append( rField );
    QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) );

    // If not using map units, then calculate a conversion factor to convert the radii to map units
    if ( d.radiusUnit() == HeatmapGui::LayerUnits )
    {
      radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() );
    }
  }
  else
  {
    radius = d.radius(); // radius returned by d.radius() is already in map units
    myBuffer = bufferSize( radius, cellsize );
  }

  if ( d.weighted() )
  {
    wField = d.weightField();
    myAttrList.append( wField );
  }

  // This might have attributes or mightnot have attibutes at all
  // based on the variableRadius() and weighted()
  QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) );
  int totalFeatures = inputLayer->featureCount();
  int counter = 0;

  QProgressDialog p( tr( "Rendering heatmap..." ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() );
  p.setWindowTitle( tr( "QGIS" ) );
  p.setWindowModality( Qt::ApplicationModal );
  p.show();

  QgsFeature myFeature;

  while ( fit.nextFeature( myFeature ) )
  {
    counter++;
    p.setValue( counter );
    QApplication::processEvents();
    if ( p.wasCanceled() )
    {
      mQGisIface->messageBar()->pushMessage( tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() );
      break;
    }

    const QgsGeometry* featureGeometry = myFeature.constGeometry();
    if ( !featureGeometry )
    {
      continue;
    }

    // convert the geometry to multipoint
    QgsMultiPoint multiPoints;
    if ( !isMultiPoint )
    {
      QgsPoint myPoint = featureGeometry->asPoint();
      // avoiding any empty points or out of extent points
      if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() )
          || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) )
      {
        continue;
      }
      multiPoints << myPoint;
    }
    else
    {
      multiPoints = featureGeometry->asMultiPoint();
    }

    // If radius is variable then fetch it and calculate new pixel buffer size
    if ( d.variableRadius() )
    {
      radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits;
      myBuffer = bufferSize( radius, cellsize );
    }

    int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate

    double weight = 1.0;
    if ( d.weighted() )
    {
      weight = myFeature.attribute( wField ).toDouble();
    }

    //loop through all points in multipoint
    for ( QgsMultiPoint::const_iterator pointIt = multiPoints.constBegin(); pointIt != multiPoints.constEnd(); ++pointIt )
    {
      // avoiding any empty points or out of extent points
      if ((( *pointIt ).x() < myBBox.xMinimum() ) || (( *pointIt ).y() < myBBox.yMinimum() )
          || (( *pointIt ).x() > myBBox.xMaximum() ) || (( *pointIt ).y() > myBBox.yMaximum() ) )
      {
        continue;
      }

      // calculate the pixel position
      unsigned int xPosition, yPosition;
      xPosition = ((( *pointIt ).x() - myBBox.xMinimum() ) / cellsize ) - myBuffer;
      yPosition = ((( *pointIt ).y() - myBBox.yMinimum() ) / cellsize ) - myBuffer;

      // get the data
      float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize );
      if ( GDALRasterIO( poBand, GF_Read, xPosition, yPosition, blockSize, blockSize,
                         dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None )
      {
        QgsDebugMsg( "Raster IO Error" );
      }

      for ( int xp = 0; xp <= myBuffer; xp++ )
      {
        for ( int yp = 0; yp <= myBuffer; yp++ )
        {
          double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) );

          // is pixel outside search bandwidth of feature?
          if ( distance > myBuffer )
          {
            continue;
          }

          double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape, valueType );

          // clearing anamolies along the axes
          if ( xp == 0 && yp == 0 )
          {
            pixelValue /= 4;
          }
          else if ( xp == 0 || yp == 0 )
          {
            pixelValue /= 2;
          }

          int pos[4];
          pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp );
          pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp );
          pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp );
          pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp );
          for ( int p = 0; p < 4; p++ )
          {
            if ( dataBuffer[ pos[p] ] == NO_DATA )
            {
              dataBuffer[ pos[p] ] = 0;
            }
            dataBuffer[ pos[p] ] += pixelValue;
          }
        }
      }
      if ( GDALRasterIO( poBand, GF_Write, xPosition, yPosition, blockSize, blockSize,
                         dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ) != CE_None )
      {
        QgsDebugMsg( "Raster IO Error" );
      }
      CPLFree( dataBuffer );
    }
  }

  // Finally close the dataset
  GDALClose(( GDALDatasetH ) heatmapDS );

  // Open the file in QGIS window if requested
  if ( d.addToCanvas() )
  {
    mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() );
  }

}
int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format )
{
  QgsDebugMsg( "Info format is:" + format );

  //read TYPENAME
  QMap<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" );
  if ( type_name_it != mParameterMap.end() )
  {
    mTypeName = type_name_it.value();
  }
  else
  {
    return 1;
  }

  QStringList wfsLayersId = mConfigParser->wfsLayers();
  QMap< QString, QMap< int, QString > > aliasInfo = mConfigParser->layerAliasInfo();
  QMap< QString, QSet<QString> > hiddenAttributes = mConfigParser->hiddenAttributes();

  QList<QgsMapLayer*> layerList;
  QgsMapLayer* currentLayer = 0;

  layerList = mConfigParser->mapLayerFromStyle( mTypeName, "" );
  currentLayer = layerList.at( 0 );

  QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
  if ( layer && wfsLayersId.contains( layer->id() ) )
  {
    //is there alias info for this vector layer?
    QMap< int, QString > layerAliasInfo;
    QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() );
    if ( aliasIt != aliasInfo.constEnd() )
    {
      layerAliasInfo = aliasIt.value();
    }

    //hidden attributes for this layer
    QSet<QString> layerHiddenAttributes;
    QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() );
    if ( hiddenIt != hiddenAttributes.constEnd() )
    {
      layerHiddenAttributes = hiddenIt.value();
    }

    //do a select with searchRect and go through all the features
    QgsVectorDataProvider* provider = layer->dataProvider();
    if ( !provider )
    {
      return 2;
    }

    QgsFeature feature;
    QgsAttributeMap featureAttributes;
    const QgsFieldMap& fields = provider->fields();

    //map extent
    QgsRectangle searchRect = layer->extent();

    //read FEATUREDID
    bool fidOk = false;
    QString fid;
    QMap<QString, QString>::const_iterator fidIt = mParameterMap.find( "FEATUREID" );
    if ( fidIt != mParameterMap.end() )
    {
      fidOk = true;
      fid = fidIt.value();
    }

    //read FILTER
    bool filterOk = false;
    QDomDocument filter;
    QMap<QString, QString>::const_iterator filterIt = mParameterMap.find( "FILTER" );
    if ( filterIt != mParameterMap.end() )
    {
      try
      {
        QString errorMsg;
        if ( !filter.setContent( filterIt.value(), true, &errorMsg ) )
        {
          QgsDebugMsg( "soap request parse error" );
          QgsDebugMsg( "error message: " + errorMsg );
          QgsDebugMsg( "the xml string was:" );
          QgsDebugMsg( filterIt.value() );
        }
        else
        {
          filterOk = true;
        }
      }
      catch ( QgsMapServiceException& e )
      {
        Q_UNUSED( e );
        filterOk = false;
      }
    }


    bool conversionSuccess;
    double minx, miny, maxx, maxy;
    bool bboxOk = false;
    //read BBOX
    QMap<QString, QString>::const_iterator bbIt = mParameterMap.find( "BBOX" );
    if ( bbIt == mParameterMap.end() )
    {
      minx = 0; miny = 0; maxx = 0; maxy = 0;
    }
    else
    {
      bboxOk = true;
      QString bbString = bbIt.value();
      minx = bbString.section( ",", 0, 0 ).toDouble( &conversionSuccess );
      if ( !conversionSuccess ) {bboxOk = false;}
      miny = bbString.section( ",", 1, 1 ).toDouble( &conversionSuccess );
      if ( !conversionSuccess ) {bboxOk = false;}
      maxx = bbString.section( ",", 2, 2 ).toDouble( &conversionSuccess );
      if ( !conversionSuccess ) {bboxOk = false;}
      maxy = bbString.section( ",", 3, 3 ).toDouble( &conversionSuccess );
      if ( !conversionSuccess ) {bboxOk = false;}
    }

    //read MAXFEATURES
    long maxFeat = layer->featureCount();
    long featureCounter = 0;
    QMap<QString, QString>::const_iterator mfIt = mParameterMap.find( "MAXFEATURES" );
    if ( mfIt != mParameterMap.end() )
    {
      QString mfString = mfIt.value();
      bool mfOk;
      maxFeat = mfString.toLong( &mfOk, 10 );
      if ( !mfOk ) { maxFeat = layer->featureCount(); }
    }

    //read PROPERTYNAME
    mWithGeom = true;
    QgsAttributeList attrIndexes = provider->attributeIndexes();
    QMap<QString, QString>::const_iterator pnIt = mParameterMap.find( "PROPERTYNAME" );
    if ( pnIt != mParameterMap.end() )
    {
      QStringList attrList = pnIt.value().split( "," );
      if ( attrList.size() > 0 )
      {
        mWithGeom = false;
        QStringList::const_iterator alstIt;
        QList<int> idxList;
        QMap<QString, int> fieldMap = provider->fieldNameMap();
        QMap<QString, int>::const_iterator fieldIt;
        QString fieldName;
        for ( alstIt = attrList.begin(); alstIt != attrList.end(); ++alstIt )
        {
          fieldName = *alstIt;
          fieldIt = fieldMap.find( fieldName );
          if ( fieldIt != fieldMap.end() )
          {
            idxList.append( fieldIt.value() );
          }
          else if ( fieldName == "geometry" )
          {
            mWithGeom = true;
          }
        }
        if ( idxList.size() > 0 || mWithGeom )
        {
          attrIndexes = idxList;
        }
        else
        {
          mWithGeom = true;
        }
      }
    }

    QgsCoordinateReferenceSystem layerCrs = layer->crs();

    startGetFeature( request, format );

    if ( fidOk )
    {
      provider->featureAtId( fid.toInt(), feature, mWithGeom, attrIndexes );
      sendGetFeature( request, format, &feature, 0, layerCrs, fields, layerHiddenAttributes );
    }
    else if ( filterOk )
    {
      provider->select( attrIndexes, searchRect, mWithGeom, true );
      try
      {
        QgsFilter* mFilter = QgsFilter::createFilterFromXml( filter.firstChild().toElement().firstChild().toElement(), layer );
        while ( provider->nextFeature( feature ) && featureCounter < maxFeat )
        {
          if ( mFilter )
          {
            if ( mFilter->evaluate( feature ) )
            {
              sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes );
              ++featureCounter;
            }
          }
          else
          {
            sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes );
            ++featureCounter;
          }
        }
        delete mFilter;
      }
      catch ( QgsMapServiceException& e )
      {
        Q_UNUSED( e );

        while ( provider->nextFeature( feature ) && featureCounter < maxFeat )
        {
          sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes );
          ++featureCounter;
        }
      }
    }
    else
    {
      if ( bboxOk )
        searchRect.set( minx, miny, maxx, maxy );
      provider->select( attrIndexes, searchRect, mWithGeom, true );
      while ( provider->nextFeature( feature ) && featureCounter < maxFeat )
      {
        sendGetFeature( request, format, &feature, featureCounter, layerCrs, fields, layerHiddenAttributes );
        ++featureCounter;
      }
    }

    endGetFeature( request, format );
  }
  else
  {
    return 2;
  }
  return 0;
}
void QgsGeometrySnapperDialog::run()
{
  /** Get layers **/
  QgsVectorLayer* layer = getInputLayer();
  QgsVectorLayer* referenceLayer = getReferenceLayer();
  if ( layer == 0 || referenceLayer == 0 )
  {
    return;
  }

  if ( ui.radioButtonOutputNew->isChecked() &&
       ( layer->dataProvider()->dataSourceUri().startsWith( ui.lineEditOutput->text() ) ||
         referenceLayer->dataProvider()->dataSourceUri().startsWith( ui.lineEditOutput->text() ) ) )
  {
    QMessageBox::critical( this, tr( "Invalid Output Layer" ), tr( "The chosen output layer is the same as an input layer." ) );
    return;
  }

  bool selectedOnly = ui.checkBoxInputSelectedOnly->isChecked();

  /** Duplicate if necessary **/
  if ( ui.radioButtonOutputNew->isChecked() )
  {
    QString filename = ui.lineEditOutput->text();

    // Remove existing layer with same uri
    QStringList toRemove;
    foreach ( QgsMapLayer* maplayer, QgsMapLayerRegistry::instance()->mapLayers() )
    {
      if ( dynamic_cast<QgsVectorLayer*>( maplayer ) &&
           static_cast<QgsVectorLayer*>( maplayer )->dataProvider()->dataSourceUri().startsWith( filename ) )
      {
        toRemove.append( maplayer->id() );
      }
    }
    if ( !toRemove.isEmpty() )
    {
      QgsMapLayerRegistry::instance()->removeMapLayers( toRemove );
    }

    QString errMsg;
    QgsVectorFileWriter::WriterError err =  QgsVectorFileWriter::writeAsVectorFormat( layer, filename, layer->dataProvider()->encoding(), &layer->crs(), mOutputDriverName, selectedOnly, &errMsg );
    if ( err != QgsVectorFileWriter::NoError )
    {
      QMessageBox::critical( this, tr( "Layer Creation Failed" ), tr( "Failed to create the output layer: %1" ).arg( errMsg ) );
      return;
    }
    QgsVectorLayer* newlayer = new QgsVectorLayer( filename, QFileInfo( filename ).completeBaseName(), "ogr" );

    if ( selectedOnly )
    {
      QgsFeature feature;

      // Get features to select (only selected features were written up to this point)
      QgsFeatureIds selectedFeatures = newlayer->allFeatureIds();

      // Write non-selected feature ids
      QgsFeatureList features;
      QgsFeatureIterator it = layer->getFeatures();
      while ( it.nextFeature( feature ) )
      {
        if ( !layer->selectedFeaturesIds().contains( feature.id() ) )
        {
          features.append( feature );
        }
      }
      newlayer->dataProvider()->addFeatures( features );

      // Set selected features
      newlayer->setSelectedFeatures( selectedFeatures );
    }
    layer = newlayer;
  }
Exemple #22
0
bool QgsSLConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
{
  if ( !QgsMimeDataUtils::isUriList( data ) )
    return false;

  // TODO: probably should show a GUI with settings etc

  QgsDataSourceURI destUri;
  destUri.setDatabase( mDbPath );

  qApp->setOverrideCursor( Qt::WaitCursor );

  QStringList importResults;
  bool hasError = false;
  QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
  foreach ( const QgsMimeDataUtils::Uri& u, lst )
  {
    if ( u.layerType != "vector" )
    {
      importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
      hasError = true; // only vectors can be imported
      continue;
    }

    // open the source layer
    QgsVectorLayer* srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );

    if ( srcLayer->isValid() )
    {
      destUri.setDataSource( QString(), u.name, "geom" );
      QgsDebugMsg( "URI " + destUri.uri() );
      QgsVectorLayerImport::ImportError err;
      QString importError;
      err = QgsVectorLayerImport::importLayer( srcLayer, destUri.uri(), "spatialite", &srcLayer->crs(), false, &importError );
      if ( err == QgsVectorLayerImport::NoError )
        importResults.append( tr( "%1: OK!" ).arg( u.name ) );
      else
      {
        importResults.append( QString( "%1: %2" ).arg( u.name ).arg( importError ) );
        hasError = true;
      }
    }
    else
    {
      importResults.append( tr( "%1: OK!" ).arg( u.name ) );
      hasError = true;
    }

    delete srcLayer;
  }

  qApp->restoreOverrideCursor();

  if ( hasError )
  {
    QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
    output->setTitle( tr( "Import to SpatiaLite database" ) );
    output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( "\n" ), QgsMessageOutput::MessageText );
    output->showMessage();
  }
  else
  {
    QMessageBox::information( 0, tr( "Import to SpatiaLite database" ), tr( "Import was successful." ) );
    refresh();
  }

  return true;
}
Exemple #23
0
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();
  }
}
Exemple #24
0
bool QgsSLConnectionItem::handleDrop( const QMimeData * data, Qt::DropAction )
{
  if ( !QgsMimeDataUtils::isUriList( data ) )
    return false;

  // TODO: probably should show a GUI with settings etc

  QgsDataSourceURI destUri;
  destUri.setDatabase( mDbPath );

  qApp->setOverrideCursor( Qt::WaitCursor );

  QProgressDialog *progress = new QProgressDialog( tr( "Copying features..." ), tr( "Abort" ), 0, 0, nullptr );
  progress->setWindowTitle( tr( "Import layer" ) );
  progress->setWindowModality( Qt::WindowModal );
  progress->show();

  QStringList importResults;
  bool hasError = false;
  bool cancelled = false;

  QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( data );
  Q_FOREACH ( const QgsMimeDataUtils::Uri& u, lst )
  {
    if ( u.layerType != "vector" )
    {
      importResults.append( tr( "%1: Not a vector layer!" ).arg( u.name ) );
      hasError = true; // only vectors can be imported
      continue;
    }

    // open the source layer
    QgsVectorLayer* srcLayer = new QgsVectorLayer( u.uri, u.name, u.providerKey );

    if ( srcLayer->isValid() )
    {
      destUri.setDataSource( QString(), u.name, srcLayer->geometryType() != Qgis::NoGeometry ? "geom" : QString() );
      QgsDebugMsg( "URI " + destUri.uri() );
      QgsVectorLayerImport::ImportError err;
      QString importError;
      err = QgsVectorLayerImport::importLayer( srcLayer, destUri.uri(), "spatialite", srcLayer->crs(), false, &importError, false, nullptr, progress );
      if ( err == QgsVectorLayerImport::NoError )
        importResults.append( tr( "%1: OK!" ).arg( u.name ) );
      else if ( err == QgsVectorLayerImport::ErrUserCancelled )
        cancelled = true;
      else
      {
        importResults.append( QString( "%1: %2" ).arg( u.name, importError ) );
        hasError = true;
      }
    }
    else
    {
      importResults.append( tr( "%1: OK!" ).arg( u.name ) );
      hasError = true;
    }

    delete srcLayer;
  }

  delete progress;

  qApp->restoreOverrideCursor();

  if ( cancelled )
  {
    QMessageBox::information( nullptr, tr( "Import to SpatiaLite database" ), tr( "Import cancelled." ) );
    refresh();
  }
  else if ( hasError )
  {
    QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
    output->setTitle( tr( "Import to SpatiaLite database" ) );
    output->setMessage( tr( "Failed to import some layers!\n\n" ) + importResults.join( "\n" ), QgsMessageOutput::MessageText );
    output->showMessage();
  }
  else
  {
    QMessageBox::information( nullptr, tr( "Import to SpatiaLite database" ), tr( "Import was successful." ) );
    refresh();
  }

  return true;
}
Exemple #25
0
// Slot called when the menu item is triggered
// If you created more menu items / toolbar buttons in initiGui, you should
// create a separate handler for each action - this single run() method will
// not be enough
void Heatmap::run()
{
  HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings );

  if ( d.exec() == QDialog::Accepted )
  {
    // everything runs here

    // Get the required data from the dialog
    QgsRectangle myBBox = d.bbox();
    int columns = d.columns();
    int rows = d.rows();
    double cellsize = d.cellSizeX(); // or d.cellSizeY();  both have the same value
    mDecay = d.decayRatio();
    int kernelShape = d.kernelShape();

    // Start working on the input vector
    QgsVectorLayer* inputLayer = d.inputVectorLayer();

    // Getting the rasterdataset in place
    GDALAllRegister();

    GDALDataset *emptyDataset;
    GDALDriver *myDriver;

    myDriver = GetGDALDriverManager()->GetDriverByName( d.outputFormat().toUtf8() );
    if ( myDriver == NULL )
    {
      QMessageBox::information( 0, tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ) );
      return;
    }

    double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize };
    emptyDataset = myDriver->Create( d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, NULL );
    emptyDataset->SetGeoTransform( geoTransform );
    // Set the projection on the raster destination to match the input layer
    emptyDataset->SetProjection( inputLayer->crs().toWkt().toLocal8Bit().data() );

    GDALRasterBand *poBand;
    poBand = emptyDataset->GetRasterBand( 1 );
    poBand->SetNoDataValue( NO_DATA );

    float* line = ( float * ) CPLMalloc( sizeof( float ) * columns );
    for ( int i = 0; i < columns ; i++ )
    {
      line[i] = NO_DATA;
    }
    // Write the empty raster
    for ( int i = 0; i < rows ; i++ )
    {
      poBand->RasterIO( GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 );
    }

    CPLFree( line );
    //close the dataset
    GDALClose(( GDALDatasetH ) emptyDataset );

    // open the raster in GA_Update mode
    GDALDataset *heatmapDS;
    heatmapDS = ( GDALDataset * ) GDALOpen( d.outputFilename().toUtf8(), GA_Update );
    if ( !heatmapDS )
    {
      QMessageBox::information( 0, tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ) );
      return;
    }
    poBand = heatmapDS->GetRasterBand( 1 );

    QgsAttributeList myAttrList;
    int rField = 0;
    int wField = 0;

    // Handle different radius options
    double radius;
    double radiusToMapUnits = 1;
    int myBuffer = 0;
    if ( d.variableRadius() )
    {
      rField = d.radiusField();
      myAttrList.append( rField );
      QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) );

      // If not using map units, then calculate a conversion factor to convert the radii to map units
      if ( d.radiusUnit() == HeatmapGui::Meters )
      {
        radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() );
      }
    }
    else
    {
      radius = d.radius(); // radius returned by d.radius() is already in map units
      myBuffer = bufferSize( radius, cellsize );
    }

    if ( d.weighted() )
    {
      wField = d.weightField();
      myAttrList.append( wField );
    }

    // This might have attributes or mightnot have attibutes at all
    // based on the variableRadius() and weighted()
    QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) );
    int totalFeatures = inputLayer->featureCount();
    int counter = 0;

    QProgressDialog p( tr( "Creating heatmap" ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() );
    p.setWindowModality( Qt::ApplicationModal );
    p.show();

    QgsFeature myFeature;

    while ( fit.nextFeature( myFeature ) )
    {
      counter++;
      p.setValue( counter );
      QApplication::processEvents();
      if ( p.wasCanceled() )
      {
        QMessageBox::information( 0, tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster." ) );
        break;
      }

      QgsGeometry* myPointGeometry;
      myPointGeometry = myFeature.geometry();
      // convert the geometry to point
      QgsPoint myPoint;
      myPoint = myPointGeometry->asPoint();
      // avoiding any empty points or out of extent points
      if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() )
          || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) )
      {
        continue;
      }

      // If radius is variable then fetch it and calculate new pixel buffer size
      if ( d.variableRadius() )
      {
        radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits;
        myBuffer = bufferSize( radius, cellsize );
      }

      int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate
      // calculate the pixel position
      unsigned int xPosition, yPosition;
      xPosition = (( myPoint.x() - myBBox.xMinimum() ) / cellsize ) - myBuffer;
      yPosition = (( myPoint.y() - myBBox.yMinimum() ) / cellsize ) - myBuffer;

      // get the data
      float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize );
      poBand->RasterIO( GF_Read, xPosition, yPosition, blockSize, blockSize,
                        dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 );

      double weight = 1.0;
      if ( d.weighted() )
      {
        weight = myFeature.attribute( wField ).toDouble();
      }

      for ( int xp = 0; xp <= myBuffer; xp++ )
      {
        for ( int yp = 0; yp <= myBuffer; yp++ )
        {
          double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) );

          // is pixel outside search bandwidth of feature?
          if ( distance > myBuffer )
          {
            continue;
          }

          double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape );

          // clearing anamolies along the axes
          if ( xp == 0 && yp == 0 )
          {
            pixelValue /= 4;
          }
          else if ( xp == 0 || yp == 0 )
          {
            pixelValue /= 2;
          }

          int pos[4];
          pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp );
          pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp );
          pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp );
          pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp );
          for ( int p = 0; p < 4; p++ )
          {
            if ( dataBuffer[ pos[p] ] == NO_DATA )
            {
              dataBuffer[ pos[p] ] = 0;
            }
            dataBuffer[ pos[p] ] += pixelValue;
          }
        }
      }

      poBand->RasterIO( GF_Write, xPosition, yPosition, blockSize, blockSize,
                        dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 );
      CPLFree( dataBuffer );
    }
    // Finally close the dataset
    GDALClose(( GDALDatasetH ) heatmapDS );

    // Open the file in QGIS window
    mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() );
  }
}
Exemple #26
0
int QgsGridFileWriter::writeFile( bool showProgressDialog )
{
  QFile outputFile( mOutputFilePath );

  if ( !outputFile.open( QFile::WriteOnly ) )
  {
    return 1;
  }

  if ( !mInterpolator )
  {
    outputFile.remove();
    return 2;
  }

  QTextStream outStream( &outputFile );
  outStream.setRealNumberPrecision( 8 );
  writeHeader( outStream );

  double currentYValue = mInterpolationExtent.yMaximum() - mCellSizeY / 2.0; //calculate value in the center of the cell
  double currentXValue;
  double interpolatedValue;

  QProgressDialog* progressDialog = 0;
  if ( showProgressDialog )
  {
    progressDialog = new QProgressDialog( QObject::tr( "Interpolating..." ), QObject::tr( "Abort" ), 0, mNumRows, 0 );
    progressDialog->setWindowModality( Qt::WindowModal );
  }

  for ( int i = 0; i < mNumRows; ++i )
  {
    currentXValue = mInterpolationExtent.xMinimum() + mCellSizeX / 2.0; //calculate value in the center of the cell
    for ( int j = 0; j < mNumColumns; ++j )
    {
      if ( mInterpolator->interpolatePoint( currentXValue, currentYValue, interpolatedValue ) == 0 )
      {
        outStream << interpolatedValue << ' ';
      }
      else
      {
        outStream << "-9999 ";
      }
      currentXValue += mCellSizeX;
    }
    outStream << endl;
    currentYValue -= mCellSizeY;

    if ( showProgressDialog )
    {
      if ( progressDialog->wasCanceled() )
      {
        outputFile.remove();
        return 3;
      }
      progressDialog->setValue( i );
    }
  }

  // create prj file
  QgsInterpolator::LayerData ld;
  ld = mInterpolator->layerData().first();
  QgsVectorLayer* vl = ld.vectorLayer;
  QString crs = vl->crs().toWkt();
  QFileInfo fi( mOutputFilePath );
  QString fileName = fi.absolutePath() + '/' + fi.completeBaseName() + ".prj";
  QFile prjFile( fileName );
  if ( !prjFile.open( QFile::WriteOnly ) )
  {
    return 1;
  }
  QTextStream prjStream( &prjFile );
  prjStream << crs;
  prjStream << endl;
  prjFile.close();

  delete progressDialog;
  return 0;
}
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;
}
void QgsGeometryCheckerSetupTab::runChecks()
{
  // Get selected layer
  QList<QgsVectorLayer *> layers = getSelectedLayers();
  if ( layers.isEmpty() )
    return;

  if ( ui.radioButtonOutputNew->isChecked() )
  {
    for ( QgsVectorLayer *layer : layers )
    {
      if ( layer->dataProvider()->dataSourceUri().startsWith( ui.lineEditOutputDirectory->text() ) )
      {
        QMessageBox::critical( this, tr( "Invalid Output Directory" ), tr( "The chosen output directory contains one or more input layers." ) );
        return;
      }
    }
  }
  QgsVectorLayer *lineLayerCheckLayer = ui.comboLineLayerIntersection->isEnabled() ? dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboLineLayerIntersection->currentData().toString() ) ) : nullptr;
  QgsVectorLayer *followBoundaryCheckLayer = ui.comboBoxFollowBoundaries->isEnabled() ? dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboBoxFollowBoundaries->currentData().toString() ) ) : nullptr;
  if ( layers.contains( lineLayerCheckLayer ) || layers.contains( followBoundaryCheckLayer ) )
  {
    QMessageBox::critical( this, tr( "Error" ), tr( "The test layer set contains a layer selected for a topology check." ) );
    return;
  }

  for ( QgsVectorLayer *layer : layers )
  {
    if ( layer->isEditable() )
    {
      QMessageBox::critical( this, tr( "Editable Input Layer" ), tr( "Input layer are not allowed to be in editing mode." ) );
      return;
    }
  }
  bool selectedOnly = ui.checkBoxInputSelectedOnly->isChecked();

  // Set window busy
  setCursor( Qt::WaitCursor );
  mRunButton->setEnabled( false );
  ui.labelStatus->setText( tr( "<b>Preparing output...</b>" ) );
  ui.labelStatus->show();
  QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );

  QList<QgsVectorLayer *> processLayers;
  if ( ui.radioButtonOutputNew->isChecked() )
  {
    // Get output directory and file extension
    QDir outputDir = QDir( ui.lineEditOutputDirectory->text() );
    QString outputDriverName = ui.comboBoxOutputFormat->currentText();
    QgsVectorFileWriter::MetaData metadata;
    if ( !QgsVectorFileWriter::driverMetadata( outputDriverName, metadata ) )
    {
      QMessageBox::critical( this, tr( "Unknown Output Format" ), tr( "The specified output format cannot be recognized." ) );
      mRunButton->setEnabled( true );
      ui.labelStatus->hide();
      unsetCursor();
      return;
    }
    QString outputExtension = metadata.ext;

    // List over input layers, check which existing project layers need to be removed and create output layers
    QString filenamePrefix = ui.lineEditFilenamePrefix->text();
    QSettings().setValue( "/geometry_checker/previous_values/filename_prefix", filenamePrefix );
    QStringList toRemove;
    QStringList createErrors;
    for ( QgsVectorLayer *layer : layers )
    {
      QString outputPath = outputDir.absoluteFilePath( filenamePrefix + layer->name() + "." + outputExtension );

      // Remove existing layer with same uri from project
      for ( QgsVectorLayer *projectLayer : QgsProject::instance()->layers<QgsVectorLayer *>() )
      {
        if ( projectLayer->dataProvider()->dataSourceUri().startsWith( outputPath ) )
        {
          toRemove.append( projectLayer->id() );
        }
      }

      // Create output layer
      QString errMsg;
      QgsVectorFileWriter::WriterError err =  QgsVectorFileWriter::writeAsVectorFormat( layer, outputPath, layer->dataProvider()->encoding(), layer->crs(), outputDriverName, selectedOnly, &errMsg );
      if ( err != QgsVectorFileWriter::NoError )
      {
        createErrors.append( errMsg );
        continue;
      }

      QgsVectorLayer *newlayer = new QgsVectorLayer( outputPath, QFileInfo( outputPath ).completeBaseName(), QStringLiteral( "ogr" ) );
      if ( selectedOnly )
      {
        QgsFeature feature;

        // Get features to select (only selected features were written up to this point)
        QgsFeatureIds selectedFeatures = newlayer->allFeatureIds();

        // Write non-selected feature ids
        QgsFeatureList features;
        QgsFeatureIterator it = layer->getFeatures();
        while ( it.nextFeature( feature ) )
        {
          if ( !layer->selectedFeatureIds().contains( feature.id() ) )
          {
            features.append( feature );
          }
        }
        newlayer->dataProvider()->addFeatures( features );

        // Set selected features
        newlayer->selectByIds( selectedFeatures );
      }
      processLayers.append( newlayer );
    }

    //  Remove layers from project
    if ( !toRemove.isEmpty() )
    {
      QgsProject::instance()->removeMapLayers( toRemove );
    }

    // Error if an output layer could not be created
    if ( !createErrors.isEmpty() )
    {
      QMessageBox::critical( this, tr( "Layer Creation Failed" ), tr( "Failed to create one or moure output layers:\n%1" ).arg( createErrors.join( "\n" ) ) );
      mRunButton->setEnabled( true );
      ui.labelStatus->hide();
      unsetCursor();
      return;
    }
  }
  else
  {
    processLayers = layers;
  }

  // Check if output layers are editable
  QList<QgsVectorLayer *> nonEditableLayers;
  for ( QgsVectorLayer *layer : processLayers )
  {
    if ( ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeGeometries ) == 0 )
    {
      nonEditableLayers.append( layer );
    }
  }
  if ( !nonEditableLayers.isEmpty() )
  {
    QStringList nonEditableLayerNames;
    for ( QgsVectorLayer *layer : nonEditableLayers )
    {
      nonEditableLayerNames.append( layer->name() );
    }
    if ( QMessageBox::Yes != QMessageBox::question( this, tr( "Non-editable Output Layers" ), tr( "The following output layers are ina format that does not support editing features:\n%1\n\nThe geometry check can be performed, but it will not be possible to fix any errors. Do you want to continue?" ).arg( nonEditableLayerNames.join( "\n" ) ), QMessageBox::Yes, QMessageBox::No ) )
    {
      if ( ui.radioButtonOutputNew->isChecked() )
      {
        for ( QgsVectorLayer *layer : processLayers )
        {
          QString layerPath = layer->dataProvider()->dataSourceUri();
          delete layer;
          if ( ui.comboBoxOutputFormat->currentText() == QLatin1String( "ESRI Shapefile" ) )
          {
            QgsVectorFileWriter::deleteShapeFile( layerPath );
          }
          else
          {
            QFile( layerPath ).remove();
          }
        }
        mRunButton->setEnabled( true );
        ui.labelStatus->hide();
        unsetCursor();
      }
      return;
    }
  }

  // Setup checker
  ui.labelStatus->setText( tr( "<b>Building spatial index...</b>" ) );
  QApplication::processEvents( QEventLoop::ExcludeUserInputEvents );
  QMap<QString, QgsFeaturePool *> featurePools;
  for ( QgsVectorLayer *layer : processLayers )
  {
    double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer );
    QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() );
    featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) );
  }
  // LineLayerIntersection check is enabled, make sure there is also a feature pool for that layer
  if ( ui.checkLineLayerIntersection->isChecked() && !featurePools.keys().contains( ui.comboLineLayerIntersection->currentData().toString() ) )
  {
    QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboLineLayerIntersection->currentData().toString() ) );
    Q_ASSERT( layer );
    double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer );
    QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() );
    featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) );
  }

  QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), mIface->mapCanvas()->mapSettings().destinationCrs().authid(), featurePools );

  QList<QgsGeometryCheck *> checks;
  for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() )
  {
    QgsGeometryCheck *check = factory->createInstance( context, ui );
    if ( check )
    {
      checks.append( check );
    }
  }
  QgsGeometryChecker *checker = new QgsGeometryChecker( checks, context );

  emit checkerStarted( checker );

  if ( ui.radioButtonOutputNew->isChecked() )
  {
    QList<QgsMapLayer *> addLayers;
    for ( QgsVectorLayer *layer : processLayers )
    {
      addLayers.append( layer );
    }
    QgsProject::instance()->addMapLayers( addLayers );
  }

  // Run
  ui.buttonBox->addButton( mAbortButton, QDialogButtonBox::ActionRole );
  mRunButton->hide();
  ui.progressBar->setRange( 0, 0 );
  ui.labelStatus->hide();
  ui.progressBar->show();
  ui.widgetInputs->setEnabled( false );
  QEventLoop evLoop;
  QFutureWatcher<void> futureWatcher;
  connect( checker, &QgsGeometryChecker::progressValue, ui.progressBar, &QProgressBar::setValue );
  connect( &futureWatcher, &QFutureWatcherBase::finished, &evLoop, &QEventLoop::quit );
  connect( mAbortButton, &QAbstractButton::clicked, &futureWatcher, &QFutureWatcherBase::cancel );
  connect( mAbortButton, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::showCancelFeedback );

  int maxSteps = 0;
  futureWatcher.setFuture( checker->execute( &maxSteps ) );
  ui.progressBar->setRange( 0, maxSteps );
  evLoop.exec();

  // Restore window
  unsetCursor();
  mAbortButton->setEnabled( true );
  ui.buttonBox->removeButton( mAbortButton );
  mRunButton->setEnabled( true );
  mRunButton->show();
  ui.progressBar->hide();
  ui.labelStatus->hide();
  ui.widgetInputs->setEnabled( true );

  // Show result
  emit checkerFinished( !futureWatcher.isCanceled() );
}