Exemplo n.º 1
0
void QgsRelationReferenceWidget::highlightActionTriggered( QAction *action )
{
  if ( action == mHighlightFeatureAction )
  {
    highlightFeature();
  }
  else if ( action == mScaleHighlightFeatureAction )
  {
    highlightFeature( QgsFeature(), Scale );
  }
  else if ( action == mPanHighlightFeatureAction )
  {
    highlightFeature( QgsFeature(), Pan );
  }
}
Exemplo n.º 2
0
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context )
{
  mEditorContext = context;

  connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) );

  initLayerCache( layer, !request.filterRect().isNull() );
  initModels( mapCanvas, request );

  mConditionalFormatWidget->setLayer( layer );

  mTableView->setModel( mFilterModel );
  mFeatureList->setModel( mFeatureListModel );
  mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext );
  if ( !mAttributeEditorScrollArea->layout() )
    mAttributeEditorScrollArea->setLayout( new QGridLayout() );
  mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm );
  mAttributeEditorScrollArea->setWidget( mAttributeForm );

  mAttributeForm->hideButtonBox();

  connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) );
  connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) );

  if ( mFeatureListPreviewButton->defaultAction() )
    mFeatureList->setDisplayExpression( mDisplayExpression );
  else
    columnBoxInit();

  // This slows down load of the attribute table heaps and uses loads of memory.
  //mTableView->resizeColumnsToContents();

  mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) );
}
void QgsRelationReferenceWidget::deleteForeignKey()
{
  QVariant nullValue = QSettings().value( "qgis/nullValue", "NULL" );
  if ( mReadOnlySelector )
  {
    QString nullText = "";
    if ( mAllowNull )
    {
      nullText = tr( "%1 (no selection)" ).arg( nullValue.toString() );
    }
    mLineEdit->setText( nullText );
    mForeignKey = QVariant();
    mFeature.setValid( false );
  }
  else
  {
    if ( mAllowNull )
    {
      mComboBox->setCurrentIndex( 0 );
    }
    else
    {
      mComboBox->setCurrentIndex( -1 );
    }
  }
  mRemoveFKButton->setEnabled( false );
  updateAttributeEditorFrame( QgsFeature() );
  emit foreignKeyChanged( QVariant( QVariant::Int ) );
}
Exemplo n.º 4
0
bool QgsCachedFeatureIterator::fetchFeature( QgsFeature &f )
{
  f.setValid( false );

  if ( mClosed )
    return false;

  while ( mFeatureIdIterator != mFeatureIds.constEnd() )
  {
    if ( !mVectorLayerCache->mCache.contains( *mFeatureIdIterator ) )
    {
      ++mFeatureIdIterator;
      continue;
    }

    f = QgsFeature( *mVectorLayerCache->mCache[*mFeatureIdIterator]->feature() );
    ++mFeatureIdIterator;
    if ( mRequest.acceptFeature( f ) )
    {
      f.setValid( true );
      geometryToDestinationCrs( f, mTransform );
      return true;
    }
  }
  close();
  return false;
}
Exemplo n.º 5
0
void QgsRelationReferenceWidget::deleteForeignKey()
{
  // deactivate filter comboboxes
  if ( mChainFilters && !mFilterComboBoxes.isEmpty() )
  {
    QComboBox *cb = mFilterComboBoxes.first();
    cb->setCurrentIndex( 0 );
    disableChainedComboBoxes( cb );
  }

  if ( mReadOnlySelector )
  {
    const QString nullValue = QgsApplication::nullRepresentation();

    QString nullText;
    if ( mAllowNull )
    {
      nullText = tr( "%1 (no selection)" ).arg( nullValue );
    }
    mLineEdit->setText( nullText );
    mForeignKey = QVariant( QVariant::Int );
    mFeature.setValid( false );
  }
  else
  {
    mComboBox->setIdentifierValue( QVariant( QVariant::Int ) );
  }
  mRemoveFKButton->setEnabled( false );
  updateAttributeEditorFrame( QgsFeature() );
  emitForeignKeyChanged( QVariant( QVariant::Int ) );
}
Exemplo n.º 6
0
QgsSelectByFormDialog::QgsSelectByFormDialog( QgsVectorLayer *layer, const QgsAttributeEditorContext &context, QWidget *parent, Qt::WindowFlags fl )
  : QDialog( parent, fl )
  , mLayer( layer )
  , mMessageBar( nullptr )
{
  QgsAttributeEditorContext dlgContext = context;
  dlgContext.setFormMode( QgsAttributeEditorContext::StandaloneDialog );
  dlgContext.setAllowCustomUi( false );

  mForm = new QgsAttributeForm( layer, QgsFeature(), dlgContext, this );
  mForm->setMode( QgsAttributeForm::SearchMode );

  QVBoxLayout *vLayout = new QVBoxLayout();
  vLayout->setMargin( 0 );
  vLayout->setContentsMargins( 0, 0, 0, 0 );
  setLayout( vLayout );

  vLayout->addWidget( mForm );

  connect( mForm, &QgsAttributeForm::closed, this, &QWidget::close );

  QgsSettings settings;
  restoreGeometry( settings.value( QStringLiteral( "Windows/SelectByForm/geometry" ) ).toByteArray() );

  setWindowTitle( tr( "Select features by value" ) );
}
Exemplo n.º 7
0
QgsFeatureList QgsClipboard::copyOf( const QgsFields &fields )
{
    QgsDebugMsg( "returning clipboard." );
    if ( !mUseSystemClipboard )
        return mFeatureClipboard;

    QClipboard *cb = QApplication::clipboard();

#ifndef Q_OS_WIN
    QString text = cb->text( QClipboard::Selection );
#else
    QString text = cb->text( QClipboard::Clipboard );
#endif

    QStringList values = text.split( "\n" );
    if ( values.isEmpty() || text.isEmpty() )
        return mFeatureClipboard;

    QgsFeatureList features;
    foreach ( QString row, values )
    {
        // Assume that it's just WKT for now.
        QgsGeometry* geometry = QgsGeometry::fromWkt( row );
        if ( !geometry )
            continue;

        QgsFeature* feature = new QgsFeature();
        if ( !fields.isEmpty() )
            feature->setFields( &fields, true );

        feature->setGeometry( geometry );
        features.append( QgsFeature( *feature ) );
    }
Exemplo n.º 8
0
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition )
    : mComposition( composition )
    , mEnabled( false )
    , mHideCoverage( false )
    , mFilenamePattern( "'output_'||$feature" )
    , mCoverageLayer( 0 )
    , mSingleFile( false )
    , mSortFeatures( false )
    , mSortAscending( true )
    , mCurrentFeatureNo( 0 )
    , mFilterFeatures( false )
{

  // declare special columns with a default value
  QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( QgsFeature() ) );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );

  //listen out for layer removal
  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
}
Exemplo n.º 9
0
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, QgsAttributeEditorContext context )
{
  mEditorContext = context;

  connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) );

  initLayerCache( layer );
  initModels( mapCanvas, request );

  mTableView->setModel( mFilterModel );
  mFeatureList->setModel( mFeatureListModel );
  mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext );
  mAttributeEditorScrollArea->setLayout( new QGridLayout() );
  mAttributeEditorScrollArea->layout()->addWidget( mAttributeForm );
  mAttributeEditorScrollArea->setWidget( mAttributeForm );

  mAttributeForm->hideButtonBox();

  connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) );

  if ( mFeatureListPreviewButton->defaultAction() )
    mFeatureList->setDisplayExpression( mDisplayExpression );
  else
    columnBoxInit();

  mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) );
}
void QgsRelationReferenceWidget::setRelation( const QgsRelation& relation, bool allowNullValue )
{
  mAllowNull = allowNullValue;
  mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector );

  if ( relation.isValid() )
  {
    mInvalidLabel->hide();

    mRelation = relation;
    mReferencingLayer = relation.referencingLayer();
    mRelationName = relation.name();
    mReferencedLayer = relation.referencedLayer();
    mFkeyFieldIdx = mReferencedLayer->fieldNameIndex( relation.fieldPairs().first().second );

    QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed );

    if ( mEmbedForm )
    {
      mAttributeEditorFrame->setTitle( mReferencedLayer->name() );
      mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this );
      mReferencedAttributeForm->hideButtonBox();
      mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
    }
  }
  else
  {
    mInvalidLabel->show();
  }

  if ( mShown && isVisible() )
  {
    init();
  }
}
Exemplo n.º 11
0
bool QgsPostgresFeatureIterator::fetchFeature( QgsFeature& feature )
{
  feature.setValid( false );

  if ( mClosed )
    return false;

  if ( mFeatureQueue.empty() )
  {
    QString fetch = QString( "FETCH FORWARD %1 FROM %2" ).arg( mFeatureQueueSize ).arg( mCursorName );
    QgsDebugMsgLevel( QString( "fetching %1 features." ).arg( mFeatureQueueSize ), 4 );
    if ( mConn->PQsendQuery( fetch ) == 0 ) // fetch features asynchronously
    {
      QgsMessageLog::logMessage( QObject::tr( "Fetching from cursor %1 failed\nDatabase error: %2" ).arg( mCursorName, mConn->PQerrorMessage() ), QObject::tr( "PostGIS" ) );
    }

    QgsPostgresResult queryResult;
    for ( ;; )
    {
      queryResult = mConn->PQgetResult();
      if ( !queryResult.result() )
        break;

      if ( queryResult.PQresultStatus() != PGRES_TUPLES_OK )
      {
        QgsMessageLog::logMessage( QObject::tr( "Fetching from cursor %1 failed\nDatabase error: %2" ).arg( mCursorName, mConn->PQerrorMessage() ), QObject::tr( "PostGIS" ) );
        break;
      }

      int rows = queryResult.PQntuples();
      if ( rows == 0 )
        continue;

      for ( int row = 0; row < rows; row++ )
      {
        mFeatureQueue.enqueue( QgsFeature() );
        getFeature( queryResult, row, mFeatureQueue.back() );
      } // for each row in queue
    }
  }

  if ( mFeatureQueue.empty() )
  {
    QgsDebugMsg( QString( "Finished after %1 features" ).arg( mFetched ) );
    close();

    mSource->mShared->ensureFeaturesCountedAtLeast( mFetched );

    return false;
  }

  feature = mFeatureQueue.dequeue();
  mFetched++;

  feature.setValid( true );
  feature.setFields( mSource->mFields ); // allow name-based attribute lookups

  return true;
}
Exemplo n.º 12
0
void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context, bool loadFeatures )
{
  if ( !layer )
    return;

  mLayer = layer;

  mEditorContext = context;

  connect( mTableView, &QgsAttributeTableView::willShowContextMenu, this, &QgsDualView::viewWillShowContextMenu );
  mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
  connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &QgsDualView::showViewHeaderMenu );
  connect( mTableView, &QgsAttributeTableView::columnResized, this, &QgsDualView::tableColumnResized );
  connect( mFeatureList, &QgsFeatureListView::willShowContextMenu, this, &QgsDualView::widgetWillShowContextMenu );

  initLayerCache( !( request.flags() & QgsFeatureRequest::NoGeometry ) || !request.filterRect().isNull() );
  initModels( mapCanvas, request, loadFeatures );

  mConditionalFormatWidget->setLayer( mLayer );

  mTableView->setModel( mFilterModel );
  mFeatureList->setModel( mFeatureListModel );
  delete mAttributeForm;
  mAttributeForm = new QgsAttributeForm( mLayer, mTempAttributeFormFeature, mEditorContext );
  mTempAttributeFormFeature = QgsFeature();
  if ( !context.parentContext() )
  {
    mAttributeEditorScrollArea = new QgsScrollArea();
    mAttributeEditorScrollArea->setWidgetResizable( true );
    mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
    mAttributeEditorScrollArea->setWidget( mAttributeForm );
  }
  else
  {
    mAttributeEditor->layout()->addWidget( mAttributeForm );
  }

  connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged );
  connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged );
  connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature );
  connect( mAttributeForm, &QgsAttributeForm::filterExpressionSet, this, &QgsDualView::filterExpressionSet );
  connect( mFilterModel, &QgsAttributeTableFilterModel::sortColumnChanged, this, &QgsDualView::onSortColumnChanged );

  if ( mFeatureListPreviewButton->defaultAction() )
    mFeatureList->setDisplayExpression( mDisplayExpression );
  else
    columnBoxInit();

  // This slows down load of the attribute table heaps and uses loads of memory.
  //mTableView->resizeColumnsToContents();

  mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) );
}
Exemplo n.º 13
0
bool QgsCachedFeatureIterator::fetchFeature( QgsFeature& f )
{
  mFeatureIdIterator++;

  while ( mFeatureIdIterator != mFeatureIds.end() )
  {
    f = QgsFeature( *mVectorLayerCache->mCache[*mFeatureIdIterator]->feature() );
    if ( mRequest.acceptFeature( f ) )
      return true;
  }
  return false;
}
Exemplo n.º 14
0
QStringList QgsDataDefined::referencedColumns( QgsVectorLayer* layer )
{
  if ( layer )
  {
    return referencedColumns( QgsExpressionContextUtils::createFeatureBasedContext( QgsFeature(), layer->fields() ) );
  }
  else
  {
    QgsExpressionContext empty;
    return referencedColumns( empty );
  }
}
Exemplo n.º 15
0
void QgsRelationReferenceWidget::showIndeterminateState()
{
  if ( mReadOnlySelector )
  {
    whileBlocking( mLineEdit )->setText( QString() );
  }
  else
  {
    whileBlocking( mComboBox )->setCurrentIndex( -1 );
  }
  mRemoveFKButton->setEnabled( false );
  updateAttributeEditorFrame( QgsFeature() );
}
Exemplo n.º 16
0
bool QgsDataDefined::prepareExpression( QgsVectorLayer* layer )
{
  if ( layer )
  {
    return prepareExpression( QgsExpressionContextUtils::createFeatureBasedContext( QgsFeature(), layer->fields() ) );
  }
  else
  {
    //preparing expression without a layer set, so pass empty context
    QgsExpressionContext empty;
    return prepareExpression( empty );
  }
}
Exemplo n.º 17
0
bool QgsCachedFeatureIterator::fetchFeature( QgsFeature& f )
{
  mFeatureIdIterator++;

  if ( mFeatureIdIterator == mFeatureIds.end() )
  {
    return false;
  }
  else
  {
    f = QgsFeature( *mVectorLayerCache->mCache[*mFeatureIdIterator]->feature() );
    return true;
  }
}
Exemplo n.º 18
0
void QgsDualView::init( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, const QgsFeatureRequest &request, const QgsAttributeEditorContext &context )
{
  if ( !layer )
    return;

  mEditorContext = context;

  connect( mTableView, SIGNAL( willShowContextMenu( QMenu*, QModelIndex ) ), this, SLOT( viewWillShowContextMenu( QMenu*, QModelIndex ) ) );
  mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
  connect( mTableView->horizontalHeader(), SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( showViewHeaderMenu( QPoint ) ) );
  connect( mTableView, SIGNAL( columnResized( int, int ) ), this, SLOT( tableColumnResized( int, int ) ) );

  initLayerCache( layer, !request.filterRect().isNull() );
  initModels( mapCanvas, request );

  mConditionalFormatWidget->setLayer( layer );

  mTableView->setModel( mFilterModel );
  mFeatureList->setModel( mFeatureListModel );
  delete mAttributeForm;
  mAttributeForm = new QgsAttributeForm( layer, QgsFeature(), mEditorContext );
  if ( !context.parentContext() )
  {
    mAttributeEditorScrollArea = new QScrollArea();
    mAttributeEditorScrollArea->setWidgetResizable( true );
    mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
    mAttributeEditorScrollArea->setWidget( mAttributeForm );
  }
  else
  {
    mAttributeEditor->layout()->addWidget( mAttributeForm );
  }

  connect( mAttributeForm, SIGNAL( attributeChanged( QString, QVariant ) ), this, SLOT( featureFormAttributeChanged() ) );
  connect( mAttributeForm, SIGNAL( modeChanged( QgsAttributeForm::Mode ) ), this, SIGNAL( formModeChanged( QgsAttributeForm::Mode ) ) );
  connect( mMasterModel, SIGNAL( modelChanged() ), mAttributeForm, SLOT( refreshFeature() ) );
  connect( mAttributeForm, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ), this, SIGNAL( filterExpressionSet( QString, QgsAttributeForm::FilterType ) ) );
  connect( mFilterModel, SIGNAL( sortColumnChanged( int, Qt::SortOrder ) ), this, SLOT( onSortColumnChanged() ) );
  if ( mFeatureListPreviewButton->defaultAction() )
    mFeatureList->setDisplayExpression( mDisplayExpression );
  else
    columnBoxInit();

  // This slows down load of the attribute table heaps and uses loads of memory.
  //mTableView->resizeColumnsToContents();

  mFeatureList->setEditSelection( QgsFeatureIds() << mFeatureListModel->idxToFid( mFeatureListModel->index( 0, 0 ) ) );
}
Exemplo n.º 19
0
void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool allowNullValue )
{
  mAllowNull = allowNullValue;
  mRemoveFKButton->setVisible( allowNullValue && mReadOnlySelector );

  if ( relation.isValid() )
  {
    mInvalidLabel->hide();

    mRelation = relation;
    mReferencingLayer = relation.referencingLayer();
    mRelationName = relation.name();
    mReferencedLayer = relation.referencedLayer();
    mReferencedField = relation.fieldPairs().at( 0 ).second;
    if ( mComboBox )
      mComboBox->setIdentifierField( mReferencedField );

    mReferencedFieldIdx = mReferencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second );
    mReferencingFieldIdx = mReferencingLayer->fields().lookupField( relation.fieldPairs().at( 0 ).first );
    mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() );


    if ( mEmbedForm )
    {
      QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed );
      mAttributeEditorFrame->setTitle( mReferencedLayer->name() );
      mReferencedAttributeForm = new QgsAttributeForm( relation.referencedLayer(), QgsFeature(), context, this );
      mAttributeEditorLayout->addWidget( mReferencedAttributeForm );
    }

    connect( mReferencedLayer, &QgsVectorLayer::editingStarted, this, &QgsRelationReferenceWidget::updateAddEntryButton );
    connect( mReferencedLayer, &QgsVectorLayer::editingStopped, this, &QgsRelationReferenceWidget::updateAddEntryButton );
    updateAddEntryButton();
  }
  else
  {
    mInvalidLabel->show();
  }

  if ( mShown && isVisible() )
  {
    init();
  }
}
Exemplo n.º 20
0
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition ) :
    mComposition( composition ),
    mEnabled( false ),
    mHideCoverage( false ), mFilenamePattern( "'output_'||$feature" ),
    mCoverageLayer( 0 ), mSingleFile( false ),
    mSortFeatures( false ), mSortAscending( true ), mCurrentFeatureNo( 0 ),
    mFilterFeatures( false ), mFeatureFilter( "" ),
    mFilenameParserError( QString() ),
    mFilterParserError( QString() )
{

  // declare special columns with a default value
  QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( QgsFeature() ) );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );
}
Exemplo n.º 21
0
bool QgsFeaturePool::get( QgsFeatureId id, QgsFeature &feature )
{
  QMutexLocker lock( &mLayerMutex );
  QgsFeature *pfeature = mFeatureCache.object( id );
  if ( pfeature )
  {
    //feature was cached
    feature = *pfeature;
  }

  // Feature not in cache, retrieve from layer
  pfeature = new QgsFeature();
  // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
  if ( !mLayer->getFeatures( QgsFeatureRequest( id ) ).nextFeature( *pfeature ) )
  {
    delete pfeature;
    return false;
  }
  //make a copy of pfeature into feature parameter
  feature = QgsFeature( *pfeature );
  //ownership of pfeature is transferred to cache
  mFeatureCache.insert( id, pfeature );
  return true;
}
bool QgsPostgresFeatureIterator::nextFeature( QgsFeature& feature )
{
  feature.setValid( false );

  if ( mClosed )
    return false;

#if 0
  // featureAtId used to have some special checks - necessary?
  if ( !mUseQueue )
  {
    QgsPostgresResult queryResult = P->mConnectionRO->PQexec( QString( "FETCH FORWARD 1 FROM %1" ).arg( mCursorName ) );

    int rows = queryResult.PQntuples();
    if ( rows == 0 )
    {
      QgsMessageLog::logMessage( tr( "feature %1 not found" ).arg( featureId ), tr( "PostGIS" ) );
      P->mConnectionRO->closeCursor( cursorName );
      return false;
    }
    else if ( rows != 1 )
    {
      QgsMessageLog::logMessage( tr( "found %1 features instead of just one." ).arg( rows ), tr( "PostGIS" ) );
    }

    bool gotit = getFeature( queryResult, 0, feature );

    feature.setValid( gotit );
    feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups
    return gotit;
  }
#endif

  if ( mFeatureQueue.empty() )
  {
    QString fetch = QString( "FETCH FORWARD %1 FROM %2" ).arg( mFeatureQueueSize ).arg( mCursorName );
    QgsDebugMsgLevel( QString( "fetching %1 features." ).arg( mFeatureQueueSize ), 4 );
    if ( P->mConnectionRO->PQsendQuery( fetch ) == 0 ) // fetch features asynchronously
    {
      QgsMessageLog::logMessage( QObject::tr( "Fetching from cursor %1 failed\nDatabase error: %2" ).arg( mCursorName ).arg( P->mConnectionRO->PQerrorMessage() ), QObject::tr( "PostGIS" ) );
    }

    QgsPostgresResult queryResult;
    for ( ;; )
    {
      queryResult = P->mConnectionRO->PQgetResult();
      if ( !queryResult.result() )
        break;

      if ( queryResult.PQresultStatus() != PGRES_TUPLES_OK )
      {
        QgsMessageLog::logMessage( QObject::tr( "Fetching from cursor %1 failed\nDatabase error: %2" ).arg( mCursorName ).arg( P->mConnectionRO->PQerrorMessage() ), QObject::tr( "PostGIS" ) );
        break;
      }

      int rows = queryResult.PQntuples();
      if ( rows == 0 )
        continue;

      for ( int row = 0; row < rows; row++ )
      {
        mFeatureQueue.enqueue( QgsFeature() );
        getFeature( queryResult, row, mFeatureQueue.back() );
      } // for each row in queue
    }
  }

  if ( mFeatureQueue.empty() )
  {
    QgsDebugMsg( QString( "Finished after %1 features" ).arg( mFetched ) );
    close();

    if ( P->mFeaturesCounted < mFetched )
    {
      QgsDebugMsg( QString( "feature count adjusted from %1 to %2" ).arg( P->mFeaturesCounted ).arg( mFetched ) );
      P->mFeaturesCounted = mFetched;
    }
    return false;
  }

  // Now return the next feature from the queue
  if ( mRequest.flags() & QgsFeatureRequest::NoGeometry )
  {
    feature.setGeometryAndOwnership( 0, 0 );
  }
  else
  {
    QgsGeometry* featureGeom = mFeatureQueue.front().geometryAndOwnership();
    feature.setGeometry( featureGeom );
  }
  feature.setFeatureId( mFeatureQueue.front().id() );
  feature.setAttributes( mFeatureQueue.front().attributes() );

  mFeatureQueue.dequeue();
  mFetched++;

  feature.setValid( true );
  feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups
  return true;
}
Exemplo n.º 23
0
  QDomDocument createTransactionDocument( QgsServerInterface* serverIface, const QString& version,
                                          const QgsServerRequest& request )
  {
    Q_UNUSED( version );

    QDomDocument doc;

    QgsWfsProjectParser* configParser = getConfigParser( serverIface );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
    QgsAccessControl* accessControl = serverIface->accessControls();
#endif
    const QString requestBody = request.getParameter( QStringLiteral( "REQUEST_BODY" ) );

    QString errorMsg;
    if ( !doc.setContent( requestBody, true, &errorMsg ) )
    {
      throw QgsRequestNotWellFormedException( errorMsg );
    }

    QDomElement docElem = doc.documentElement();
    QDomNodeList docChildNodes = docElem.childNodes();

    // Re-organize the transaction document
    QDomDocument mDoc;
    QDomElement mDocElem = mDoc.createElement( QStringLiteral( "myTransactionDocument" ) );
    mDocElem.setAttribute( QStringLiteral( "xmlns" ), QGS_NAMESPACE );
    mDocElem.setAttribute( QStringLiteral( "xmlns:wfs" ), WFS_NAMESPACE );
    mDocElem.setAttribute( QStringLiteral( "xmlns:gml" ), GML_NAMESPACE );
    mDocElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
    mDocElem.setAttribute( QStringLiteral( "xmlns:qgs" ), QGS_NAMESPACE );
    mDocElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
    mDoc.appendChild( mDocElem );

    QDomElement actionElem;
    QString actionName;
    QDomElement typeNameElem;
    QString typeName;

    for ( int i = docChildNodes.count(); 0 < i; --i )
    {
      actionElem = docChildNodes.at( i - 1 ).toElement();
      actionName = actionElem.localName();

      if ( actionName == QLatin1String( "Insert" ) )
      {
        QDomElement featureElem = actionElem.firstChild().toElement();
        typeName = featureElem.localName();
      }
      else if ( actionName == QLatin1String( "Update" ) )
      {
        typeName = actionElem.attribute( QStringLiteral( "typeName" ) );
      }
      else if ( actionName == QLatin1String( "Delete" ) )
      {
        typeName = actionElem.attribute( QStringLiteral( "typeName" ) );
      }

      if ( typeName.contains( QLatin1String( ":" ) ) )
        typeName = typeName.section( QStringLiteral( ":" ), 1, 1 );

      QDomNodeList typeNameList = mDocElem.elementsByTagName( typeName );
      if ( typeNameList.count() == 0 )
      {
        typeNameElem = mDoc.createElement( typeName );
        mDocElem.appendChild( typeNameElem );
      }
      else
        typeNameElem = typeNameList.at( 0 ).toElement();

      typeNameElem.appendChild( actionElem );
    }

    // It's time to make the transaction
    // Create the response document
    QDomDocument resp;
    //wfs:WFS_TransactionRespone element
    QDomElement respElem = resp.createElement( QStringLiteral( "WFS_TransactionResponse" )/*wfs:WFS_TransactionResponse*/ );
    respElem.setAttribute( QStringLiteral( "xmlns" ), WFS_NAMESPACE );
    respElem.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
    respElem.setAttribute( QStringLiteral( "xsi:schemaLocation" ), WFS_NAMESPACE + " http://schemas.opengis.net/wfs/1.0.0/wfs.xsd" );
    respElem.setAttribute( QStringLiteral( "xmlns:ogc" ), OGC_NAMESPACE );
    respElem.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.0.0" ) );
    resp.appendChild( respElem );

    // Store the created feature id for WFS
    QStringList insertResults;
    // Get the WFS layers id
    QStringList wfsLayersId = configParser->wfsLayers();;

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

    // Loop through the layer transaction elements
    docChildNodes = mDocElem.childNodes();
    for ( int i = 0; i < docChildNodes.count(); ++i )
    {
      // Get the vector layer
      typeNameElem = docChildNodes.at( i ).toElement();
      typeName = typeNameElem.tagName();

      layerList = configParser->mapLayerFromTypeName( typeName );
      // Could be empty!
      if ( layerList.count() > 0 )
      {
        currentLayer = layerList.at( 0 );
      }
      else
      {
        throw QgsRequestNotWellFormedException( QStringLiteral( "Wrong TypeName: %1" ).arg( typeName ) );
      }

      QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( currentLayer );
      // it's a vectorlayer and defined by the administrator as a WFS layer
      if ( layer && wfsLayersId.contains( layer->id() ) )
      {
#ifdef HAVE_SERVER_PYTHON_PLUGINS
        if ( actionName == QLatin1String( "Insert" ) )
        {
          if ( !accessControl->layerInsertPermission( layer ) )
          {
            throw QgsSecurityAccessException( QStringLiteral( "Feature insert permission denied" ) );
          }
        }
        else if ( actionName == QLatin1String( "Update" ) )
        {
          if ( !accessControl->layerUpdatePermission( layer ) )
          {
            throw QgsSecurityAccessException( QStringLiteral( "Feature update permission denied" ) );
          }
        }
        else if ( actionName == QLatin1String( "Delete" ) )
        {
          if ( !accessControl->layerDeletePermission( layer ) )
          {
            throw QgsSecurityAccessException( QStringLiteral( "Feature delete permission denied" ) );
          }
        }
#endif

        // Get the provider and it's capabilities
        QgsVectorDataProvider* provider = layer->dataProvider();
        if ( !provider )
        {
          continue;
        }

        int cap = provider->capabilities();

        // Start the update transaction
        layer->startEditing();
        if (( cap & QgsVectorDataProvider::ChangeAttributeValues ) && ( cap & QgsVectorDataProvider::ChangeGeometries ) )
        {
          // Loop through the update elements for this layer
          QDomNodeList upNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Update" ) );
          for ( int j = 0; j < upNodeList.count(); ++j )
          {
            if ( !configParser->wfstUpdateLayers().contains( layer->id() ) )
            {
              //no wfs permissions to do updates
              QString errorMsg = "No permissions to do WFS updates on layer '" + layer->name() + "'";
              QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL );
              addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Update" ), errorMsg );
              return resp;
            }

            actionElem = upNodeList.at( j ).toElement();

            // Get the Feature Ids for this filter on the layer
            QDomElement filterElem = actionElem.elementsByTagName( QStringLiteral( "Filter" ) ).at( 0 ).toElement();
            QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer );

            // Loop through the property elements
            // Store properties and the geometry element
            QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral( "Property" ) );
            QMap<QString, QString> propertyMap;
            QDomElement propertyElem;
            QDomElement nameElem;
            QDomElement valueElem;
            QDomElement geometryElem;

            for ( int l = 0; l < propertyNodeList.count(); ++l )
            {
              propertyElem = propertyNodeList.at( l ).toElement();
              nameElem = propertyElem.elementsByTagName( QStringLiteral( "Name" ) ).at( 0 ).toElement();
              valueElem = propertyElem.elementsByTagName( QStringLiteral( "Value" ) ).at( 0 ).toElement();
              if ( nameElem.text() != QLatin1String( "geometry" ) )
              {
                propertyMap.insert( nameElem.text(), valueElem.text() );
              }
              else
              {
                geometryElem = valueElem;
              }
            }

            // Update the features
            QgsFields fields = provider->fields();
            QMap<QString, int> fieldMap = provider->fieldNameMap();
            QMap<QString, int>::const_iterator fieldMapIt;
            QString fieldName;
            bool conversionSuccess;

            QgsFeatureIds::const_iterator fidIt = fids.constBegin();
            for ( ; fidIt != fids.constEnd(); ++fidIt )
            {
#ifdef HAVE_SERVER_PYTHON_PLUGINS
              QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) );
              QgsFeature feature;
              while ( fit.nextFeature( feature ) )
              {
                if ( !accessControl->allowToEdit( layer, feature ) )
                {
                  throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) );
                }
              }
#endif

              QMap< QString, QString >::const_iterator it = propertyMap.constBegin();
              for ( ; it != propertyMap.constEnd(); ++it )
              {
                fieldName = it.key();
                fieldMapIt = fieldMap.find( fieldName );
                if ( fieldMapIt == fieldMap.constEnd() )
                {
                  continue;
                }
                QgsField field = fields.at( fieldMapIt.value() );
                if ( field.type() == 2 )
                  layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toInt( &conversionSuccess ) );
                else if ( field.type() == 6 )
                  layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value().toDouble( &conversionSuccess ) );
                else
                  layer->changeAttributeValue( *fidIt, fieldMapIt.value(), it.value() );
              }

              if ( !geometryElem.isNull() )
              {
                QgsGeometry g = QgsOgcUtils::geometryFromGML( geometryElem );
                if ( !layer->changeGeometry( *fidIt, g ) )
                {
                  throw QgsRequestNotWellFormedException( QStringLiteral( "Error in change geometry" ) );
                }
              }

#ifdef HAVE_SERVER_PYTHON_PLUGINS
              fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) );
              while ( fit.nextFeature( feature ) )
              {
                if ( !accessControl->allowToEdit( layer, feature ) )
                {
                  layer->rollBack();
                  throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) );
                }
              }
#endif
            }
          }
        }
        // Commit the changes of the update elements
        if ( !layer->commitChanges() )
        {
          addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Update" ), layer->commitErrors().join( QStringLiteral( "\n  " ) ) );
          return resp;
        }
        // Start the delete transaction
        layer->startEditing();
        if (( cap & QgsVectorDataProvider::DeleteFeatures ) )
        {
          // Loop through the delete elements
          QDomNodeList delNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Delete" ) );
          for ( int j = 0; j < delNodeList.count(); ++j )
          {
            if ( !configParser->wfstDeleteLayers().contains( layer->id() ) )
            {
              //no wfs permissions to do updates
              QString errorMsg = "No permissions to do WFS deletes on layer '" + layer->name() + "'";
              QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL );
              addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Delete" ), errorMsg );
              return resp;
            }

            actionElem = delNodeList.at( j ).toElement();
            QDomElement filterElem = actionElem.firstChild().toElement();
            // Get Feature Ids for the Filter element
            QgsFeatureIds fids = getFeatureIdsFromFilter( filterElem, layer );

#ifdef HAVE_SERVER_PYTHON_PLUGINS
            QgsFeatureIds::const_iterator fidIt = fids.constBegin();
            for ( ; fidIt != fids.constEnd(); ++fidIt )
            {
              QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest( *fidIt ) );
              QgsFeature feature;
              while ( fit.nextFeature( feature ) )
              {
                if ( !accessControl->allowToEdit( layer, feature ) )
                {
                  throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) );
                }
              }
            }
#endif

            layer->selectByIds( fids );
            layer->deleteSelectedFeatures();
          }
        }
        // Commit the changes of the delete elements
        if ( !layer->commitChanges() )
        {
          addTransactionResult( resp, respElem, QStringLiteral( "PARTIAL" ), QStringLiteral( "Delete" ), layer->commitErrors().join( QStringLiteral( "\n  " ) ) );
          return resp;
        }

        // Store the inserted features
        QgsFeatureList inFeatList;
        if ( cap & QgsVectorDataProvider::AddFeatures )
        {
          // Get Layer Field Information
          QgsFields fields = provider->fields();
          QMap<QString, int> fieldMap = provider->fieldNameMap();
          QMap<QString, int>::const_iterator fieldMapIt;

          // Loop through the insert elements
          QDomNodeList inNodeList = typeNameElem.elementsByTagNameNS( WFS_NAMESPACE, QStringLiteral( "Insert" ) );
          for ( int j = 0; j < inNodeList.count(); ++j )
          {
            if ( !configParser->wfstInsertLayers().contains( layer->id() ) )
            {
              //no wfs permissions to do updates
              QString errorMsg = "No permissions to do WFS inserts on layer '" + layer->name() + "'";
              QgsMessageLog::logMessage( errorMsg, QStringLiteral( "Server" ), QgsMessageLog::CRITICAL );
              addTransactionResult( resp, respElem, QStringLiteral( "FAILED" ), QStringLiteral( "Insert" ), errorMsg );
              return resp;
            }

            actionElem = inNodeList.at( j ).toElement();
            // Loop through the feature element
            QDomNodeList featNodes = actionElem.childNodes();
            for ( int l = 0; l < featNodes.count(); l++ )
            {
              // Add the feature to the layer
              // and store it to put it's Feature Id in the response
              inFeatList << QgsFeature( fields );

              // Create feature for this layer
              QDomElement featureElem = featNodes.at( l ).toElement();

              QDomNode currentAttributeChild = featureElem.firstChild();

              while ( !currentAttributeChild.isNull() )
              {
                QDomElement currentAttributeElement = currentAttributeChild.toElement();
                QString attrName = currentAttributeElement.localName();

                if ( attrName != QLatin1String( "boundedBy" ) )
                {
                  if ( attrName != QLatin1String( "geometry" ) ) //a normal attribute
                  {
                    fieldMapIt = fieldMap.find( attrName );
                    if ( fieldMapIt == fieldMap.constEnd() )
                    {
                      continue;
                    }
                    QgsField field = fields.at( fieldMapIt.value() );
                    QString attrValue = currentAttributeElement.text();
                    int attrType = field.type();
                    QgsMessageLog::logMessage( QStringLiteral( "attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) );
                    if ( attrType == QVariant::Int )
                      inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toInt() );
                    else if ( attrType == QVariant::Double )
                      inFeatList.last().setAttribute( fieldMapIt.value(), attrValue.toDouble() );
                    else
                      inFeatList.last().setAttribute( fieldMapIt.value(), attrValue );
                  }
                  else //a geometry attribute
                  {
                    QgsGeometry g = QgsOgcUtils::geometryFromGML( currentAttributeElement );
                    inFeatList.last().setGeometry( g );
                  }
                }
                currentAttributeChild = currentAttributeChild.nextSibling();
              }
            }
          }
        }
#ifdef HAVE_SERVER_PYTHON_PLUGINS
        QgsFeatureList::iterator featureIt = inFeatList.begin();
        while ( featureIt != inFeatList.end() )
        {
          if ( !accessControl->allowToEdit( layer, *featureIt ) )
          {
            throw QgsSecurityAccessException( QStringLiteral( "Feature modify permission denied" ) );
          }
          featureIt++;
        }
#endif

        // add the features
        if ( !provider->addFeatures( inFeatList ) )
        {
          addTransactionResult( resp, respElem, QStringLiteral( "Partial" ), QStringLiteral( "Insert" ), layer->commitErrors().join( QStringLiteral( "\n  " ) ) );
          if ( provider->hasErrors() )
          {
            provider->clearErrors();
          }
          return resp;
        }
        // Get the Feature Ids of the inserted feature
        for ( int j = 0; j < inFeatList.size(); j++ )
        {
          insertResults << typeName + "." + QString::number( inFeatList[j].id() );
        }
      }
    }

    // Put the Feature Ids of the inserted feature
    if ( !insertResults.isEmpty() )
    {
      Q_FOREACH ( const QString &fidStr, insertResults )
      {
        QDomElement irElem = doc.createElement( QStringLiteral( "InsertResult" ) );
        QDomElement fiElem = doc.createElement( QStringLiteral( "ogc:FeatureId" ) );
        fiElem.setAttribute( QStringLiteral( "fid" ), fidStr );
        irElem.appendChild( fiElem );
        respElem.appendChild( irElem );
      }
Exemplo n.º 24
0
bool QgsLayoutAtlas::endRender()
{
  emit featureChanged( QgsFeature() );
  emit renderEnded();
  return true;
}
Exemplo n.º 25
0
QgsExpressionContextScope* QgsExpressionContextUtils::atlasScope( const QgsAtlasComposition* atlas )
{
  QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
  if ( !atlas )
  {
    //add some dummy atlas variables. This is done so that as in certain contexts we want to show
    //users that these variables are available even if they have no current value
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_pagename", QString(), true ) );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_feature", QVariant::fromValue( QgsFeature() ), true ) );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_featureid", 0, true ) );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_geometry", QVariant::fromValue( QgsGeometry() ), true ) );
    return scope;
  }

  //add known atlas variables
  scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_totalfeatures", atlas->numFeatures(), true ) );
  scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_featurenumber", atlas->currentFeatureNumber() + 1, true ) );
  scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_filename", atlas->currentFilename(), true ) );
  scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_pagename", atlas->currentPageName(), true ) );

  if ( atlas->enabled() && atlas->coverageLayer() )
  {
    scope->setFields( atlas->coverageLayer()->fields() );
  }

  if ( atlas->enabled() )
  {
    QgsFeature atlasFeature = atlas->feature();
    scope->setFeature( atlasFeature );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_feature", QVariant::fromValue( atlasFeature ), true ) );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_featureid", atlasFeature.id(), true ) );
    scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_geometry", QVariant::fromValue( *atlasFeature.constGeometry() ), true ) );
  }

  return scope;
}
Exemplo n.º 26
0
bool QgsMapToolIdentify::identifyVectorLayer( QList<IdentifyResult> *results, QgsVectorLayer *layer, const QgsPoint& point )
{
  if ( !layer || !layer->hasGeometryType() )
    return false;

  if ( layer->hasScaleBasedVisibility() &&
       ( layer->minimumScale() > mCanvas->mapSettings().scale() ||
         layer->maximumScale() <= mCanvas->mapSettings().scale() ) )
  {
    QgsDebugMsg( "Out of scale limits" );
    return false;
  }

  QApplication::setOverrideCursor( Qt::WaitCursor );

  QMap< QString, QString > commonDerivedAttributes;

  commonDerivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );

  int featureCount = 0;

  QgsFeatureList featureList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // 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.
  try
  {
    // create the search rectangle
    double searchRadius = searchRadiusMU( mCanvas );

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featureList << QgsFeature( f );
  }
  catch ( QgsCsException & cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and proceed with no features found
    QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) );
  }

  QgsFeatureList::iterator f_it = featureList.begin();

  bool filter = false;

  QgsRenderContext context( QgsRenderContext::fromMapSettings( mCanvas->mapSettings() ) );
  context.expressionContext() << QgsExpressionContextUtils::layerScope( layer );
  QgsFeatureRendererV2* renderer = layer->rendererV2();
  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    // setup scale for scale dependent visibility (rule based)
    renderer->startRender( context, layer->fields() );
    filter = renderer->capabilities() & QgsFeatureRendererV2::Filter;
  }

  for ( ; f_it != featureList.end(); ++f_it )
  {
    QMap< QString, QString > derivedAttributes = commonDerivedAttributes;

    QgsFeatureId fid = f_it->id();
    context.expressionContext().setFeature( *f_it );

    if ( filter && !renderer->willRenderFeature( *f_it, context ) )
      continue;

    featureCount++;

    derivedAttributes.unite( featureDerivedAttributes( &( *f_it ), layer, toLayerCoordinates( layer, point ) ) );

    derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) );

    results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), *f_it, derivedAttributes ) );
  }

  if ( renderer && renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
  {
    renderer->stopRender( context );
  }

  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );

  QApplication::restoreOverrideCursor();
  return featureCount > 0;
}
Exemplo n.º 27
0
bool QgsMapToolFeatureAction::doAction( QgsVectorLayer *layer, int x, int y )
{
  if ( !layer )
    return false;

  QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );

  QgsFeatureList featList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // 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.
  try
  {
    // create the search rectangle
    double searchRadius = searchRadiusMU( mCanvas );

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featList << QgsFeature( f );
  }
  catch ( QgsCsException & cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and proceed with no features found
    QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) );
  }

  if ( featList.size() == 0 )
    return false;

  Q_FOREACH ( const QgsFeature& feat, featList )
  {
    if ( layer->actions()->defaultAction() >= 0 )
    {
      // define custom substitutions: layer id and clicked coords
      QMap<QString, QVariant> substitutionMap;
      substitutionMap.insert( "$layerid", layer->id() );
      point = toLayerCoordinates( layer, point );
      substitutionMap.insert( "$clickx", point.x() );
      substitutionMap.insert( "$clicky", point.y() );

      int actionIdx = layer->actions()->defaultAction();
      layer->actions()->doAction( actionIdx, feat, &substitutionMap );
    }
    else
    {
      QgsMapLayerAction* mapLayerAction = QgsMapLayerActionRegistry::instance()->defaultActionForLayer( layer );
      if ( mapLayerAction )
      {
        mapLayerAction->triggerForFeature( layer, &feat );
      }
    }
  }

  return true;
}
Exemplo n.º 28
0
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
{
    if ( !L->hasGeometryType() )
        return 4;

    QgsFeatureList newFeatures; //store all the newly created features
    double xMin, yMin, xMax, yMax;
    QgsRectangle bBox; //bounding box of the split line
    int returnCode = 0;
    int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
    int numberOfSplittedFeatures = 0;

    QgsFeatureList featureList;
    const QgsFeatureIds selectedIds = L->selectedFeaturesIds();

    if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
    {
        featureList = L->selectedFeatures();
    }
    else //else consider all the feature that intersect the bounding box of the split line
    {
        if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
        {
            bBox.setXMinimum( xMin );
            bBox.setYMinimum( yMin );
            bBox.setXMaximum( xMax );
            bBox.setYMaximum( yMax );
        }
        else
        {
            return 1;
        }

        if ( bBox.isEmpty() )
        {
            //if the bbox is a line, try to make a square out of it
            if ( bBox.width() == 0.0 && bBox.height() > 0 )
            {
                bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
                bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
            }
            else if ( bBox.height() == 0.0 && bBox.width() > 0 )
            {
                bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
                bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
            }
            else
            {
                //If we have a single point, we still create a non-null box
                double bufferDistance = 0.000001;
                if ( L->crs().geographicFlag() )
                    bufferDistance = 0.00000001;
                bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
                bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
                bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
                bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
            }
        }

        QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );

        QgsFeature f;
        while ( fit.nextFeature( f ) )
            featureList << QgsFeature( f );
    }

    QgsFeatureList::iterator select_it = featureList.begin();
    for ( ; select_it != featureList.end(); ++select_it )
    {
        if ( !select_it->geometry() )
        {
            continue;
        }
        QList<QgsGeometry*> newGeometries;
        QList<QgsPoint> topologyTestPoints;
        QgsGeometry* newGeometry = 0;
        splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
        if ( splitFunctionReturn == 0 )
        {
            //change this geometry
            L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() );

            //insert new features
            for ( int i = 0; i < newGeometries.size(); ++i )
            {
                newGeometry = newGeometries.at( i );
                QgsFeature newFeature;
                newFeature.setGeometry( newGeometry );

                //use default value where possible for primary key (e.g. autoincrement),
                //and use the value from the original (split) feature if not primary key
                QgsAttributes newAttributes = select_it->attributes();
                foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
                {
                    const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
                    if ( !defaultValue.isNull() )
                    {
                        newAttributes[ pkIdx ] = defaultValue;
                    }
                    else //try with NULL
                    {
                        newAttributes[ pkIdx ] = QVariant();
                    }
                }

                newFeature.setAttributes( newAttributes );

                newFeatures.append( newFeature );
            }

            if ( topologicalEditing )
            {
                QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
                for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
                {
                    addTopologicalPoints( *topol_it );
                }
            }
            ++numberOfSplittedFeatures;
        }
        else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
void QgsPointDisplacementRenderer::createDisplacementGroups( QgsVectorLayer* vlayer, const QgsRectangle& viewExtent )
{
  if ( !vlayer || ( vlayer->wkbType() != QGis::WKBPoint && vlayer->wkbType() != QGis::WKBPoint25D ) )
  {
    return;
  }

  mDisplacementGroups.clear();
  mDisplacementIds.clear();

  //use a spatial index to check if there is already a point at a position
  QgsSpatialIndex spatialIndex;

  //attributes
  QgsAttributeList attList;
  QList<QString> attributeStrings = usedAttributes();
  QList<QString>::const_iterator attStringIt = attributeStrings.constBegin();
  for ( ; attStringIt != attributeStrings.constEnd(); ++attStringIt )
  {
    attList.push_back( vlayer->fieldNameIndex( *attStringIt ) );
  }

  QgsFeature f;
  QList<QgsFeatureId> intersectList;

  //Because the new vector api does not allow querying features by id within a nextFeature loop, default constructed QgsFeature() is
  //inserted first and the real features are created in a second loop

  QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( viewExtent ).setSubsetOfAttributes( attList ) );
  while ( fit.nextFeature( f ) )
  {
    intersectList.clear();

    //check, if there is already a point at that position
    if ( f.geometry() )
    {
      intersectList = spatialIndex.intersects( searchRect( f.geometry()->asPoint() ) );
      if ( intersectList.empty() )
      {
        spatialIndex.insertFeature( f );
      }
      else
      {
        //go through all the displacement group maps and search an entry where the id equals the result of the spatial search
        QgsFeatureId existingEntry = intersectList.at( 0 );
        bool found = false;
        QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
        for ( ; it != mDisplacementGroups.end(); ++it )
        {
          if ( it->size() > 0 && it->contains( existingEntry ) )
          {
            found = true;
            QgsFeature feature;
            it->insert( f.id(), QgsFeature() );
            mDisplacementIds.insert( f.id() );
            break;
          }
        }

        if ( !found )//insert the already existing feature and the new one into a map
        {
          QMap<QgsFeatureId, QgsFeature> newMap;
          newMap.insert( existingEntry, QgsFeature() );
          mDisplacementIds.insert( existingEntry );
          newMap.insert( f.id(), QgsFeature() );
          mDisplacementIds.insert( f.id() );
          mDisplacementGroups.push_back( newMap );
        }
      }
    }
  }

  //insert the real features into mDisplacementGroups
  QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
  for ( ; it != mDisplacementGroups.end(); ++it )
  {
    QMap<QgsFeatureId, QgsFeature>::iterator mapIt = it->begin();
    for ( ; mapIt != it->end(); ++mapIt )
    {
      QgsFeature fet;
      vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mapIt.key() ) ).nextFeature( fet );
      mapIt.value() = fet;
    }
  }

}
Exemplo n.º 30
0
bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int y )
{
  if ( !layer )
    return false;

  QMap< QString, QString > attributes, derivedAttributes;

  QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );

  derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() );

  // load identify radius from settings
  QSettings settings;
  double identifyValue = settings.value( "/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS ).toDouble();
  QString ellipsoid = settings.value( "/qgis/measure/ellipsoid", "WGS84" ).toString();

  if ( identifyValue <= 0.0 )
    identifyValue = QGis::DEFAULT_IDENTIFY_RADIUS;

  int featureCount = 0;

  QgsFeatureList featureList;

  // toLayerCoordinates will throw an exception for an 'invalid' point.
  // 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.
  try
  {
    // create the search rectangle
    double searchRadius = mCanvas->extent().width() * ( identifyValue / 100.0 );

    QgsRectangle r;
    r.setXMinimum( point.x() - searchRadius );
    r.setXMaximum( point.x() + searchRadius );
    r.setYMinimum( point.y() - searchRadius );
    r.setYMaximum( point.y() + searchRadius );

    r = toLayerCoordinates( layer, r );

    layer->select( layer->pendingAllAttributesList(), r, true, true );
    QgsFeature f;
    while ( layer->nextFeature( f ) )
      featureList << QgsFeature( f );
  }
  catch ( QgsCsException & cse )
  {
    Q_UNUSED( cse );
    // catch exception for 'invalid' point and proceed with no features found
    QgsDebugMsg( QString( "Caught CRS exception %1" ).arg( cse.what() ) );
  }

  // init distance/area calculator
  QgsDistanceArea calc;
  if ( !featureList.count() == 0 )
  {
    calc.setProjectionsEnabled( mCanvas->hasCrsTransformEnabled() ); // project?
    calc.setEllipsoid( ellipsoid );
    calc.setSourceCrs( layer->crs().srsid() );
  }
  QgsFeatureList::iterator f_it = featureList.begin();

  for ( ; f_it != featureList.end(); ++f_it )
  {
    featureCount++;

    QgsFeatureId fid = f_it->id();
    QMap<QString, QString> derivedAttributes;

    // Calculate derived attributes and insert:
    // measure distance or area depending on geometry type
    if ( layer->geometryType() == QGis::Line )
    {
      double dist = calc.measure( f_it->geometry() );
      QGis::UnitType myDisplayUnits;
      convertMeasurement( calc, dist, myDisplayUnits, false );
      QString str = calc.textUnit( dist, 3, myDisplayUnits, false );  // dist and myDisplayUnits are out params
      derivedAttributes.insert( tr( "Length" ), str );
      if ( f_it->geometry()->wkbType() == QGis::WKBLineString ||
           f_it->geometry()->wkbType() == QGis::WKBLineString25D )
      {
        // Add the start and end points in as derived attributes
        str = QLocale::system().toString( f_it->geometry()->asPolyline().first().x(), 'g', 10 );
        derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
        str = QLocale::system().toString( f_it->geometry()->asPolyline().first().y(), 'g', 10 );
        derivedAttributes.insert( tr( "firstY" ), str );
        str = QLocale::system().toString( f_it->geometry()->asPolyline().last().x(), 'g', 10 );
        derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
        str = QLocale::system().toString( f_it->geometry()->asPolyline().last().y(), 'g', 10 );
        derivedAttributes.insert( tr( "lastY" ), str );
      }
    }
    else if ( layer->geometryType() == QGis::Polygon )
    {
      double area = calc.measure( f_it->geometry() );
      QGis::UnitType myDisplayUnits;
      convertMeasurement( calc, area, myDisplayUnits, true );  // area and myDisplayUnits are out params
      QString str = calc.textUnit( area, 3, myDisplayUnits, true );
      derivedAttributes.insert( tr( "Area" ), str );
    }
    else if ( layer->geometryType() == QGis::Point &&
              ( f_it->geometry()->wkbType() == QGis::WKBPoint ||
                f_it->geometry()->wkbType() == QGis::WKBPoint25D ) )
    {
      // Include the x and y coordinates of the point as a derived attribute
      QString str;
      str = QLocale::system().toString( f_it->geometry()->asPoint().x(), 'g', 10 );
      derivedAttributes.insert( "X", str );
      str = QLocale::system().toString( f_it->geometry()->asPoint().y(), 'g', 10 );
      derivedAttributes.insert( "Y", str );
    }

    derivedAttributes.insert( tr( "feature id" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) );

    results()->addFeature( layer, *f_it, derivedAttributes );
  }

  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );

  return featureCount > 0;
}