[QGIS Commit] r10863 - in trunk/qgis: python/core src/app src/core src/providers/memory src/providers/ogr src/providers/postgres src/providers/spatialite src/ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat May 30 13:48:49 EDT 2009


Author: jef
Date: 2009-05-30 13:48:49 -0400 (Sat, 30 May 2009)
New Revision: 10863

Modified:
   trunk/qgis/python/core/qgsvectordataprovider.sip
   trunk/qgis/python/core/qgsvectorlayer.sip
   trunk/qgis/src/app/qgsaddattrdialog.cpp
   trunk/qgis/src/app/qgsaddattrdialog.h
   trunk/qgis/src/app/qgsvectorlayerproperties.cpp
   trunk/qgis/src/app/qgsvectorlayerproperties.h
   trunk/qgis/src/core/qgsvectordataprovider.cpp
   trunk/qgis/src/core/qgsvectordataprovider.h
   trunk/qgis/src/core/qgsvectorlayer.cpp
   trunk/qgis/src/core/qgsvectorlayer.h
   trunk/qgis/src/providers/memory/qgsmemoryprovider.cpp
   trunk/qgis/src/providers/memory/qgsmemoryprovider.h
   trunk/qgis/src/providers/ogr/qgsogrprovider.cpp
   trunk/qgis/src/providers/ogr/qgsogrprovider.h
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.h
   trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp
   trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h
   trunk/qgis/src/ui/qgsaddattrdialogbase.ui
Log:
- allow setting of field width and precision when adding attributes
- update vector data providers accordingly
- postgres provider:
  - add support for more native types and setting of column comments
  - catch errors on retrieval of defaults values (fixes #1713)



Modified: trunk/qgis/python/core/qgsvectordataprovider.sip
===================================================================
--- trunk/qgis/python/core/qgsvectordataprovider.sip	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/python/core/qgsvectordataprovider.sip	2009-05-30 17:48:49 UTC (rev 10863)
@@ -164,7 +164,7 @@
        * @param attributes map with attribute name as key and type as value
        * @return true in case of success and false in case of failure
        */
-      virtual bool addAttributes(const QMap<QString, QString> & attributes);
+      virtual bool addAttributes(const QList<QgsField> & attributes);
 
       /**
        * Deletes existing attributes
@@ -231,10 +231,13 @@
        */
       QList<int> attributeIndexes();
 
-      /**Returns the names of the numerical types*/
-      const QMap<QString,QVariant::Type> &supportedNativeTypes() const;
-      
       /**
+       * check if provider supports type of field
+       * @note added in 1.2
+       */
+      bool supportedType( const QgsField &field ) const;
+
+      /**
        * Set whether provider should return also features that don't have
        * associated geometry. FALSE by default
        */

Modified: trunk/qgis/python/core/qgsvectorlayer.sip
===================================================================
--- trunk/qgis/python/core/qgsvectorlayer.sip	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/python/core/qgsvectorlayer.sip	2009-05-30 17:48:49 UTC (rev 10863)
@@ -325,7 +325,7 @@
 
   /** add an attribute field (but does not commit it) 
       returns the field index or -1 in case of failure */
-  bool addAttribute(QString name, QString type);
+  bool addAttribute( const QgsField &field );
 
   /** delete an attribute field (but does not commit it) */
   bool deleteAttribute(int attr);

Modified: trunk/qgis/src/app/qgsaddattrdialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsaddattrdialog.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/app/qgsaddattrdialog.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -17,6 +17,7 @@
 
 #include "qgsaddattrdialog.h"
 #include "qgsvectordataprovider.h"
+#include "qgslogger.h"
 
 QgsAddAttrDialog::QgsAddAttrDialog( QgsVectorDataProvider* provider, QWidget *parent, Qt::WFlags fl )
     : QDialog( parent, fl ), mDataProvider( provider )
@@ -24,31 +25,66 @@
   setupUi( this );
 
   //fill data types into the combo box
-  const QgsNativeTypeMap &typelist = mDataProvider->supportedNativeTypes();
+  const QList< QgsVectorDataProvider::NativeType > &typelist = mDataProvider->nativeTypes();
 
-  for ( QgsNativeTypeMap::const_iterator it = typelist.constBegin(); it != typelist.constEnd(); ++it )
+  for ( int i = 0; i < typelist.size(); i++ )
   {
-    mTypeBox->addItem( it.key() );
+    QgsDebugMsg( QString( "name:%1 type:%2 typeName:%3 length:%4-%5 prec:%6-%7" )
+                 .arg( typelist[i].mTypeDesc )
+                 .arg( typelist[i].mType )
+                 .arg( typelist[i].mTypeName )
+                 .arg( typelist[i].mMinLen ).arg( typelist[i].mMaxLen )
+                 .arg( typelist[i].mMinPrec ).arg( typelist[i].mMaxPrec ) );
+
+    mTypeBox->addItem( typelist[i].mTypeDesc );
+    mTypeBox->setItemData( i, static_cast<int>( typelist[i].mType ), Qt::UserRole );
+    mTypeBox->setItemData( i, typelist[i].mTypeName, Qt::UserRole + 1 );
+    mTypeBox->setItemData( i, typelist[i].mMinLen, Qt::UserRole + 2 );
+    mTypeBox->setItemData( i, typelist[i].mMaxLen, Qt::UserRole + 3 );
+    mTypeBox->setItemData( i, typelist[i].mMinPrec, Qt::UserRole + 4 );
+    mTypeBox->setItemData( i, typelist[i].mMaxPrec, Qt::UserRole + 5 );
   }
+
+  on_mTypeBox_currentIndexChanged( 0 );
 }
 
-QgsAddAttrDialog::QgsAddAttrDialog( const std::list<QString>& typelist, QWidget *parent, Qt::WFlags fl )
-    : QDialog( parent, fl ), mDataProvider( 0 )
+void QgsAddAttrDialog::on_mTypeBox_currentIndexChanged( int idx )
 {
-  setupUi( this );
+  mTypeName->setText( mTypeBox->itemData( idx, Qt::UserRole + 1 ).toString() );
 
-  for ( std::list<QString>::const_iterator iter = typelist.begin();iter != typelist.end();++iter )
-  {
-    mTypeBox->addItem( *iter );
-  }
+  mLength->setMinimum( mTypeBox->itemData( idx, Qt::UserRole + 2 ).toInt() );
+  mLength->setMaximum( mTypeBox->itemData( idx, Qt::UserRole + 3 ).toInt() );
+  mLength->setVisible( mLength->minimum() < mLength->maximum() );
+  if ( mLength->value() < mLength->minimum() )
+    mLength->setValue( mLength->minimum() );
+  if ( mLength->value() > mLength->maximum() )
+    mLength->setValue( mLength->maximum() );
+
+  mPrec->setMinimum( mTypeBox->itemData( idx, Qt::UserRole + 4 ).toInt() );
+  mPrec->setMaximum( mTypeBox->itemData( idx, Qt::UserRole + 5 ).toInt() );
+  mPrec->setVisible( mPrec->minimum() < mPrec->maximum() );
+  if ( mPrec->value() < mPrec->minimum() )
+    mPrec->setValue( mPrec->minimum() );
+  if ( mPrec->value() > mPrec->maximum() )
+    mPrec->setValue( mPrec->maximum() );
 }
 
-QString QgsAddAttrDialog::name() const
+QgsField QgsAddAttrDialog::field() const
 {
-  return mNameEdit->text();
-}
+  QgsDebugMsg( QString( "idx:%1 name:%2 type:%3 typeName:%4 length:%5 prec:%6 comment:%7" )
+               .arg( mTypeBox->currentIndex() )
+               .arg( mNameEdit->text() )
+               .arg( mTypeBox->itemData( mTypeBox->currentIndex(), Qt::UserRole ).toInt() )
+               .arg( mTypeBox->itemData( mTypeBox->currentIndex(), Qt::UserRole + 1 ).toString() )
+               .arg( mLength->value() )
+               .arg( mPrec->value() )
+               .arg( mCommentEdit->text() ) );
 
-QString QgsAddAttrDialog::type() const
-{
-  return mTypeBox->currentText();
+  return QgsField(
+           mNameEdit->text(),
+           ( QVariant::Type ) mTypeBox->itemData( mTypeBox->currentIndex(), Qt::UserRole ).toInt(),
+           mTypeBox->itemData( mTypeBox->currentIndex(), Qt::UserRole + 1 ).toString(),
+           mLength->value(),
+           mPrec->value(),
+           mCommentEdit->text() );
 }

Modified: trunk/qgis/src/app/qgsaddattrdialog.h
===================================================================
--- trunk/qgis/src/app/qgsaddattrdialog.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/app/qgsaddattrdialog.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -20,6 +20,7 @@
 
 #include "ui_qgsaddattrdialogbase.h"
 #include "qgisgui.h"
+#include "qgsfield.h"
 
 class QgsVectorDataProvider;
 
@@ -31,8 +32,12 @@
                       QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
     QgsAddAttrDialog( const std::list<QString>& typelist,
                       QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
-    QString name() const;
-    QString type() const;
+
+    QgsField field() const;
+
+  public slots:
+    void on_mTypeBox_currentIndexChanged( int idx );
+
   protected:
     QgsVectorDataProvider* mDataProvider;
 };

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -261,17 +261,17 @@
   QgsAddAttrDialog dialog( layer->dataProvider(), this );
   if ( dialog.exec() == QDialog::Accepted )
   {
-    if ( !addAttribute( dialog.name(), dialog.type() ) )
+    if ( !addAttribute( dialog.field() ) )
     {
       QMessageBox::information( this, tr( "Name conflict" ), tr( "The attribute could not be inserted. The name already exists in the table." ) );
     }
   }
 }
 
-bool QgsVectorLayerProperties::addAttribute( QString name, QString type )
+bool QgsVectorLayerProperties::addAttribute( const QgsField &field )
 {
-  QgsDebugMsg( "inserting attribute " + name + " of type " + type );
-  return layer->addAttribute( name, type );
+  QgsDebugMsg( "inserting attribute " + field.name() + " of type " + field.typeName() );
+  return layer->addAttribute( field );
 }
 
 void QgsVectorLayerProperties::deleteAttribute()

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.h
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -50,10 +50,9 @@
     void setDisplayField( QString name );
 
     /**Adds an attribute to the table (but does not commit it yet)
-    @param name attribute name
-    @param type attribute type
-    @return false in case of a name conflict, true in case of success*/
-    bool addAttribute( QString name, QString type );
+    @param field the field to add
+    @return false in case of a name conflict, true in case of success */
+    bool addAttribute( const QgsField &field );
 
     /**Deletes an attribute (but does not commit it)
       @param name attribute name

Modified: trunk/qgis/src/core/qgsvectordataprovider.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectordataprovider.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/core/qgsvectordataprovider.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -78,7 +78,7 @@
   return false;
 }
 
-bool QgsVectorDataProvider::addAttributes( const QgsNewAttributesMap & attributes )
+bool QgsVectorDataProvider::addAttributes( const QList<QgsField> & attributes )
 {
   return false;
 }
@@ -262,12 +262,28 @@
   mFetchFeaturesWithoutGeom = fetch;
 }
 
-const QgsNativeTypeMap &QgsVectorDataProvider::supportedNativeTypes() const
+const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
 {
-  return mSupportedNativeTypes;
+  return mNativeTypes;
 }
 
 
+bool QgsVectorDataProvider::supportedType( const QgsField &field ) const
+{
+  int i;
+  for ( i = 0; i < mNativeTypes.size(); i++ )
+  {
+    if ( field.type() == mNativeTypes[i].mType &&
+         field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
+         field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
+    {
+      break;
+    }
+  }
+
+  return i < mNativeTypes.size();
+}
+
 QVariant QgsVectorDataProvider::minimumValue( int index )
 {
   if ( !fields().contains( index ) )

Modified: trunk/qgis/src/core/qgsvectordataprovider.h
===================================================================
--- trunk/qgis/src/core/qgsvectordataprovider.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/core/qgsvectordataprovider.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -29,9 +29,6 @@
 #include "qgsvectorlayer.h"
 #include "qgsfield.h"
 
-typedef QMap<QString, QString> QgsNewAttributesMap;
-typedef QMap<QString, QVariant::Type> QgsNativeTypeMap;
-
 /** \ingroup core
  * This is the base class for vector data providers.
  *
@@ -208,21 +205,21 @@
      * @param attributes map with attribute name as key and type as value
      * @return true in case of success and false in case of failure
      */
-    virtual bool addAttributes( const QgsNewAttributesMap & attributes );
+    virtual bool addAttributes( const QList<QgsField> &attributes );
 
     /**
      * Deletes existing attributes
      * @param attributes a set containing names of attributes
      * @return true in case of success and false in case of failure
      */
-    virtual bool deleteAttributes( const QgsAttributeIds& attributes );
+    virtual bool deleteAttributes( const QgsAttributeIds &attributes );
 
     /**
      * Changes attribute values of existing features.
      * @param attr_map a map containing changed attributes
      * @return true in case of success and false in case of failure
      */
-    virtual bool changeAttributeValues( const QgsChangedAttributesMap & attr_map );
+    virtual bool changeAttributeValues( const QgsChangedAttributesMap &attr_map );
 
     /**
      * Returns the default value for field specified by @c fieldId
@@ -279,15 +276,37 @@
      */
     virtual QgsAttributeList attributeIndexes();
 
-    /**Returns the names of the numerical types*/
-    const QgsNativeTypeMap &supportedNativeTypes() const;
-
     /**
      * Set whether provider should also return features that don't have
      * associated geometry. FALSE by default
      */
     void enableGeometrylessFeatures( bool fetch );
 
+    /**
+     * check if provider supports type of field
+     * @note added in 1.2
+     */
+    bool supportedType( const QgsField &field ) const;
+
+    struct NativeType
+    {
+      NativeType( QString typeDesc, QString typeName, QVariant::Type type, int minLen = 0, int maxLen = 0, int minPrec = 0, int maxPrec = 0 ) :
+          mTypeDesc( typeDesc ), mTypeName( typeName ), mType( type ), mMinLen( minLen ), mMaxLen( maxLen ), mMinPrec( minPrec ), mMaxPrec( maxPrec ) {};
+
+      QString mTypeDesc;
+      QString mTypeName;
+      QVariant::Type mType;
+      int mMinLen, mMaxLen;
+      int mMinPrec, mMaxPrec;
+    };
+
+
+    /**
+     * Returns the names of the numerical types
+     * @note added in 1.2
+     */
+    const QList< NativeType > &nativeTypes() const;
+
   protected:
     QVariant convertValue( QVariant::Type type, QString value );
 
@@ -309,7 +328,7 @@
     QgsAttributeList mAttributesToFetch;
 
     /**The names of the providers native types*/
-    QgsNativeTypeMap mSupportedNativeTypes;
+    QList< NativeType > mNativeTypes;
 };
 
 #endif

Modified: trunk/qgis/src/core/qgsvectorlayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/core/qgsvectorlayer.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -172,9 +172,9 @@
   //delete remaining overlays
 
   QList<QgsVectorOverlay*>::iterator overlayIt = mOverlays.begin();
-  for(; overlayIt != mOverlays.end(); ++overlayIt)
+  for ( ; overlayIt != mOverlays.end(); ++overlayIt )
   {
-    delete (*overlayIt);
+    delete *overlayIt;
   }
 }
 
@@ -1469,7 +1469,7 @@
   // and add to the known added features.
   f.setFeatureId( addedIdLowWaterMark );
   mAddedFeatures.append( f );
-  mCachedGeometries[f.id()] = *(f.geometry());
+  mCachedGeometries[f.id()] = *f.geometry();
 
   setModified( true );
 
@@ -1666,7 +1666,7 @@
     if ( addedIt->id() == selectedFeatureId )
     {
       return addedIt->geometry()->addIsland( ring );
-      mCachedGeometries[selectedFeatureId] = *(addedIt->geometry());
+      mCachedGeometries[selectedFeatureId] = *addedIt->geometry();
     }
   }
 
@@ -1737,19 +1737,19 @@
 
   //else get the geometry from provider (may be slow)
   QgsFeature f;
-  if(mDataProvider && mDataProvider->featureAtId(featureId, f, true))
+  if ( mDataProvider && mDataProvider->featureAtId( featureId, f, true ) )
   {
-      if(f.geometry())
+    if ( f.geometry() )
+    {
+      QgsGeometry translateGeom( *( f.geometry() ) );
+      int errorCode = translateGeom.translate( dx, dy );
+      if ( errorCode == 0 )
       {
-          QgsGeometry translateGeom(*(f.geometry()));
-          int errorCode = translateGeom.translate(dx, dy);
-          if(errorCode == 0)
-          {
-            mChangedGeometries.insert(featureId, translateGeom);
-            setModified(true, true);
-          }
-          return errorCode;
+        mChangedGeometries.insert( featureId, translateGeom );
+        setModified( true, true );
       }
+      return errorCode;
+    }
   }
   return 1; //geometry not found
 }
@@ -2571,7 +2571,7 @@
 }
 
 
-bool QgsVectorLayer::changeGeometry(int fid, QgsGeometry* geom)
+bool QgsVectorLayer::changeGeometry( int fid, QgsGeometry* geom )
 {
   if ( !mEditable || !mDataProvider )
   {
@@ -2621,24 +2621,22 @@
   return true;
 }
 
-bool QgsVectorLayer::addAttribute( QString name, QString type )
+bool QgsVectorLayer::addAttribute( const QgsField &field )
 {
   if ( !isEditable() )
     return false;
 
   for ( QgsFieldMap::const_iterator it = mUpdatedFields.begin(); it != mUpdatedFields.end(); it++ )
   {
-    if ( it.value().name() == name )
+    if ( it.value().name() == field.name() )
       return false;
   }
 
-  const QgsNativeTypeMap &types = mDataProvider->supportedNativeTypes();
-  QVariant::Type typeType = QVariant::String;
-  if ( types.contains( type ) )
-    typeType = ( QVariant::Type ) types[type];
+  if ( !mDataProvider->supportedType( field ) )
+    return false;
 
   mMaxUpdatedIndex++;
-  mUpdatedFields.insert( mMaxUpdatedIndex, QgsField( name, typeType, type ) );
+  mUpdatedFields.insert( mMaxUpdatedIndex, field );
   mAddedAttributeIds.insert( mMaxUpdatedIndex );
 
   setModified( true, false );
@@ -2656,10 +2654,12 @@
   if ( mDeletedAttributeIds.contains( index ) )
     return false;
 
-  if ( !mDataProvider->fields().contains( index ) )
+  if ( !mAddedAttributeIds.contains( index ) &&
+       !mDataProvider->fields().contains( index ) )
     return false;
 
   mDeletedAttributeIds.insert( index );
+  mAddedAttributeIds.remove( index );
   mUpdatedFields.remove( index );
 
   setModified( true, false );
@@ -2748,9 +2748,9 @@
   //
   if ( mAddedAttributeIds.size() > 0 )
   {
-    QgsNewAttributesMap addedAttributes;
+    QList<QgsField> addedAttributes;
     for ( QgsAttributeIds::const_iterator it = mAddedAttributeIds.begin(); it != mAddedAttributeIds.end(); it++ )
-      addedAttributes[ mUpdatedFields[ *it ].name()] = mUpdatedFields[ *it ].typeName();
+      addedAttributes << mUpdatedFields[ *it ];
 
     if (( cap & QgsVectorDataProvider::AddAttributes ) && mDataProvider->addAttributes( addedAttributes ) )
     {
@@ -3244,7 +3244,7 @@
   int n = 0;
   QgsFeature f;
 
-  if (mCachedGeometriesRect.contains( searchRect ) )
+  if ( mCachedGeometriesRect.contains( searchRect ) )
   {
     QgsDebugMsg( "Using cached geometries for snapping." );
 

Modified: trunk/qgis/src/core/qgsvectorlayer.h
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/core/qgsvectorlayer.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -380,14 +380,15 @@
 
     /** change feature's geometry
       @note added in version 1.2 */
-    bool changeGeometry(int fid, QgsGeometry* geom);
+    bool changeGeometry( int fid, QgsGeometry* geom );
 
     /** changed an attribute value (but does not commit it) */
     bool changeAttributeValue( int fid, int field, QVariant value, bool emitSignal = true );
 
     /** add an attribute field (but does not commit it)
-        returns the field index or -1 in case of failure */
-    bool addAttribute( QString name, QString type );
+        returns true if the field was added
+      @note added in version 1.2 */
+    bool addAttribute( const QgsField &field );
 
     /** delete an attribute field (but does not commit it) */
     bool deleteAttribute( int attr );

Modified: trunk/qgis/src/providers/memory/qgsmemoryprovider.cpp
===================================================================
--- trunk/qgis/src/providers/memory/qgsmemoryprovider.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/memory/qgsmemoryprovider.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -271,30 +271,26 @@
   return TRUE;
 }
 
-bool QgsMemoryProvider::addAttributes( const QgsNewAttributesMap & attributes )
+bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes )
 {
-  for ( QgsNewAttributesMap::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
+  for ( QList<QgsField>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
   {
-    QString name = it.key();
-    QString typeName = it.value();
-    QVariant::Type type;
-    if ( typeName == "int" )
-      type = QVariant::Int;
-    else if ( typeName == "double" )
-      type = QVariant::Double;
-    else if ( typeName == "string" )
-      type = QVariant::String;
-    else
+    switch ( it->type() )
     {
-      QgsDebugMsg( "Field type not supported: " + typeName );
-      continue;
+      case QVariant::Int:
+      case QVariant::Double:
+      case QVariant::String:
+        break;
+      default:
+        QgsDebugMsg( "Field type not supported: " + it->typeName() );
+        continue;
     }
 
     // add new field as a last one
     int nextId = -1;
     for ( QgsFieldMap::iterator it2 = mFields.begin(); it2 != mFields.end(); ++it2 )
       if ( it2.key() > nextId ) nextId = it2.key();
-    mFields[nextId+1] = QgsField( name, type, typeName );
+    mFields[nextId+1] = *it;
   }
   return TRUE;
 }

Modified: trunk/qgis/src/providers/memory/qgsmemoryprovider.h
===================================================================
--- trunk/qgis/src/providers/memory/qgsmemoryprovider.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/memory/qgsmemoryprovider.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -115,7 +115,7 @@
      * @param attributes map with attribute name as key and type as value
      * @return true in case of success and false in case of failure
      */
-    virtual bool addAttributes( const QgsNewAttributesMap & attributes );
+    virtual bool addAttributes( const QList<QgsField> &attributes );
 
     /**
      * Deletes existing attributes

Modified: trunk/qgis/src/providers/ogr/qgsogrprovider.cpp
===================================================================
--- trunk/qgis/src/providers/ogr/qgsogrprovider.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/ogr/qgsogrprovider.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -184,9 +184,11 @@
     valid = false;
   }
 
-  mSupportedNativeTypes.insert( "Integer", QVariant::Int );
-  mSupportedNativeTypes.insert( "Real", QVariant::Double );
-  mSupportedNativeTypes.insert( "String", QVariant::String );
+  mNativeTypes
+  << QgsVectorDataProvider::NativeType( tr( "Integer" ), "integer", QVariant::Int, 1, 10 )
+  << QgsVectorDataProvider::NativeType( tr( "Real" ), "double", QVariant::Double, 1, 20, 0, 5 )
+  << QgsVectorDataProvider::NativeType( tr( "String" ), "string", QVariant::String, 1, 20, 0, 5 )
+  ;
 }
 
 QgsOgrProvider::~QgsOgrProvider()
@@ -672,34 +674,35 @@
   return returnvalue;
 }
 
-bool QgsOgrProvider::addAttributes( const QgsNewAttributesMap & attributes )
+bool QgsOgrProvider::addAttributes( const QList<QgsField> &attributes )
 {
   bool returnvalue = true;
 
-  for ( QgsNewAttributesMap::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter )
+  for ( QList<QgsField>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter )
   {
-    OGRFieldDefnH fielddefn = OGR_Fld_Create( mEncoding->fromUnicode( iter.key() ).data(), OFTInteger );
+    OGRFieldType type;
 
-    if ( *iter == "Integer" )
+    switch ( iter->type() )
     {
-      OGR_Fld_SetType( fielddefn, OFTInteger );
-      OGR_Fld_SetWidth( fielddefn, 10 );
+      case QVariant::Int:
+        type = OFTInteger;
+        break;
+      case QVariant::Double:
+        type = OFTReal;
+        break;
+      case QVariant::String:
+        type = OFTString;
+        break;
+      default:
+        QgsLogger::warning( QString( "QgsOgrProvider::addAttributes, type %1 not found" ).arg( iter->typeName() ) );
+        returnvalue = false;
+        continue;
     }
-    else if ( *iter == "Real" )
-    {
-      OGR_Fld_SetType( fielddefn, OFTReal );
-    }
-    else if ( *iter == "String" )
-    {
-      OGR_Fld_SetType( fielddefn, OFTString );
-    }
-    else
-    {
-      QgsLogger::warning( QString( "QgsOgrProvider::addAttributes, type %1 not found" ).arg( *iter ) );
-      returnvalue = false;
-      continue;
-    }
 
+    OGRFieldDefnH fielddefn = OGR_Fld_Create( mEncoding->fromUnicode( iter->name() ).data(), type );
+    OGR_Fld_SetWidth( fielddefn, iter->length() );
+    OGR_Fld_SetPrecision( fielddefn, iter->precision() );
+
     if ( OGR_L_CreateField( ogrLayer, fielddefn, TRUE ) != OGRERR_NONE )
     {
       QgsLogger::warning( "QgsOgrProvider.cpp: writing of field failed" );

Modified: trunk/qgis/src/providers/ogr/qgsogrprovider.h
===================================================================
--- trunk/qgis/src/providers/ogr/qgsogrprovider.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/ogr/qgsogrprovider.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -133,7 +133,7 @@
     virtual bool deleteFeatures( const QgsFeatureIds & id );
 
     /**Adds new attributess. Unfortunately not supported for layers with features in it*/
-    virtual bool addAttributes( const QgsNewAttributesMap & attributes );
+    virtual bool addAttributes( const QList<QgsField> &attributes );
 
     /**Changes attribute values of existing features */
     virtual bool changeAttributeValues( const QgsChangedAttributesMap & attr_map );

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -224,12 +224,24 @@
 #endif
 
   //fill type names into sets
-  mSupportedNativeTypes.insert( "double precision", QVariant::Double );
-  mSupportedNativeTypes.insert( "int4", QVariant::Int );
-  mSupportedNativeTypes.insert( "int8", QVariant::LongLong );
-  mSupportedNativeTypes.insert( "text", QVariant::String );
-  mSupportedNativeTypes.insert( "varchar(30)", QVariant::String );
+  mNativeTypes
+  // integer types
+  << QgsVectorDataProvider::NativeType( tr( "smallint (16bit)" ), "int2", QVariant::Int )
+  << QgsVectorDataProvider::NativeType( tr( "integer (32bit)" ), "int4", QVariant::Int )
+  << QgsVectorDataProvider::NativeType( tr( "integer (64bit)" ), "int8", QVariant::LongLong )
+  << QgsVectorDataProvider::NativeType( tr( "numeric" ), "numeric", QVariant::LongLong, 1, 20, 0, 20 )
+  << QgsVectorDataProvider::NativeType( tr( "decimal" ), "decimal", QVariant::LongLong, 1, 20, 0, 20 )
 
+  // floating point
+  << QgsVectorDataProvider::NativeType( tr( "real" ), "real", QVariant::Double )
+  << QgsVectorDataProvider::NativeType( tr( "double" ), "double precision", QVariant::Double )
+
+  // string types
+  << QgsVectorDataProvider::NativeType( tr( "char" ), "char", QVariant::String, 1, 255 )
+  << QgsVectorDataProvider::NativeType( tr( "varchar" ), "varchar", QVariant::String, 1, 255 )
+  << QgsVectorDataProvider::NativeType( tr( "text" ), "text", QVariant::String )
+  ;
+
   if ( primaryKey.isEmpty() )
   {
     valid = false;
@@ -875,9 +887,13 @@
 
         if ( fieldTypeName == "int8" )
           fieldType = QVariant::LongLong;
-        else if ( fieldTypeName.startsWith( "int" ) || fieldTypeName == "serial" )
+        else if ( fieldTypeName.startsWith( "int" ) ||
+                  fieldTypeName == "serial" )
           fieldType = QVariant::Int;
-        else if ( fieldTypeName == "real" || fieldTypeName == "double precision" || fieldTypeName.startsWith( "float" ) || fieldTypeName == "numeric" )
+        else if ( fieldTypeName == "real" ||
+                  fieldTypeName == "double precision" ||
+                  fieldTypeName.startsWith( "float" ) ||
+                  fieldTypeName == "numeric" )
           fieldType = QVariant::Double;
         else if ( fieldTypeName == "text" ||
                   fieldTypeName == "char" ||
@@ -1828,15 +1844,19 @@
 
   if ( fieldValue == defaultValue && !defaultValue.isNull() )
   {
-    Result result = connectionRO->PQexec( QString( "select %1" ).arg( defaultValue ) );
+    PGresult *result = connectionRW->PQexec( QString( "select %1" ).arg( defaultValue ) );
+    if ( PQresultStatus( result ) == PGRES_FATAL_ERROR )
+      throw PGException( result );
+
     if ( PQgetisnull( result, 0, 0 ) )
     {
+      PQclear( result );
       return QByteArray( 0 );  // QByteArray(0).isNull() is true
     }
     else
     {
-      QString val = QString::fromUtf8( PQgetvalue( result, 0, 0 ) );
-      return val.toUtf8();
+      PQclear( result );
+      return QString::fromUtf8( PQgetvalue( result, 0, 0 ) ).toUtf8();
     }
   }
 
@@ -2060,7 +2080,7 @@
   return returnvalue;
 }
 
-bool QgsPostgresProvider::addAttributes( const QgsNewAttributesMap & name )
+bool QgsPostgresProvider::addAttributes( const QList<QgsField> &attributes )
 {
   bool returnvalue = true;
 
@@ -2071,12 +2091,22 @@
   {
     connectionRW->PQexecNR( "BEGIN" );
 
-    for ( QgsNewAttributesMap::const_iterator iter = name.begin();iter != name.end();++iter )
+    for ( QList<QgsField>::const_iterator iter = attributes.begin();iter != attributes.end();++iter )
     {
+      QString type = iter->typeName();
+      if ( type == "char" || type == "varchar" )
+      {
+        type = QString( "%1(%2)" ).arg( type ).arg( iter->length() );
+      }
+      else if ( type == "numeric" || type == "decimal" )
+      {
+        type = QString( "%1(%2,%3)" ).arg( type ).arg( iter->length() ).arg( iter->precision() );
+      }
+
       QString sql = QString( "ALTER TABLE %1 ADD COLUMN %2 %3" )
                     .arg( mSchemaTableName )
-                    .arg( quotedIdentifier( iter.key() ) )
-                    .arg( iter.value() );
+                    .arg( quotedIdentifier( iter->name() ) )
+                    .arg( type );
       QgsDebugMsg( sql );
 
       //send sql statement and do error handling
@@ -2084,6 +2114,18 @@
       if ( result == 0 || PQresultStatus( result ) == PGRES_FATAL_ERROR )
         throw PGException( result );
       PQclear( result );
+
+      if ( !iter->comment().isEmpty() )
+      {
+        sql = QString( "COMMENT ON COLUMN %1.%2 IS %3" )
+              .arg( mSchemaTableName )
+              .arg( quotedIdentifier( iter->name() ) )
+              .arg( quotedValue( iter->comment() ) );
+        result = connectionRW->PQexec( sql );
+        if ( result == 0 || PQresultStatus( result ) == PGRES_FATAL_ERROR )
+          throw PGException( result );
+        PQclear( result );
+      }
     }
 
     connectionRW->PQexecNR( "COMMIT" );

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -215,7 +215,7 @@
     /**Adds new attributes
       @param name map with attribute name as key and type as value
       @return true in case of success and false in case of failure*/
-    bool addAttributes( const QgsNewAttributesMap & name );
+    bool addAttributes( const QList<QgsField> &attributes );
 
     /**Deletes existing attributes
       @param names of the attributes to delete

Modified: trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp
===================================================================
--- trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.cpp	2009-05-30 17:48:49 UTC (rev 10863)
@@ -42,7 +42,7 @@
 QMap < QString, QgsSpatiaLiteProvider::SqliteHandles * >QgsSpatiaLiteProvider::SqliteHandles::handles;
 
 QgsSpatiaLiteProvider::QgsSpatiaLiteProvider( QString const &uri ): QgsVectorDataProvider( uri ),
-    geomType( QGis::WKBUnknown ), mSrid( -1 ), spatialIndexRTree( false ), sqliteHandle( NULL ), spatialIndexMbrCache( false ), sqliteStatement( NULL )
+    geomType( QGis::WKBUnknown ), sqliteHandle( NULL ), sqliteStatement( NULL ), mSrid( -1 ), spatialIndexRTree( false ), spatialIndexMbrCache( false )
 {
   QgsDataSourceURI mUri = QgsDataSourceURI( uri );
 
@@ -107,10 +107,12 @@
     return;
   }
   //fill type names into sets
-  mSupportedNativeTypes.insert( "SQLITE_BLOB", QVariant::ByteArray );
-  mSupportedNativeTypes.insert( "SQLITE_TEXT", QVariant::String );
-  mSupportedNativeTypes.insert( "SQLITE_FLOAT", QVariant::Double );
-  mSupportedNativeTypes.insert( "SQLITE_INTEGER", QVariant::LongLong );
+  mNativeTypes
+  << QgsVectorDataProvider::NativeType( tr( "BLOB" ), "SQLITE_BLOB", QVariant::ByteArray )
+  << QgsVectorDataProvider::NativeType( tr( "Text" ), "SQLITE_TEXT", QVariant::String )
+  << QgsVectorDataProvider::NativeType( tr( "Double" ), "SQLITE_FLOAT", QVariant::Double, 0, 20, 0, 20 )
+  << QgsVectorDataProvider::NativeType( tr( "Integer" ), "SQLITE_INTEGER", QVariant::LongLong, 0, 20 )
+  ;
 }
 
 QgsSpatiaLiteProvider::~QgsSpatiaLiteProvider()
@@ -175,7 +177,7 @@
           fieldType = QVariant::Double;
         }
 
-        attributeFields.insert( i - 1, QgsField( name, fieldType, type, 0, 0, tr( "" ) ) );
+        attributeFields.insert( i - 1, QgsField( name, fieldType, type, 0, 0, "" ) );
       }
     }
   }
@@ -1096,7 +1098,7 @@
   return false;
 }
 
-bool QgsSpatiaLiteProvider::addAttributes( const QgsNewAttributesMap & name )
+bool QgsSpatiaLiteProvider::addAttributes( const QList<QgsField> &attributes )
 {
   char *errMsg = NULL;
   bool toCommit = false;
@@ -1112,9 +1114,12 @@
   }
   toCommit = true;
 
-  for ( QgsNewAttributesMap::const_iterator iter = name.begin(); iter != name.end(); ++iter )
+  for ( QList<QgsField>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter )
   {
-    sql = QString( "ALTER TABLE %1 ADD COLUMN %2 %3" ).arg( quotedValue( mTableName ) ).arg( quotedValue( iter.key() ) ).arg( iter.value() );
+    sql = QString( "ALTER TABLE %1 ADD COLUMN %2 %3" )
+          .arg( quotedValue( mTableName ) )
+          .arg( quotedValue( iter->name() ) )
+          .arg( iter->typeName() );
     strcpy( xSql, sql.toUtf8().constData() );
     ret = sqlite3_exec( sqliteHandle, xSql, NULL, NULL, &errMsg );
     if ( ret != SQLITE_OK )

Modified: trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h
===================================================================
--- trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/providers/spatialite/qgsspatialiteprovider.h	2009-05-30 17:48:49 UTC (rev 10863)
@@ -168,7 +168,7 @@
     /**Adds new attributes
       @param name map with attribute name as key and type as value
       @return true in case of success and false in case of failure*/
-    bool addAttributes( const QgsNewAttributesMap & name );
+    bool addAttributes( const QList<QgsField> &attributes );
 
     /**Changes attribute values of existing features
       @param attr_map a map containing the new attributes. The integer is the feature id,

Modified: trunk/qgis/src/ui/qgsaddattrdialogbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsaddattrdialogbase.ui	2009-05-30 17:39:42 UTC (rev 10862)
+++ trunk/qgis/src/ui/qgsaddattrdialogbase.ui	2009-05-30 17:48:49 UTC (rev 10863)
@@ -1,57 +1,107 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>QgsAddAttrDialogBase</class>
- <widget class="QDialog" name="QgsAddAttrDialogBase" >
-  <property name="geometry" >
+ <widget class="QDialog" name="QgsAddAttrDialogBase">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>312</width>
-    <height>132</height>
+    <width>356</width>
+    <height>207</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>Add Attribute</string>
   </property>
-  <property name="modal" >
+  <property name="modal">
    <bool>true</bool>
   </property>
-  <layout class="QGridLayout" >
-   <item row="0" column="0" >
-    <widget class="QLabel" name="textLabel1" >
-     <property name="text" >
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QLabel" name="textLabel1">
+     <property name="text">
       <string>Name:</string>
      </property>
-     <property name="buddy" >
+     <property name="buddy">
       <cstring>mNameEdit</cstring>
      </property>
     </widget>
    </item>
-   <item row="0" column="1" >
-    <widget class="QLineEdit" name="mNameEdit" />
+   <item row="0" column="1">
+    <widget class="QLineEdit" name="mNameEdit"/>
    </item>
-   <item row="1" column="0" >
-    <widget class="QLabel" name="textLabel2" >
-     <property name="text" >
+   <item row="1" column="0">
+    <widget class="QLabel" name="textLabel1_2">
+     <property name="text">
+      <string>Comment:</string>
+     </property>
+     <property name="buddy">
+      <cstring>mCommentEdit</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1">
+    <widget class="QLineEdit" name="mCommentEdit"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="textLabel2">
+     <property name="text">
       <string>Type:</string>
      </property>
-     <property name="buddy" >
+     <property name="buddy">
       <cstring>mTypeBox</cstring>
      </property>
     </widget>
    </item>
-   <item row="1" column="1" >
-    <widget class="QComboBox" name="mTypeBox" />
+   <item row="2" column="1">
+    <widget class="QComboBox" name="mTypeBox"/>
    </item>
-   <item row="2" column="0" colspan="2" >
-    <widget class="QDialogButtonBox" name="buttonBox" >
-     <property name="standardButtons" >
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+   <item row="3" column="1">
+    <widget class="QLabel" name="mTypeName">
+     <property name="text">
+      <string>Type:</string>
      </property>
+     <property name="buddy">
+      <cstring>mTypeBox</cstring>
+     </property>
     </widget>
    </item>
+   <item row="4" column="0">
+    <widget class="QLabel" name="textLabel2_2">
+     <property name="text">
+      <string>Width</string>
+     </property>
+     <property name="buddy">
+      <cstring>mLength</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="4" column="1">
+    <widget class="QSpinBox" name="mLength"/>
+   </item>
+   <item row="5" column="0">
+    <widget class="QLabel" name="textLabel2_3">
+     <property name="text">
+      <string>Precision</string>
+     </property>
+     <property name="buddy">
+      <cstring>mPrec</cstring>
+     </property>
+    </widget>
+   </item>
+   <item row="5" column="1">
+    <widget class="QSpinBox" name="mPrec"/>
+   </item>
+   <item row="6" column="1">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
   </layout>
  </widget>
- <layoutdefault spacing="6" margin="11" />
+ <layoutdefault spacing="6" margin="11"/>
  <tabstops>
   <tabstop>mNameEdit</tabstop>
   <tabstop>mTypeBox</tabstop>
@@ -64,11 +114,11 @@
    <receiver>QgsAddAttrDialogBase</receiver>
    <slot>accept()</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>260</x>
      <y>109</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>307</x>
      <y>68</y>
     </hint>
@@ -80,11 +130,11 @@
    <receiver>QgsAddAttrDialogBase</receiver>
    <slot>reject()</slot>
    <hints>
-    <hint type="sourcelabel" >
+    <hint type="sourcelabel">
      <x>196</x>
      <y>106</y>
     </hint>
-    <hint type="destinationlabel" >
+    <hint type="destinationlabel">
      <x>6</x>
      <y>77</y>
     </hint>



More information about the QGIS-commit mailing list