QGIS API Documentation  3.25.0-Master (dec16ba68b)
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 #include "qgsfields.h"
23 
24 #include <QMessageBox>
25 
26 QgsAddAttrDialog::QgsAddAttrDialog( QgsVectorLayer *vlayer, QWidget *parent, Qt::WindowFlags fl )
27  : QDialog( parent, fl )
28  , mIsShapeFile( vlayer && vlayer->providerType() == QLatin1String( "ogr" ) && vlayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
29 {
30  setupUi( this );
31  connect( mTypeBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsAddAttrDialog::mTypeBox_currentIndexChanged );
32  connect( mLength, &QSpinBox::editingFinished, this, &QgsAddAttrDialog::mLength_editingFinished );
33 
34  if ( !vlayer )
35  return;
36 
37  //fill data types into the combo box
38  const QList< QgsVectorDataProvider::NativeType > &typelist = vlayer->dataProvider()->nativeTypes();
39  for ( int i = 0; i < typelist.size(); i++ )
40  {
41  QgsDebugMsgLevel( QStringLiteral( "name:%1 type:%2 typeName:%3 length:%4-%5 prec:%6-%7" )
42  .arg( typelist[i].mTypeDesc )
43  .arg( typelist[i].mType )
44  .arg( typelist[i].mTypeName )
45  .arg( typelist[i].mMinLen ).arg( typelist[i].mMaxLen )
46  .arg( typelist[i].mMinPrec ).arg( typelist[i].mMaxPrec ), 2 );
47 
48  whileBlocking( mTypeBox )->addItem( QgsFields::iconForFieldType( typelist[i].mType, typelist[i].mSubType ),
49  typelist[i].mTypeDesc );
50  mTypeBox->setItemData( i, static_cast<int>( typelist[i].mType ), Qt::UserRole );
51  mTypeBox->setItemData( i, typelist[i].mTypeName, Qt::UserRole + 1 );
52  mTypeBox->setItemData( i, typelist[i].mMinLen, Qt::UserRole + 2 );
53  mTypeBox->setItemData( i, typelist[i].mMaxLen, Qt::UserRole + 3 );
54  mTypeBox->setItemData( i, typelist[i].mMinPrec, Qt::UserRole + 4 );
55  mTypeBox->setItemData( i, typelist[i].mMaxPrec, Qt::UserRole + 5 );
56  }
57 
58  //default values for field width and precision
59  mLength->setValue( 10 );
60  mLength->setClearValue( 10 );
61  mPrec->setValue( 3 );
62  mPrec->setClearValue( 3 );
63  mTypeBox_currentIndexChanged( 0 );
64 
65  if ( mIsShapeFile )
66  mNameEdit->setMaxLength( 10 );
67 
68  mNameEdit->setFocus();
69 }
70 
71 void QgsAddAttrDialog::mTypeBox_currentIndexChanged( int idx )
72 {
73  mTypeName->setText( mTypeBox->itemData( idx, Qt::UserRole + 1 ).toString() );
74 
75  mLength->setMinimum( mTypeBox->itemData( idx, Qt::UserRole + 2 ).toInt() );
76  mLength->setMaximum( mTypeBox->itemData( idx, Qt::UserRole + 3 ).toInt() );
77  mLength->setVisible( mLength->minimum() < mLength->maximum() );
78  mLengthLabel->setVisible( mLength->minimum() < mLength->maximum() );
79  if ( mLength->value() < mLength->minimum() )
80  mLength->setValue( mLength->minimum() );
81  if ( mLength->value() > mLength->maximum() )
82  mLength->setValue( mLength->maximum() );
83  setPrecisionMinMax();
84 }
85 
86 void QgsAddAttrDialog::mLength_editingFinished()
87 {
88  setPrecisionMinMax();
89 }
90 
91 void QgsAddAttrDialog::setPrecisionMinMax()
92 {
93  const int idx = mTypeBox->currentIndex();
94  const int minPrecType = mTypeBox->itemData( idx, Qt::UserRole + 4 ).toInt();
95  const int maxPrecType = mTypeBox->itemData( idx, Qt::UserRole + 5 ).toInt();
96  const bool precisionIsEnabled = minPrecType < maxPrecType;
97  mPrec->setEnabled( precisionIsEnabled );
98  mPrec->setVisible( precisionIsEnabled );
99  mPrecLabel->setVisible( precisionIsEnabled );
100 
101  // Do not set min/max if it's disabled or we'll loose the default value,
102  // see https://github.com/qgis/QGIS/issues/26880 - QGIS saves integer field when
103  // I create a new real field through field calculator (Update field works as intended)
104  if ( precisionIsEnabled )
105  {
106  mPrec->setMinimum( minPrecType );
107  mPrec->setMaximum( std::max( minPrecType, std::min( maxPrecType, mLength->value() ) ) );
108  }
109 }
110 
111 void QgsAddAttrDialog::accept()
112 {
113  if ( mIsShapeFile && mNameEdit->text().compare( QLatin1String( "shape" ), Qt::CaseInsensitive ) == 0 )
114  {
115  QMessageBox::warning( this, tr( "Add Field" ),
116  tr( "Invalid field name. This field name is reserved and cannot be used." ) );
117  return;
118  }
119  if ( mNameEdit->text().isEmpty() )
120  {
121  QMessageBox::warning( this, tr( "Add Field" ),
122  tr( "No name specified. Please specify a name to create a new field." ) );
123  return;
124  }
125 
126  QDialog::accept();
127 }
128 
130 {
131 
132  QgsDebugMsgLevel( QStringLiteral( "idx:%1 name:%2 type:%3 typeName:%4 length:%5 prec:%6 comment:%7" )
133  .arg( mTypeBox->currentIndex() )
134  .arg( mNameEdit->text() )
135  .arg( mTypeBox->currentData( Qt::UserRole ).toInt() )
136  .arg( mTypeBox->currentData( Qt::UserRole + 1 ).toString() )
137  .arg( mLength->value() )
138  .arg( mPrec->value() )
139  .arg( mCommentEdit->text() ), 2 );
140 
141  return QgsField(
142  mNameEdit->text(),
143  ( QVariant::Type ) mTypeBox->currentData( Qt::UserRole ).toInt(),
144  mTypeBox->currentData( Qt::UserRole + 1 ).toString(),
145  mLength->value(),
146  mPrec->isEnabled() ? mPrec->value() : 0,
147  mCommentEdit->text(),
148  static_cast<QVariant::Type>( mTypeBox->currentData( Qt::UserRole ).toInt() ) == QVariant::Map ? QVariant::String : QVariant::Invalid
149  );
150 }
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
static QIcon iconForFieldType(QVariant::Type type, QVariant::Type subType=QVariant::Type::Invalid)
Returns an icon corresponding to a field type.
Definition: qgsfields.cpp:294
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:1929
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39