Exemplo n.º 1
0
void QgsAttributeTableDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
  QgsVectorLayer *vl = layer( model );
  if ( !vl )
    return;

  int fieldIdx = model->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();
  QgsFeatureId fid = model->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
  QVariant oldValue = model->data( index, Qt::EditRole );

  QVariant newValue;
  QgsEditorWidgetWrapper *eww = QgsEditorWidgetWrapper::fromWidget( editor );
  if ( !eww )
    return;

  newValue = eww->value();

  if ( ( oldValue != newValue && newValue.isValid() ) || oldValue.isNull() != newValue.isNull() )
  {
    // This fixes https://issues.qgis.org/issues/16492
    QgsFeatureRequest request( fid );
    request.setFlags( QgsFeatureRequest::NoGeometry );
    request.setSubsetOfAttributes( QgsAttributeList() );
    QgsFeature feature;
    vl->getFeatures( request ).nextFeature( feature );
    if ( feature.isValid() )
    {
      vl->beginEditCommand( tr( "Attribute changed" ) );
      vl->changeAttributeValue( fid, fieldIdx, newValue, oldValue );
      vl->endEditCommand();
    }
  }
}
Exemplo n.º 2
0
QWidget *QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  Q_UNUSED( option );
  QgsVectorLayer *vl = layer( index.model() );
  if ( !vl )
    return nullptr;

  int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();

  QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup );
  QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vl, fieldIdx, nullptr, parent, context );
  QWidget *w = eww->widget();

  w->setAutoFillBackground( true );
  w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget

  const int fieldOrigin = vl->fields().fieldOrigin( fieldIdx );
  bool readOnly = true;
  if ( fieldOrigin == QgsFields::OriginJoin )
  {
    int srcFieldIndex;
    const QgsVectorLayerJoinInfo *info = vl->joinBuffer()->joinForFieldIndex( fieldIdx, vl->fields(), srcFieldIndex );

    if ( info && info->isEditable() )
      readOnly = info->joinLayer()->editFormConfig().readOnly( srcFieldIndex );
  }
  else
    readOnly = vl->editFormConfig().readOnly( fieldIdx );

  eww->setEnabled( !readOnly );

  return w;
}
Exemplo n.º 3
0
    void testUpdate()
    {
      const QgsKeyValueWidgetFactory factory( QStringLiteral( "testKeyValue" ) );
      QgsEditorWidgetWrapper* wrapper = factory.create( nullptr, 0, nullptr, nullptr );
      QVERIFY( wrapper );
      QSignalSpy spy( wrapper, SIGNAL( valueChanged( const QVariant& ) ) );

      QgsKeyValueWidget* widget = qobject_cast< QgsKeyValueWidget* >( wrapper->widget() );
      QVERIFY( widget );

      QVariantMap initial;
      initial[QStringLiteral( "1" )] = "one";
      initial[QStringLiteral( "2" )] = "two";
      wrapper->setValue( initial );

      const QVariant value = wrapper->value();
      QCOMPARE( int( value.type() ), int( QVariant::Map ) );
      QCOMPARE( value.toMap(), initial );
      QCOMPARE( spy.count(), 0 );

      QAbstractItemModel* model = widget->tableView->model();
      model->setData( model->index( 0, 1 ), "hello" );
      QCOMPARE( spy.count(), 1 );

      QVariantMap expected = initial;
      expected[QStringLiteral( "1" )] = "hello";
      QVariant eventValue = spy.at( 0 ).at( 0 ).value<QVariant>();
      QCOMPARE( int( eventValue.type() ), int( QVariant::Map ) );
      QCOMPARE( eventValue.toMap(), expected );
      QCOMPARE( wrapper->value().toMap(), expected );
      QCOMPARE( spy.count(), 1 );
    }
Exemplo n.º 4
0
void QgsAttributeTableDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
{
  QgsEditorWidgetWrapper* eww =  QgsEditorWidgetWrapper::fromWidget( editor );
  if ( !eww )
    return;

  eww->setValue( index.model()->data( index, Qt::EditRole ) );
}
Exemplo n.º 5
0
 Q_FOREACH ( QgsWidgetWrapper* ww, mWidgets )
 {
   QgsEditorWidgetWrapper* eww = qobject_cast<QgsEditorWidgetWrapper*>( ww );
   if ( eww && eww->field().name() == field )
   {
     eww->setValue( value );
   }
 }
Exemplo n.º 6
0
QWidget* QgsAttributeEditor::createAttributeEditor( QWidget* parent, QWidget* editor, QgsVectorLayer* vl, int idx, const QVariant& value, QgsAttributeEditorContext& context )
{
  QString widgetType = vl->editFormConfig()->widgetType( idx );
  QgsEditorWidgetConfig cfg = vl->editFormConfig()->widgetConfig( idx );

  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, vl, idx, cfg, editor, parent, context );

  if ( eww )
  {
    eww->setValue( value );
    return eww->widget();
  }
  else
  {
    return 0;
  }
}
Exemplo n.º 7
0
QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QVariantMap& config, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext &context )
{
  if ( mWidgetFactories.contains( widgetId ) )
  {
    QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );

    if ( ww )
    {
      ww->setConfig( config );
      ww->setContext( context );
      // Make sure that there is a widget created at this point
      // so setValue() et al won't crash
      ww->widget();

      // If we tried to set a widget which is not supported by this wrapper
      if ( !ww->valid() )
      {
        delete ww;
        QString wid = findSuitableWrapper( editor, QStringLiteral( "TextEdit" ) );
        ww = mWidgetFactories[wid]->create( vl, fieldIdx, editor, parent );
        ww->setConfig( config );
        ww->setContext( context );
      }

      return ww;
    }
  }

  return nullptr;
}
Exemplo n.º 8
0
QgsEditorWidgetWrapper* QgsEditorWidgetRegistry::create( const QString& widgetId, QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, QWidget* editor, QWidget* parent, const QgsAttributeEditorContext &context )
{
  if ( mWidgetFactories.contains( widgetId ) )
  {
    QgsEditorWidgetWrapper* ww = mWidgetFactories[widgetId]->create( vl, fieldIdx, editor, parent );

    if ( ww )
    {
      ww->setConfig( config );
      ww->setContext( context );
      // Make sure that there is a widget created at this point
      // so setValue() et al won't crash
      ww->widget();
      return ww;
    }
  }
  return 0;
}
QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  Q_UNUSED( option );
  QgsVectorLayer *vl = layer( index.model() );
  if ( !vl )
    return nullptr;

  int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();

  QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup );
  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( vl, fieldIdx, nullptr, parent, context );
  QWidget* w = eww->widget();

  w->setAutoFillBackground( true );
  w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget

  eww->setEnabled( !vl->editFormConfig().readOnly( fieldIdx ) );

  return w;
}
Exemplo n.º 10
0
QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
{
  Q_UNUSED( option );
  QgsVectorLayer *vl = layer( index.model() );
  if ( !vl )
    return nullptr;

  int fieldIdx = index.model()->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();

  QString widgetType = vl->editFormConfig()->widgetType( fieldIdx );
  QgsEditorWidgetConfig cfg = vl->editFormConfig()->widgetConfig( fieldIdx );
  QgsAttributeEditorContext context( masterModel( index.model() )->editorContext(), QgsAttributeEditorContext::Popup );
  QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, vl, fieldIdx, cfg, nullptr, parent, context );
  QWidget* w = eww->widget();

  w->setAutoFillBackground( true );

  eww->setEnabled( !vl->editFormConfig()->readOnly( fieldIdx ) );

  return w;
}
Exemplo n.º 11
0
QWidget *QgsFormAnnotation::createDesignerWidget( const QString &filePath )
{
  QFile file( filePath );
  if ( !file.open( QFile::ReadOnly ) )
  {
    return nullptr;
  }

  QUiLoader loader;
  QFileInfo fi( file );
  loader.setWorkingDirectory( fi.dir() );
  QWidget *widget = loader.load( &file, nullptr );
  file.close();

  //get feature and set attribute information
  QgsAttributeEditorContext context;
  QgsVectorLayer *vectorLayer = qobject_cast< QgsVectorLayer * >( mapLayer() );
  if ( vectorLayer && associatedFeature().isValid() )
  {
    QgsFields fields = vectorLayer->fields();
    QgsAttributes attrs = associatedFeature().attributes();
    for ( int i = 0; i < attrs.count(); ++i )
    {
      if ( i < fields.count() )
      {
        QWidget *attWidget = widget->findChild<QWidget *>( fields.at( i ).name() );
        if ( attWidget )
        {
          QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( vectorLayer, i, attWidget, widget, context );
          if ( eww )
          {
            eww->setValue( attrs.at( i ) );
          }
        }
      }
    }
  }
  return widget;
}
Exemplo n.º 12
0
void QgsAttributeTableDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
{
  QgsVectorLayer *vl = layer( model );
  if ( vl == NULL )
    return;

  int fieldIdx = model->data( index, QgsAttributeTableModel::FieldIndexRole ).toInt();
  QgsFeatureId fid = model->data( index, QgsAttributeTableModel::FeatureIdRole ).toLongLong();
  QVariant oldValue = model->data( index, Qt::EditRole );

  QVariant newValue;
  QgsEditorWidgetWrapper* eww = QgsEditorWidgetWrapper::fromWidget( editor );
  if ( !eww )
    return;

  newValue = eww->value();

  if (( oldValue != newValue && newValue.isValid() ) || oldValue.isNull() != newValue.isNull() )
  {
    vl->beginEditCommand( tr( "Attribute changed" ) );
    vl->changeAttributeValue( fid, fieldIdx, newValue, oldValue );
    vl->endEditCommand();
  }
}
Exemplo n.º 13
0
void QgsMergeAttributesDialog::createTableWidgetContents()
{
  //get information about attributes from vector layer
  if ( !mVectorLayer )
  {
    return;
  }

  //combo box row, attributes titles, feature values and current merge results
  mTableWidget->setRowCount( mFeatureList.size() + 2 );

  //create combo boxes and insert attribute names
  mFields = mVectorLayer->fields();
  QSet<int> pkAttrList = mVectorLayer->pkAttributeList().toSet();

  int col = 0;
  mHiddenAttributes.clear();
  for ( int idx = 0; idx < mFields.count(); ++idx )
  {
    const QgsEditorWidgetSetup setup = QgsEditorWidgetRegistry::instance()->findBest( mVectorLayer, mFields.at( idx ).name() );
    if ( setup.type() == "Hidden" || setup.type() == "Immutable" )
    {
      mHiddenAttributes.insert( idx );
      continue;
    }

    mTableWidget->setColumnCount( col + 1 );

    QComboBox *cb = createMergeComboBox( mFields.at( idx ).type() );
    if ( pkAttrList.contains( idx ) )
    {
      cb->setCurrentIndex( cb->findData( "skip" ) );
    }
    mTableWidget->setCellWidget( 0, col, cb );

    QTableWidgetItem *item = new QTableWidgetItem( mFields.at( idx ).name() );
    item->setData( FieldIndex, idx );
    mTableWidget->setHorizontalHeaderItem( col++, item );
  }

  //insert the attribute values
  QStringList verticalHeaderLabels; //the id column is in the
  verticalHeaderLabels << tr( "Id" );

  QgsAttributeEditorContext context;

  for ( int i = 0; i < mFeatureList.size(); ++i )
  {
    verticalHeaderLabels << FID_TO_STRING( mFeatureList[i].id() );

    QgsAttributes attrs = mFeatureList.at( i ).attributes();

    for ( int j = 0; j < mTableWidget->columnCount(); j++ )
    {
      int idx = mTableWidget->horizontalHeaderItem( j )->data( FieldIndex ).toInt();

      QTableWidgetItem* attributeValItem = new QTableWidgetItem( attrs.at( idx ).toString() );
      attributeValItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable );
      mTableWidget->setItem( i + 1, j, attributeValItem );
      QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( mVectorLayer, idx, nullptr, mTableWidget, context );
      if ( eww )
      {
        eww->setValue( attrs.at( idx ) );
      }
      mTableWidget->setCellWidget( i + 1, j, eww->widget() );
    }
  }

  //merge
  verticalHeaderLabels << tr( "Merge" );
  mTableWidget->setVerticalHeaderLabels( verticalHeaderLabels );

  //insert currently merged values
  for ( int i = 0; i < mTableWidget->columnCount(); ++i )
  {
    refreshMergedValue( i );
  }
}
Exemplo n.º 14
0
void TestQgsAttributeForm::testFieldConstraint()
{
  // make a temporary vector layer
  QString def = QStringLiteral( "Point?field=col0:integer" );
  QgsVectorLayer* layer = new QgsVectorLayer( def, QStringLiteral( "test" ), QStringLiteral( "memory" ) );
  layer->setEditorWidgetSetup( 0, QgsEditorWidgetSetup( QStringLiteral( "TextEdit" ), QVariantMap() ) );

  // add a feature to the vector layer
  QgsFeature ft( layer->dataProvider()->fields(), 1 );
  ft.setAttribute( QStringLiteral( "col0" ), 0 );

  // build a form for this feature
  QgsAttributeForm form( layer );
  form.setFeature( ft );

  // testing stuff
  QString validLabel = QStringLiteral( "col0<font color=\"green\">✔</font>" );
  QString invalidLabel = QStringLiteral( "col0<font color=\"red\">✘</font>" );
  QString warningLabel = QStringLiteral( "col0<font color=\"orange\">✘</font>" );

  // set constraint
  layer->setConstraintExpression( 0, QString() );

  // get wrapper
  QgsEditorWidgetWrapper *ww;
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form.mWidgets[0] );

  // no constraint so we expect a label with just the field name
  QLabel *label = form.mBuddyMap.value( ww->widget() );
  QCOMPARE( label->text(), QString( "col0" ) );

  // set a not null constraint
  layer->setConstraintExpression( 0, QStringLiteral( "col0 is not null" ) );
  // build a form for this feature
  QgsAttributeForm form2( layer );
  form2.setFeature( ft );
  QSignalSpy spy( &form2, SIGNAL( attributeChanged( QString, QVariant ) ) );
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form2.mWidgets[0] );
  label = form2.mBuddyMap.value( ww->widget() );

  // set value to 1
  ww->setValue( 1 );
  QCOMPARE( spy.count(), 2 );
  QCOMPARE( label->text(), validLabel );

  // set value to null
  spy.clear();
  ww->setValue( QVariant() );
  QCOMPARE( spy.count(), 2 );
  QCOMPARE( label->text(), invalidLabel );

  // set value to 1
  spy.clear();
  ww->setValue( 1 );
  QCOMPARE( spy.count(), 2 );
  QCOMPARE( label->text(), validLabel );

  // set a soft constraint
  layer->setConstraintExpression( 0, QStringLiteral( "col0 is not null" ) );
  layer->setFieldConstraint( 0, QgsFieldConstraints::ConstraintExpression, QgsFieldConstraints::ConstraintStrengthSoft );
  // build a form for this feature
  QgsAttributeForm form3( layer );
  form3.setFeature( ft );
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form3.mWidgets[0] );
  label = form3.mBuddyMap.value( ww->widget() );

  // set value to 1
  ww->setValue( 1 );
  QCOMPARE( label->text(), validLabel );

  // set value to null
  ww->setValue( QVariant() );
  QCOMPARE( label->text(), warningLabel );

  // set value to 1
  ww->setValue( 1 );
  QCOMPARE( label->text(), validLabel );
}
Exemplo n.º 15
0
void TestQgsAttributeForm::testOKButtonStatus()
{
  // make a temporary vector layer
  QString def = QStringLiteral( "Point?field=col0:integer" );
  QgsVectorLayer* layer = new QgsVectorLayer( def, QStringLiteral( "test" ), QStringLiteral( "memory" ) );

  // add a feature to the vector layer
  QgsFeature ft( layer->dataProvider()->fields(), 1 );
  ft.setAttribute( QStringLiteral( "col0" ), 0 );
  ft.setValid( true );

  // set constraint
  layer->setConstraintExpression( 0, QString() );

  // build a form for this feature
  QgsAttributeForm form( layer );
  form.setFeature( ft );

  QPushButton *okButton = form.mButtonBox->button( QDialogButtonBox::Ok );

  // get wrapper
  QgsEditorWidgetWrapper *ww;
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form.mWidgets[0] );

  // testing stuff
  QSignalSpy spy1( &form, SIGNAL( attributeChanged( QString, QVariant ) ) );
  QSignalSpy spy2( layer, SIGNAL( editingStarted() ) );
  QSignalSpy spy3( layer, SIGNAL( editingStopped() ) );

  // no constraint but layer not editable : OK button disabled
  QCOMPARE( layer->isEditable(), false );
  QCOMPARE( okButton->isEnabled(), false );

  // no constraint and editable layer : OK button enabled
  layer->startEditing();
  QCOMPARE( spy2.count(), 1 );
  QCOMPARE( layer->isEditable(), true );
  QCOMPARE( okButton->isEnabled(), true );

  // invalid constraint and editable layer : OK button disabled
  layer->setConstraintExpression( 0, QStringLiteral( "col0 = 0" ) );
  QgsAttributeForm form2( layer );
  form2.setFeature( ft );
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form2.mWidgets[0] );
  okButton = form2.mButtonBox->button( QDialogButtonBox::Ok );
  ww->setValue( 1 );
  QCOMPARE( okButton->isEnabled(), false );

  // valid constraint and editable layer : OK button enabled
  layer->setConstraintExpression( 0, QStringLiteral( "col0 = 2" ) );
  QgsAttributeForm form3( layer );
  form3.setFeature( ft );
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form3.mWidgets[0] );
  okButton = form3.mButtonBox->button( QDialogButtonBox::Ok );

  ww->setValue( 2 );
  QCOMPARE( okButton->isEnabled(), true );

  // valid constraint and not editable layer : OK button disabled
  layer->rollBack();
  QCOMPARE( spy3.count(), 1 );
  QCOMPARE( layer->isEditable(), false );
  QCOMPARE( okButton->isEnabled(), false );

  // set soft constraint
  layer->setFieldConstraint( 0, QgsFieldConstraints::ConstraintExpression, QgsFieldConstraints::ConstraintStrengthSoft );
  QgsAttributeForm form4( layer );
  form4.setFeature( ft );
  ww = qobject_cast<QgsEditorWidgetWrapper*>( form4.mWidgets[0] );
  okButton = form4.mButtonBox->button( QDialogButtonBox::Ok );
  ww->setValue( 1 );
  QVERIFY( !okButton->isEnabled() );
  layer->startEditing();
  // just a soft constraint, so OK should be enabled
  QVERIFY( okButton->isEnabled() );
  layer->rollBack();
  QVERIFY( !okButton->isEnabled() );
}