QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsaddattrdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsaddattrdialog.h - description
3  -------------------
4  begin : January 2005
5  copyright : (C) 2005 by Marco Hugentobler
6  email : [email protected]
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsaddattrdialog.h"
19 #include "qgsvectorlayer.h"
20 #include "qgsvectordataprovider.h"
21 #include "qgslogger.h"
22 
23 #include <QMessageBox>
24 
25 QgsAddAttrDialog::QgsAddAttrDialog( QgsVectorLayer *vlayer, QWidget *parent, Qt::WindowFlags fl )
26  : QDialog( parent, fl )
27  , mIsShapeFile( vlayer && vlayer->providerType() == QLatin1String( "ogr" ) && vlayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
28 {
29  setupUi( this );
30  connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAddAttrDialog::mTypeBox_currentIndexChanged );
31  connect( mLength, &QSpinBox::editingFinished, this, &QgsAddAttrDialog::mLength_editingFinished );
32 
33  if ( !vlayer )
34  return;
35 
36  //fill data types into the combo box
37  const QList< QgsVectorDataProvider::NativeType > &typelist = vlayer->dataProvider()->nativeTypes();
38  for ( int i = 0; i < typelist.size(); i++ )
39  {
40  QgsDebugMsg( QStringLiteral( "name:%1 type:%2 typeName:%3 length:%4-%5 prec:%6-%7" )
41  .arg( typelist[i].mTypeDesc )
42  .arg( typelist[i].mType )
43  .arg( typelist[i].mTypeName )
44  .arg( typelist[i].mMinLen ).arg( typelist[i].mMaxLen )
45  .arg( typelist[i].mMinPrec ).arg( typelist[i].mMaxPrec ) );
46 
47  whileBlocking( mTypeBox )->addItem( typelist[i].mTypeDesc );
48  mTypeBox->setItemData( i, static_cast<int>( typelist[i].mType ), Qt::UserRole );
49  mTypeBox->setItemData( i, typelist[i].mTypeName, Qt::UserRole + 1 );
50  mTypeBox->setItemData( i, typelist[i].mMinLen, Qt::UserRole + 2 );
51  mTypeBox->setItemData( i, typelist[i].mMaxLen, Qt::UserRole + 3 );
52  mTypeBox->setItemData( i, typelist[i].mMinPrec, Qt::UserRole + 4 );
53  mTypeBox->setItemData( i, typelist[i].mMaxPrec, Qt::UserRole + 5 );
54  }
55 
56  //default values for field width and precision
57  mLength->setValue( 10 );
58  mLength->setClearValue( 10 );
59  mPrec->setValue( 3 );
60  mPrec->setClearValue( 3 );
61  mTypeBox_currentIndexChanged( 0 );
62 
63  if ( mIsShapeFile )
64  mNameEdit->setMaxLength( 10 );
65 
66  mNameEdit->setFocus();
67 }
68 
69 void QgsAddAttrDialog::mTypeBox_currentIndexChanged( int idx )
70 {
71  mTypeName->setText( mTypeBox->itemData( idx, Qt::UserRole + 1 ).toString() );
72 
73  mLength->setMinimum( mTypeBox->itemData( idx, Qt::UserRole + 2 ).toInt() );
74  mLength->setMaximum( mTypeBox->itemData( idx, Qt::UserRole + 3 ).toInt() );
75  mLength->setVisible( mLength->minimum() < mLength->maximum() );
76  mLengthLabel->setVisible( mLength->minimum() < mLength->maximum() );
77  if ( mLength->value() < mLength->minimum() )
78  mLength->setValue( mLength->minimum() );
79  if ( mLength->value() > mLength->maximum() )
80  mLength->setValue( mLength->maximum() );
81  setPrecisionMinMax();
82 }
83 
84 void QgsAddAttrDialog::mLength_editingFinished()
85 {
86  setPrecisionMinMax();
87 }
88 
89 void QgsAddAttrDialog::setPrecisionMinMax()
90 {
91  const int idx = mTypeBox->currentIndex();
92  const int minPrecType = mTypeBox->itemData( idx, Qt::UserRole + 4 ).toInt();
93  const int maxPrecType = mTypeBox->itemData( idx, Qt::UserRole + 5 ).toInt();
94  const bool precisionIsEnabled = minPrecType < maxPrecType;
95  mPrec->setEnabled( precisionIsEnabled );
96  mPrec->setVisible( precisionIsEnabled );
97  mPrecLabel->setVisible( precisionIsEnabled );
98 
99  // Do not set min/max if it's disabled or we'll loose the default value,
100  // see https://github.com/qgis/QGIS/issues/26880 - QGIS saves integer field when
101  // I create a new real field through field calculator (Update field works as intended)
102  if ( precisionIsEnabled )
103  {
104  mPrec->setMinimum( minPrecType );
105  mPrec->setMaximum( std::max( minPrecType, std::min( maxPrecType, mLength->value() ) ) );
106  }
107 }
108 
109 void QgsAddAttrDialog::accept()
110 {
111  if ( mIsShapeFile && mNameEdit->text().compare( QLatin1String( "shape" ), Qt::CaseInsensitive ) == 0 )
112  {
113  QMessageBox::warning( this, tr( "Add Field" ),
114  tr( "Invalid field name. This field name is reserved and cannot be used." ) );
115  return;
116  }
117  if ( mNameEdit->text().isEmpty() )
118  {
119  QMessageBox::warning( this, tr( "Add Field" ),
120  tr( "No name specified. Please specify a name to create a new field." ) );
121  return;
122  }
123 
124  QDialog::accept();
125 }
126 
128 {
129 
130  QgsDebugMsg( QStringLiteral( "idx:%1 name:%2 type:%3 typeName:%4 length:%5 prec:%6 comment:%7" )
131  .arg( mTypeBox->currentIndex() )
132  .arg( mNameEdit->text() )
133  .arg( mTypeBox->currentData( Qt::UserRole ).toInt() )
134  .arg( mTypeBox->currentData( Qt::UserRole + 1 ).toString() )
135  .arg( mLength->value() )
136  .arg( mPrec->value() )
137  .arg( mCommentEdit->text() ) );
138 
139  return QgsField(
140  mNameEdit->text(),
141  ( QVariant::Type ) mTypeBox->currentData( Qt::UserRole ).toInt(),
142  mTypeBox->currentData( Qt::UserRole + 1 ).toString(),
143  mLength->value(),
144  mPrec->isEnabled() ? mPrec->value() : 0,
145  mCommentEdit->text(),
146  static_cast<QVariant::Type>( mTypeBox->currentData( Qt::UserRole ).toInt() ) == QVariant::Map ? QVariant::String : QVariant::Invalid
147  );
148 }
QgsField field() const
Returns a field for the configured attribute.
QgsAddAttrDialog(QgsVectorLayer *vlayer, QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
constructor
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QList< QgsVectorDataProvider::NativeType > nativeTypes() const
Returns the names of the supported types.
Represents a vector layer which manages a vector based data sets.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1185
#define QgsDebugMsg(str)
Definition: qgslogger.h:38