[QGIS Commit] r12077 - in trunk/qgis: python python/core src/analysis/vector src/app src/app/attributetable src/core src/ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Tue Nov 10 13:31:00 EST 2009


Author: jef
Date: 2009-11-10 13:30:57 -0500 (Tue, 10 Nov 2009)
New Revision: 12077

Removed:
   trunk/qgis/src/ui/qgsattributedialogbase.ui
Modified:
   trunk/qgis/python/CMakeLists.txt
   trunk/qgis/python/core/qgsvectorlayer.sip
   trunk/qgis/src/analysis/vector/qgsoverlayanalyzer.cpp
   trunk/qgis/src/app/CMakeLists.txt
   trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp
   trunk/qgis/src/app/qgsattributedialog.cpp
   trunk/qgis/src/app/qgsattributedialog.h
   trunk/qgis/src/app/qgsattributeeditor.cpp
   trunk/qgis/src/app/qgsattributeeditor.h
   trunk/qgis/src/app/qgsattributetypedialog.cpp
   trunk/qgis/src/app/qgsattributetypedialog.h
   trunk/qgis/src/app/qgsidentifyresults.cpp
   trunk/qgis/src/app/qgsidentifyresults.h
   trunk/qgis/src/app/qgsmaptooladdfeature.cpp
   trunk/qgis/src/app/qgsvectorlayerproperties.cpp
   trunk/qgis/src/app/qgsvectorlayerproperties.h
   trunk/qgis/src/core/qgsvectorlayer.cpp
   trunk/qgis/src/core/qgsvectorlayer.h
   trunk/qgis/src/ui/qgsattributetypeedit.ui
   trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui
Log:
[FEATURE] customizable attribute forms using Qt Designer dialog UIs
- add support for checkbox edit type and edit forms for vector layers
- selection of ui file in vector layer properties (general tab)
- the forms are opened when a feature is added or via identify.
  The widgets on the ui have to be named like the attribute they are supposed
  to edit or show.  If the vector layer is not in editing mode, the widgets
  will be disabled



Modified: trunk/qgis/python/CMakeLists.txt
===================================================================
--- trunk/qgis/python/CMakeLists.txt	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/python/CMakeLists.txt	2009-11-10 18:30:57 UTC (rev 12077)
@@ -1,15 +1,15 @@
 SUBDIRS(plugins)
 IF (WIN32)
-  SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.pyd)
-  SET(BINDINGS_GUI_LIB  ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.pyd)
-  SET(BINDINGS_ANALYSIS_LIB  ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.pyd)
+  SET(BINDINGS_CORE_LIB     ${CMAKE_CURRENT_BINARY_DIR}/core/core.pyd)
+  SET(BINDINGS_GUI_LIB      ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.pyd)
+  SET(BINDINGS_ANALYSIS_LIB ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.pyd)
   IF (NOT MSVC)
     SET(QGIS_CORE_LIB     ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dll)
     SET(QGIS_GUI_LIB      ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dll)
     SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.dll)
   ELSE (NOT MSVC)
-    SET(QGIS_CORE_LIB	    ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib)
-    SET(QGIS_GUI_LIB	    ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib)
+    SET(QGIS_CORE_LIB     ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib)
+    SET(QGIS_GUI_LIB      ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib)
     SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/${CMAKE_CFG_INTDIR}/qgis_analysis.lib)
   ENDIF (NOT MSVC)
 ELSE (WIN32)
@@ -60,9 +60,9 @@
 ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_MAKEFILE} ${BINDINGS_GUI_MAKEFILE} ${BINDINGS_ANALYSIS_MAKEFILE} PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE}
                    ARGS ${CMAKE_CURRENT_BINARY_DIR}/configure.py ${CMAKE_CFG_INTDIR} ${EXPORT}
-		   DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB} ${QGIS_ANALYSIS_LIB}
-		           ${CMAKE_CURRENT_BINARY_DIR}/configure.py
-			   ${CORE_SIP_FILES} ${GUI_SIP_FILES} ${ANALYSIS_SIP_FILES})
+                   DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB} ${QGIS_ANALYSIS_LIB}
+                           ${CMAKE_CURRENT_BINARY_DIR}/configure.py
+                           ${CORE_SIP_FILES} ${GUI_SIP_FILES} ${ANALYSIS_SIP_FILES})
 
 # Step 3: run make in core and gui subdirs
 ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_LIB} PRE_LINK

Modified: trunk/qgis/python/core/qgsvectorlayer.sip
===================================================================
--- trunk/qgis/python/core/qgsvectorlayer.sip	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/python/core/qgsvectorlayer.sip	2009-11-10 18:30:57 UTC (rev 12077)
@@ -13,9 +13,10 @@
     Classification,
     EditRange,
     SliderRange
+    CheckBox,    /* @note added in 1.4 */
     FileName,
-    Enumeration,
-    Immutable
+    Enumeration, /* @note added in 1.4 */
+    Immutable    /* @note added in 1.4 */
   };
    
   struct RangeData {
@@ -130,7 +131,7 @@
   /** Write the symbology for the layer into the docment provided.
    *  @param QDomNode the node that will have the style element added to it.
    *  @param QDomDocument the document that will have the QDomNode added.
-   * @param errorMessage reference to string that will be updated with any error messages
+   *  @param errorMessage reference to string that will be updated with any error messages
    *  @return true in case of success.
    */
   bool writeSymbology(QDomNode&, QDomDocument& doc, QString& errorMessage) const;
@@ -154,7 +155,7 @@
    * @param subset The subset string. This may be the where clause of a sql statement
    *               or other defintion string specific to the underlying dataprovider
    *               and data store.
-   * @return true, when setting the string was successful, false otherwise (added in 1.4)
+   * @return true, when setting the string was successful, false otherwise (@note added in 1.4)
    */
   virtual bool setSubsetString(QString subset);
 
@@ -387,6 +388,27 @@
   /**set edit type*/
   void setEditType(int idx, EditType edit);
 
+  /** set string representing 'true' for a checkbox
+   @note added in 1.4
+   */
+  void setCheckedState( int idx, QString checked, QString notChecked );
+   
+  /** return string representing 'true' for a checkbox
+    @note added in 1.4
+   */
+  // FIXME: need SIP binding for QPair<QString, QString> 
+  // QPair<QString, QString> checkedState( int idx );
+ 
+  /** get edit form
+    @note added in 1.4
+   */
+  QString editForm();
+
+  /** set edit form
+    @note added in 1.4
+   */
+  void setEditForm( QString ui );
+
   /**access value map*/
   QMap<QString, QVariant> &valueMap(int idx);
 

Modified: trunk/qgis/src/analysis/vector/qgsoverlayanalyzer.cpp
===================================================================
--- trunk/qgis/src/analysis/vector/qgsoverlayanalyzer.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/analysis/vector/qgsoverlayanalyzer.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -52,7 +52,6 @@
 
   QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, &crs );
   QgsFeature currentFeature;
-  QgsGeometry* dissolveGeometry; //dissolve geometry (if dissolve enabled)
   QgsSpatialIndex index;
 
   //take only selection

Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/CMakeLists.txt	2009-11-10 18:30:57 UTC (rev 12077)
@@ -251,6 +251,7 @@
   ${CMAKE_CURRENT_SOURCE_DIR} composer legend attributetable
   ${CMAKE_CURRENT_BINARY_DIR}
   ${CMAKE_CURRENT_BINARY_DIR}/../ui
+  ${QT_QTUITOOLS_INCLUDE_DIR}
   ../core
   ../core/composer ../core/raster ../core/renderer ../core/symbology
   ../gui
@@ -295,6 +296,7 @@
   ${QT_QTSVG_LIBRARY} 
   ${QT_QTNETWORK_LIBRARY} 
   ${QT_QTSQL_LIBRARY}
+  ${QT_QTUITOOLS_LIBRARY}
   #should only be needed for win
   ${QT_QTMAIN_LIBRARY} 
   qgis_core

Modified: trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp
===================================================================
--- trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/attributetable/qgsattributetabledelegate.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -62,7 +62,7 @@
   if ( vl == NULL )
     return NULL;
 
-  QWidget *widget = QgsAttributeEditor::createAttributeEditor( parent, vl, fieldIdx( index ), index.model()->data( index, Qt::EditRole ) );
+  QWidget *widget = QgsAttributeEditor::createAttributeEditor( parent, 0, vl, fieldIdx( index ), index.model()->data( index, Qt::EditRole ) );
 
   return widget;
 }

Modified: trunk/qgis/src/app/qgsattributedialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsattributedialog.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributedialog.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -30,82 +30,168 @@
 #include <QLabel>
 #include <QFrame>
 #include <QScrollArea>
+#include <QFile>
+#include <QDialogButtonBox>
+#include <QUiLoader>
+#include <QDialog>
+#include <QVBoxLayout>
 
 QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature *thepFeature )
-    : QDialog(),
+    : mDialog( 0 ),
     mSettingsPath( "/Windows/AttributeDialog/" ),
     mLayer( vl ),
     mpFeature( thepFeature )
 {
-  setupUi( this );
   if ( mpFeature == NULL || vl->dataProvider() == NULL )
     return;
 
   const QgsFieldMap &theFieldMap = vl->pendingFields();
-
   if ( theFieldMap.isEmpty() )
     return;
 
   QgsAttributeMap myAttributes = mpFeature->attributeMap();
-  //
-  //Set up dynamic inside a scroll box
-  //
-  QVBoxLayout * mypOuterLayout = new QVBoxLayout();
-  mypOuterLayout->setContentsMargins( 0, 0, 0, 0 );
-  //transfers layout ownership so no need to call delete
-  mFrame->setLayout( mypOuterLayout );
-  QScrollArea * mypScrollArea = new QScrollArea();
-  //transfers scroll area ownership so no need to call delete
-  mypOuterLayout->addWidget( mypScrollArea );
-  QFrame * mypInnerFrame = new QFrame();
-  mypInnerFrame->setFrameShape( QFrame::NoFrame );
-  mypInnerFrame->setFrameShadow( QFrame::Plain );
-  //transfers frame ownership so no need to call delete
-  mypScrollArea->setWidget( mypInnerFrame );
-  mypScrollArea->setWidgetResizable( true );
-  QGridLayout * mypInnerLayout = new QGridLayout( mypInnerFrame );
 
-  int index = 0;
-  for ( QgsAttributeMap::const_iterator it = myAttributes.begin();
-        it != myAttributes.end();
-        ++it )
+  QDialogButtonBox *buttonBox = NULL;
+
+  if ( !vl->editForm().isEmpty() )
   {
-    const QgsField &field = theFieldMap[it.key()];
+    QFile file( vl->editForm() );
+    file.open( QFile::ReadOnly );
+    QUiLoader loader;
+    QWidget *myWidget = loader.load( &file, NULL );
+    file.close();
 
-    //show attribute alias if available
-    QString myFieldName = vl->attributeDisplayName( it.key() );
-    int myFieldType = field.type();
+    mDialog = qobject_cast<QDialog*>( myWidget );
+    buttonBox = myWidget->findChild<QDialogButtonBox*>();
+  }
 
-    QWidget *myWidget = QgsAttributeEditor::createAttributeEditor( 0, vl, it.key(), it.value() );
-    if ( !myWidget )
-      continue;
+  if ( !mDialog )
+  {
+    mDialog = new QDialog();
 
-    QLabel * mypLabel = new QLabel();
-    mypInnerLayout->addWidget( mypLabel, index, 0 );
-    if ( myFieldType == QVariant::Int )
+    QGridLayout *gridLayout;
+    QFrame *mFrame;
+
+    if ( mDialog->objectName().isEmpty() )
+      mDialog->setObjectName( QString::fromUtf8( "QgsAttributeDialogBase" ) );
+
+    mDialog->resize( 447, 343 );
+    gridLayout = new QGridLayout( mDialog );
+    gridLayout->setSpacing( 6 );
+    gridLayout->setMargin( 11 );
+    gridLayout->setObjectName( QString::fromUtf8( "gridLayout" ) );
+    mFrame = new QFrame( mDialog );
+    mFrame->setObjectName( QString::fromUtf8( "mFrame" ) );
+    mFrame->setFrameShape( QFrame::StyledPanel );
+    mFrame->setFrameShadow( QFrame::Raised );
+
+    gridLayout->addWidget( mFrame, 0, 0, 1, 1 );
+
+    buttonBox = new QDialogButtonBox( mDialog );
+    buttonBox->setObjectName( QString::fromUtf8( "buttonBox" ) );
+    gridLayout->addWidget( buttonBox, 2, 0, 1, 1 );
+
+    //
+    //Set up dynamic inside a scroll box
+    //
+    QVBoxLayout * mypOuterLayout = new QVBoxLayout();
+    mypOuterLayout->setContentsMargins( 0, 0, 0, 0 );
+    //transfers layout ownership so no need to call delete
+
+    mFrame->setLayout( mypOuterLayout );
+    QScrollArea * mypScrollArea = new QScrollArea();
+    //transfers scroll area ownership so no need to call delete
+    mypOuterLayout->addWidget( mypScrollArea );
+    QFrame *mypInnerFrame = new QFrame();
+    mypInnerFrame->setFrameShape( QFrame::NoFrame );
+    mypInnerFrame->setFrameShadow( QFrame::Plain );
+    //transfers frame ownership so no need to call delete
+    mypScrollArea->setWidget( mypInnerFrame );
+    mypScrollArea->setWidgetResizable( true );
+    QGridLayout * mypInnerLayout = new QGridLayout( mypInnerFrame );
+
+    int index = 0;
+    for ( QgsAttributeMap::const_iterator it = myAttributes.begin(); it != myAttributes.end(); ++it )
     {
-      mypLabel->setText( myFieldName + tr( " (int)" ) );
+      const QgsField &field = theFieldMap[it.key()];
+
+      //show attribute alias if available
+      QString myFieldName = vl->attributeDisplayName( it.key() );
+      int myFieldType = field.type();
+
+      QWidget *myWidget = QgsAttributeEditor::createAttributeEditor( 0, 0, vl, it.key(), it.value() );
+      if ( !myWidget )
+        continue;
+
+      QLabel * mypLabel = new QLabel();
+      mypInnerLayout->addWidget( mypLabel, index, 0 );
+      if ( myFieldType == QVariant::Int )
+      {
+        mypLabel->setText( myFieldName + tr( " (int)" ) );
+      }
+      else if ( myFieldType == QVariant::Double )
+      {
+        mypLabel->setText( myFieldName + tr( " (dbl)" ) );
+      }
+      else //string
+      {
+        //any special behaviour for string goes here
+        mypLabel->setText( myFieldName + tr( " (txt)" ) );
+      }
+
+      myWidget->setEnabled( vl->isEditable() );
+
+      mypInnerLayout->addWidget( myWidget, index, 1 );
+      mpIndizes << it.key();
+      mpWidgets << myWidget;
+      ++index;
     }
-    else if ( myFieldType == QVariant::Double )
+    // Set focus to first widget in list, to help entering data without moving the mouse.
+    if ( mpWidgets.size() > 0 )
     {
-      mypLabel->setText( myFieldName + tr( " (dbl)" ) );
+      mpWidgets.first()->setFocus( Qt::OtherFocusReason );
     }
-    else //string
+  }
+  else
+  {
+    for ( QgsAttributeMap::const_iterator it = myAttributes.begin(); it != myAttributes.end(); ++it )
     {
-      //any special behaviour for string goes here
-      mypLabel->setText( myFieldName + tr( " (txt)" ) );
+      const QgsField &field = theFieldMap[it.key()];
+
+      QWidget *myWidget = mDialog->findChild<QWidget*>( field.name() );
+      if ( !myWidget )
+        continue;
+
+      QgsAttributeEditor::createAttributeEditor( mDialog, myWidget, vl, it.key(), it.value() );
+
+      myWidget->setEnabled( vl->isEditable() );
+
+      mpIndizes << it.key();
+      mpWidgets << myWidget;
     }
+  }
 
-    mypInnerLayout->addWidget( myWidget, index, 1 );
-    mpIndizes << it.key();
-    mpWidgets << myWidget;
-    ++index;
-  }
-  // Set focus to first widget in list, to help entering data without moving the mouse.
-  if ( mpWidgets.size() > 0 )
+  if ( buttonBox )
   {
-    mpWidgets.first()->setFocus( Qt::OtherFocusReason );
+    buttonBox->clear();
+
+    if( vl->isEditable() )
+    {
+      buttonBox->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
+      connect( buttonBox, SIGNAL( accepted() ), mDialog, SLOT( accept() ) );
+      connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
+    }
+    else
+    {
+      buttonBox->setStandardButtons( QDialogButtonBox::Cancel );
+    }
+
+    connect( buttonBox, SIGNAL( rejected() ), mDialog, SLOT( reject() ) );
+    connect( buttonBox, SIGNAL( rejected() ), this, SLOT( rejected() ) );
   }
+
+  QMetaObject::connectSlotsByName( mDialog );
+
   restoreGeometry();
 }
 
@@ -117,12 +203,13 @@
 
 void QgsAttributeDialog::accept()
 {
+  if ( !mLayer->isEditable() )
+    return;
+
   //write the new values back to the feature
   QgsAttributeMap myAttributes = mpFeature->attributeMap();
   int myIndex = 0;
-  for ( QgsAttributeMap::const_iterator it = myAttributes.begin();
-        it != myAttributes.end();
-        ++it )
+  for ( QgsAttributeMap::const_iterator it = myAttributes.begin(); it != myAttributes.end(); ++it )
   {
     QVariant value;
 
@@ -132,17 +219,21 @@
 
     ++myIndex;
   }
-  QDialog::accept();
 }
 
+int QgsAttributeDialog::exec()
+{
+  return mDialog->exec();
+}
+
 void QgsAttributeDialog::saveGeometry()
 {
   QSettings settings;
-  settings.setValue( mSettingsPath + "geometry", QDialog::saveGeometry() );
+  settings.setValue( mSettingsPath + "geometry", mDialog->saveGeometry() );
 }
 
 void QgsAttributeDialog::restoreGeometry()
 {
   QSettings settings;
-  QDialog::restoreGeometry( settings.value( mSettingsPath + "geometry" ).toByteArray() );
+  mDialog->restoreGeometry( settings.value( mSettingsPath + "geometry" ).toByteArray() );
 }

Modified: trunk/qgis/src/app/qgsattributedialog.h
===================================================================
--- trunk/qgis/src/app/qgsattributedialog.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributedialog.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -18,10 +18,7 @@
 #ifndef QGSATTRIBUTEDIALOG_H
 #define QGSATTRIBUTEDIALOG_H
 
-#include "ui_qgsattributedialogbase.h"
-
 #include "qgsfeature.h"
-#include <vector>
 
 class QDialog;
 class QgsFeature;
@@ -29,7 +26,7 @@
 class QgsField;
 class QgsVectorLayer;
 
-class QgsAttributeDialog: public QDialog, private Ui::QgsAttributeDialogBase
+class QgsAttributeDialog : public QObject
 {
     Q_OBJECT
 
@@ -37,26 +34,33 @@
     QgsAttributeDialog( QgsVectorLayer *vl, QgsFeature * thepFeature );
     ~QgsAttributeDialog();
 
-    /** Overloaded accept method which will write the feature field
-     * values, then delegate to QDialog::accept()
-     */
-    void accept();
     /** Saves the size and position for the next time
      *  this dialog box was used.
      */
+
     void saveGeometry();
+
     /** Restores the size and position from the last time
      *  this dialog box was used.
      */
     void restoreGeometry();
 
+  public slots:
+    /** Overloaded accept method which will write the feature field
+     * values, then delegate to QDialog::accept()
+     */
+    void accept();
+
+    int exec();
+
   private:
+
+    QDialog *mDialog;
     QString mSettingsPath;
     QList<QWidget *> mpWidgets;
     QList<int> mpIndizes;
     QgsVectorLayer *mLayer;
-    QgsFeature *  mpFeature;
-
+    QgsFeature *mpFeature;
 };
 
 #endif

Modified: trunk/qgis/src/app/qgsattributeeditor.cpp
===================================================================
--- trunk/qgis/src/app/qgsattributeeditor.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributeeditor.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -24,8 +24,11 @@
 
 #include <QPushButton>
 #include <QLineEdit>
+#include <QTextEdit>
+#include <QPlainTextEdit>
 #include <QFileDialog>
 #include <QComboBox>
+#include <QCheckBox>
 #include <QSpinBox>
 #include <QCompleter>
 #include <QHBoxLayout>
@@ -51,12 +54,23 @@
   le->setText( fileName );
 }
 
-QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QgsVectorLayer *vl, int idx, const QVariant &value )
+QComboBox *QgsAttributeEditor::comboBox( QWidget *editor, QWidget *parent )
 {
+  QComboBox *cb = NULL;
+  if ( editor )
+    cb = qobject_cast<QComboBox *>( editor );
+  else
+    cb = new QComboBox( parent );
+
+  return cb;
+}
+
+QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
+{
   if ( !vl )
     return NULL;
 
-  QWidget *myWidget;
+  QWidget *myWidget = NULL;
   QgsVectorLayer::EditType editType = vl->editType( idx );
   const QgsField &field = vl->pendingFields()[idx];
   QVariant::Type myFieldType = field.type();
@@ -68,13 +82,16 @@
       QList<QVariant> values;
       vl->dataProvider()->uniqueValues( idx, values );
 
-      QComboBox *cb = new QComboBox( parent );
-      cb->setEditable( true );
+      QComboBox *cb = comboBox( editor, parent );
+      if ( cb )
+      {
+        cb->setEditable( true );
 
-      for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
-        cb->addItem( it->toString() );
+        for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
+          cb->addItem( it->toString() );
 
-      myWidget = cb;
+        myWidget = cb;
+      }
     }
     break;
 
@@ -83,14 +100,17 @@
       QStringList enumValues;
       vl->dataProvider()->enumValues( idx, enumValues );
 
-      QComboBox *cb = new QComboBox( parent );
-      QStringList::const_iterator s_it = enumValues.constBegin();
-      for ( ; s_it != enumValues.constEnd(); ++s_it )
+      QComboBox *cb = comboBox( editor, parent );
+      if ( cb )
       {
-        cb->addItem( *s_it );
+        QStringList::const_iterator s_it = enumValues.constBegin();
+        for ( ; s_it != enumValues.constEnd(); ++s_it )
+        {
+          cb->addItem( *s_it );
+        }
+
+        myWidget = cb;
       }
-
-      myWidget = cb;
     }
     break;
 
@@ -98,14 +118,16 @@
     {
       const QMap<QString, QVariant> &map = vl->valueMap( idx );
 
-      QComboBox *cb = new QComboBox( parent );
+      QComboBox *cb = comboBox( editor, parent );
+      if ( cb )
+      {
+        for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
+        {
+          cb->addItem( it.key(), it.value() );
+        }
 
-      for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
-      {
-        cb->addItem( it.key(), it.value() );
+        myWidget = cb;
       }
-
-      myWidget = cb;
     }
     break;
 
@@ -133,13 +155,16 @@
         }
       }
 
-      QComboBox *cb = new QComboBox( parent );
-      for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
+      QComboBox *cb = comboBox( editor, parent );
+      if ( cb )
       {
-        cb->addItem( it.value(), it.key() );
+        for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
+        {
+          cb->addItem( it.value(), it.key() );
+        }
+
+        myWidget = cb;
       }
-
-      myWidget = cb;
     }
     break;
 
@@ -154,77 +179,138 @@
 
         if ( editType == QgsVectorLayer::EditRange )
         {
-          QSpinBox *sb = new QSpinBox( parent );
+          QSpinBox *sb = NULL;
 
-          sb->setRange( min, max );
-          sb->setSingleStep( step );
+          if ( editor )
+            sb = qobject_cast<QSpinBox *>( editor );
+          else
+            sb = new QSpinBox( parent );
 
-          myWidget = sb;
+          if ( sb )
+          {
+            sb->setRange( min, max );
+            sb->setSingleStep( step );
+
+            myWidget = sb;
+          }
         }
         else
         {
-          QSlider *sl = new QSlider( Qt::Horizontal, parent );
+          QSlider *sl = NULL;
 
-          sl->setRange( min, max );
-          sl->setSingleStep( step );
+          if ( editor )
+            sl = qobject_cast<QSlider*>( editor );
+          else
+            sl = new QSlider( Qt::Horizontal, parent );
 
-          myWidget = sl;
+          if ( sl )
+          {
+            sl->setRange( min, max );
+            sl->setSingleStep( step );
+
+            myWidget = sl;
+          }
         }
         break;
       }
       else if ( myFieldType == QVariant::Double )
       {
-        double min = vl->range( idx ).mMin.toDouble();
-        double max = vl->range( idx ).mMax.toDouble();
-        double step = vl->range( idx ).mStep.toDouble();
-        QDoubleSpinBox *dsb = new QDoubleSpinBox( parent );
+        QDoubleSpinBox *dsb = NULL;
+        if ( editor )
+          dsb = qobject_cast<QDoubleSpinBox*>( editor );
+        else
+          dsb = new QDoubleSpinBox( parent );
 
-        dsb->setRange( min, max );
-        dsb->setSingleStep( step );
+        if ( dsb )
+        {
+          double min = vl->range( idx ).mMin.toDouble();
+          double max = vl->range( idx ).mMax.toDouble();
+          double step = vl->range( idx ).mStep.toDouble();
 
-        myWidget = dsb;
+          dsb->setRange( min, max );
+          dsb->setSingleStep( step );
+
+          myWidget = dsb;
+        }
         break;
       }
     }
 
+    case QgsVectorLayer::CheckBox:
+    {
+      QCheckBox *cb = NULL;
+      if ( editor )
+        cb = qobject_cast<QCheckBox*>( editor );
+      else
+        cb = new QCheckBox();
+
+      if ( cb )
+      {
+        myWidget = cb;
+        break;
+      }
+    }
+
     // fall-through
 
     case QgsVectorLayer::LineEdit:
     case QgsVectorLayer::UniqueValuesEditable:
-    case QgsVectorLayer::Immutable:
     default:
     {
-      QLineEdit *le = new QLineEdit( parent );
+      QLineEdit *le = NULL;
+      QTextEdit *te = NULL;
+      QPlainTextEdit *pte = NULL;
 
-      if ( editType == QgsVectorLayer::Immutable )
+      if ( editor )
       {
-        le->setEnabled( false );
+        le = qobject_cast<QLineEdit *>( editor );
+        te = qobject_cast<QTextEdit *>( editor );
+        pte = qobject_cast<QPlainTextEdit *>( editor );
+      }     
+      else
+      {
+        le = new QLineEdit( parent );
       }
 
-      if ( editType == QgsVectorLayer::UniqueValuesEditable )
+      if ( le )
       {
-        QList<QVariant> values;
-        vl->dataProvider()->uniqueValues( idx, values );
 
-        QStringList svalues;
-        for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
-          svalues << it->toString();
+        if ( editType == QgsVectorLayer::UniqueValuesEditable )
+        {
+          QList<QVariant> values;
+          vl->dataProvider()->uniqueValues( idx, values );
 
-        QCompleter *c = new QCompleter( svalues );
-        c->setCompletionMode( QCompleter::PopupCompletion );
-        le->setCompleter( c );
+          QStringList svalues;
+          for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
+            svalues << it->toString();
+
+          QCompleter *c = new QCompleter( svalues );
+          c->setCompletionMode( QCompleter::PopupCompletion );
+          le->setCompleter( c );
+        }
+
+        if ( myFieldType == QVariant::Int )
+        {
+          le->setValidator( new QIntValidator( le ) );
+        }
+        else if ( myFieldType == QVariant::Double )
+        {
+          le->setValidator( new QDoubleValidator( le ) );
+        }
+
+        myWidget = le;
       }
-
-      if ( myFieldType == QVariant::Int )
+      
+      if( te )
       {
-        le->setValidator( new QIntValidator( le ) );
+        te->setAcceptRichText(true);
+        myWidget = te;
       }
-      else if ( myFieldType == QVariant::Double )
+
+      if( pte )
       {
-        le->setValidator( new QDoubleValidator( le ) );
+        myWidget = pte;
       }
-
-      myWidget = le;
     }
     break;
 
@@ -234,21 +320,43 @@
 
     case QgsVectorLayer::FileName:
     {
-      QLineEdit *le = new QLineEdit();
+      QPushButton *pb = NULL;
+      QLineEdit *le = qobject_cast<QLineEdit *>( editor );
+      if ( le )
+      {
+        if ( le )
+          myWidget = le;
 
-      QPushButton *pb = new QPushButton( tr( "..." ) );
-      connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) );
+        if( editor->parent() )
+        {
+          pb = editor->parent()->findChild<QPushButton *>();
+        }
+      }
+      else
+      {
+        le = new QLineEdit();
 
-      QHBoxLayout *hbl = new QHBoxLayout();
-      hbl->addWidget( le );
-      hbl->addWidget( pb );
+        QPushButton *pb = new QPushButton( tr( "..." ) );
 
-      myWidget = new QWidget( parent );
-      myWidget->setLayout( hbl );
+        QHBoxLayout *hbl = new QHBoxLayout();
+        hbl->addWidget( le );
+        hbl->addWidget( pb );
+
+        myWidget = new QWidget( parent );
+        myWidget->setLayout( hbl );
+      }
+
+      if ( pb )
+        connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) );
     }
     break;
   }
 
+  if ( editType == QgsVectorLayer::Immutable )
+  {
+    myWidget->setEnabled( false );
+  }
+
   setValue( myWidget, vl, idx, value );
 
   return myWidget;
@@ -275,6 +383,28 @@
     }
   }
 
+  QTextEdit *te = qobject_cast<QTextEdit *>( widget );
+  if ( te )
+  {
+    text = te->toHtml();
+    modified = te->document()->isModified();
+    if( text == "NULL" )
+    {
+      text = QString::null;
+    }
+  }
+
+  QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
+  if ( pte )
+  {
+    text = pte->toPlainText();
+    modified = pte->document()->isModified();
+    if( text == "NULL" )
+    {
+      text = QString::null;
+    }
+  }
+
   QComboBox *cb = qobject_cast<QComboBox *>( widget );
   if ( cb )
   {
@@ -301,12 +431,20 @@
   {
     text = QString::number( slider->value() );
   }
+
   QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
   if ( dsb )
   {
     text = QString::number( dsb->value() );
   }
 
+  QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
+  if ( ckb )
+  {
+    QPair<QString, QString> states = vl->checkedState( idx );
+    text = ckb->isChecked() ? states.first : states.second;
+  }
+
   le = widget->findChild<QLineEdit *>();
   if ( le )
   {
@@ -411,6 +549,17 @@
       }
     }
 
+    case QgsVectorLayer::CheckBox:
+    {
+      QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
+      if( cb )
+      {
+        QPair<QString, QString> states = vl->checkedState( idx );
+        cb->setChecked( value == states.first );
+        break;
+      }
+    }
+
     // fall-through
 
     case QgsVectorLayer::LineEdit:
@@ -419,7 +568,9 @@
     default:
     {
       QLineEdit *le = qobject_cast<QLineEdit *>( editor );
-      if ( le == NULL )
+      QTextEdit *te = qobject_cast<QTextEdit *>( editor );
+      QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
+      if ( !le && !te && !pte )
         return false;
 
       QString text;
@@ -431,7 +582,12 @@
       else
         text = value.toString();
 
-      le->setText( text );
+      if( le )
+        le->setText( text );
+      if( te )
+        te->setHtml( text );
+      if( pte )
+        pte->setPlainText( text );
     }
     break;
 

Modified: trunk/qgis/src/app/qgsattributeeditor.h
===================================================================
--- trunk/qgis/src/app/qgsattributeeditor.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributeeditor.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -23,6 +23,7 @@
 class QObject;
 class QWidget;
 class QgsVectorLayer;
+class QComboBox;
 
 class QgsAttributeEditor : public QObject
 {
@@ -30,10 +31,13 @@
 
   public:
     QgsAttributeEditor( QObject *parent ) : QObject( parent ) {}
-    static QWidget *createAttributeEditor( QWidget *parent, QgsVectorLayer *vl, int idx, const QVariant &value );
+    static QWidget *createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value );
     static bool retrieveValue( QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value );
     static bool setValue( QWidget *widget, QgsVectorLayer *vl, int idx, const QVariant &value );
 
+  private:
+    static QComboBox *comboBox( QWidget *editor, QWidget *parent );
+
   public slots:
     void selectFileName( void );
 };

Modified: trunk/qgis/src/app/qgsattributetypedialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsattributetypedialog.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributetypedialog.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -66,7 +66,17 @@
   return mValueMap;
 }
 
+QPair<QString, QString> QgsAttributeTypeDialog::checkedState()
+{
+  return QPair<QString, QString>( leCheckedState->text(), leUncheckedState->text() );
+}
 
+void QgsAttributeTypeDialog::setCheckedState( QString checked, QString unchecked )
+{
+  leCheckedState->setText( checked );
+  leUncheckedState->setText( unchecked );
+}
+
 void QgsAttributeTypeDialog::vCellChanged( int row, int column )
 {
   if ( row == tableWidget->rowCount() - 1 )
@@ -235,6 +245,10 @@
       setPage( 8 );
       break;
 
+    case QgsVectorLayer::CheckBox:
+      setPage( 9 );
+      break;
+
     case QgsVectorLayer::LineEdit:
       setPage( 0 );
       break;
@@ -513,6 +527,9 @@
     case 8:
       mEditType = QgsVectorLayer::Hidden;
       break;
+    case 9:
+      mEditType = QgsVectorLayer::CheckBox;
+      break;
     default:
       mEditType = QgsVectorLayer::LineEdit;
   }

Modified: trunk/qgis/src/app/qgsattributetypedialog.h
===================================================================
--- trunk/qgis/src/app/qgsattributetypedialog.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsattributetypedialog.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -66,12 +66,24 @@
     void setValueMap( QMap<QString, QVariant> valueMap );
 
     /**
-     * Setter to range for to be displayed and edited in this dialog
-     * @param rangeData rande data which is to be displayed
+     * Setter to range to be displayed and edited in this dialog
+     * @param rangeData range data which is to be displayed
      */
     void setRange( QgsVectorLayer::RangeData rangeData );
 
     /**
+     * Setter to checked state to be displayed and edited in this dialog
+     * @param checked string that represents the checked state
+     */
+    void setCheckedState( QString checked, QString unchecked ); 
+
+    /**
+     * Getter for checked state after editing
+     * @return string representing the checked
+     */
+    QPair<QString, QString> checkedState();
+
+    /**
      * Getter for value map after editing
      * @return map which is to be returned
      */

Modified: trunk/qgis/src/app/qgsidentifyresults.cpp
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsidentifyresults.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -147,8 +147,8 @@
     {
       connect( vlayer, SIGNAL( layerDeleted() ), this, SLOT( layerDestroyed() ) );
       connect( vlayer, SIGNAL( featureDeleted( int ) ), this, SLOT( featureDeleted( int ) ) );
-      connect( vlayer, SIGNAL( editingStarted() ), this, SLOT( addEditAction() ) );
-      connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( removeEditAction() ) );
+      connect( vlayer, SIGNAL( editingStarted() ), this, SLOT( editingToggled() ) );
+      connect( vlayer, SIGNAL( editingStopped() ), this, SLOT( editingToggled() ) );
     }
     else
     {
@@ -176,24 +176,22 @@
     }
   }
 
-  if ( vlayer && ( vlayer->actions()->size() > 0 || vlayer->isEditable() ) )
+  if ( vlayer )
   {
     QTreeWidgetItem *actionItem = new QTreeWidgetItem( QStringList() << tr( "(Actions)" ) );
     actionItem->setData( 0, Qt::UserRole, "actions" );
     featItem->addChild( actionItem );
 
-    QTreeWidgetItem *twi;
+    QTreeWidgetItem *editItem = new QTreeWidgetItem( QStringList() << "" << (vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ) ) );
+    editItem->setIcon( 0, QgisApp::getThemeIcon( vlayer->isEditable() ? "/mIconEditable.png" : "/mIconEditable.png" ) );
+    editItem->setData( 0, Qt::UserRole, "edit" );
+    actionItem->addChild( editItem );
 
-    if ( vlayer->isEditable() )
-    {
-      addEditAction( actionItem );
-    }
-
     for ( int i = 0; i < vlayer->actions()->size(); i++ )
     {
       QgsAttributeAction::aIter iter = vlayer->actions()->retrieveAction( i );
 
-      twi = new QTreeWidgetItem( QStringList() << "" << iter->name() );
+      QTreeWidgetItem *twi = new QTreeWidgetItem( QStringList() << "" << iter->name() );
       twi->setIcon( 0, QgisApp::getThemeIcon( "/mAction.png" ) );
       twi->setData( 0, Qt::UserRole, "action" );
       twi->setData( 0, Qt::UserRole + 1, QVariant::fromValue( i ) );
@@ -204,6 +202,40 @@
   layItem->addChild( featItem );
 }
 
+void QgsIdentifyResults::editingToggled()
+{
+  QTreeWidgetItem *layItem = layerItem( sender() );
+  QgsVectorLayer *vlayer = vectorLayer( layItem );
+  if( !layItem || !vlayer )
+    return;
+
+  // iterate features
+  int i;
+  for( i=0; i<layItem->childCount(); i++ )
+  {
+    QTreeWidgetItem *featItem = layItem->child(i);
+
+    int j;
+    for( j=0; j<featItem->childCount() && featItem->child(j)->data( 0, Qt::UserRole ).toString() != "actions"; j++ )
+      QgsDebugMsg( QString("%1: skipped %2").arg( featItem->child(j)->data( 0, Qt::UserRole ).toString() ) );
+
+    if( j==featItem->childCount() || featItem->child(j)->childCount()<1 )
+      continue;
+
+    QTreeWidgetItem *actions = featItem->child(j);
+
+    for( j=0; i<actions->childCount() && actions->child(j)->data( 0, Qt::UserRole ).toString() != "edit"; j++ )  
+      ;
+
+    if( j==actions->childCount() )
+      continue;
+
+    QTreeWidgetItem *editItem = actions->child(j);
+    editItem->setIcon( 0, QgisApp::getThemeIcon( vlayer->isEditable() ? "/mIconEditable.png" : "/mIconEditable.png" ) );
+    editItem->setText( 1, vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ) );
+  }
+}
+
 // Call to show the dialog box.
 void QgsIdentifyResults::show()
 {
@@ -223,13 +255,10 @@
       {
         highlightFeature( featItem );
 
-        if ( layer->isEditable() )
-        {
-          // if this is the only feature, it's on a vector layer and that layer is editable:
-          // don't show the edit dialog instead of the results window
-          editFeature( featItem );
-          return;
-        }
+        // if this is the only feature and it's on a vector layer
+        // don't show the form dialog instead of the results window
+        featureForm( featItem );
+        return;
       }
     }
 
@@ -240,6 +269,7 @@
 
   QDialog::show();
 }
+
 // Slot called when user clicks the Close button
 // (saves the current window size/position)
 void QgsIdentifyResults::close()
@@ -247,6 +277,7 @@
   saveWindowLocation();
   done( 0 );
 }
+
 // Save the current window size/position before closing
 // from window menu or X in titlebar
 void QgsIdentifyResults::closeEvent( QCloseEvent *e )
@@ -256,83 +287,11 @@
   close();
 }
 
-void QgsIdentifyResults::addEditAction( QTreeWidgetItem *item )
-{
-  QTreeWidgetItem *editItem = new QTreeWidgetItem( QStringList() << "" << tr( "Edit feature" ) );
-  editItem->setIcon( 0, QgisApp::getThemeIcon( "/mIconEditable.png" ) );
-  editItem->setData( 0, Qt::UserRole, "edit" );
-  item->addChild( editItem );
-}
-
-void QgsIdentifyResults::addOrRemoveEditAction( bool addItem )
-{
-  QTreeWidgetItem *layItem = layerItem( sender() );
-
-  for ( int i = 0; i < layItem->childCount(); i++ )
-  {
-    QTreeWidgetItem *featItem = layItem->child( i );
-    QTreeWidgetItem *actionsItem = 0;
-
-    for ( int j = 0; j < featItem->childCount(); j++ )
-    {
-      QTreeWidgetItem *attrItem = featItem->child( j );
-
-      if ( attrItem->childCount() == 0 || attrItem->data( 0, Qt::UserRole ).toString() != "actions" )
-        continue;
-
-      actionsItem = attrItem;
-      break;
-    }
-
-    if ( addItem )
-    {
-      if ( !actionsItem )
-      {
-        actionsItem = new QTreeWidgetItem( QStringList() << tr( "(Actions)" ) );
-        actionsItem->setData( 0, Qt::UserRole, "actions" );
-        featItem->addChild( actionsItem );
-      }
-
-      addEditAction( actionsItem );
-    }
-    else if ( actionsItem )
-    {
-      for ( int k = 0; k < actionsItem->childCount(); k++ )
-      {
-        QTreeWidgetItem *editItem = actionsItem->child( k );
-        if ( editItem->data( 0, Qt::UserRole ).toString() != "edit" )
-          continue;
-
-        delete editItem;
-
-        if ( actionsItem->childCount() == 0 )
-          delete actionsItem;
-
-        break;
-      }
-    }
-    else
-    {
-      QgsDebugMsg( "actions item not found" );
-    }
-  }
-}
-
-void QgsIdentifyResults::addEditAction()
-{
-  addOrRemoveEditAction( true );
-}
-
-void QgsIdentifyResults::removeEditAction()
-{
-  addOrRemoveEditAction( false );
-}
-
 void QgsIdentifyResults::itemClicked( QTreeWidgetItem *item, int column )
 {
   if ( item->data( 0, Qt::UserRole ).toString() == "edit" )
   {
-    editFeature( item );
+    featureForm( item );
   }
   else if ( item->data( 0, Qt::UserRole ).toString() == "action" )
   {
@@ -362,12 +321,9 @@
 
   QAction *a;
 
-  if ( vlayer->isEditable() )
-  {
-    a = mActionPopup->addAction( tr( "Edit feature" ) );
-    a->setEnabled( true );
-    a->setData( QVariant::fromValue( -6 ) );
-  }
+  a = mActionPopup->addAction( vlayer->isEditable() ? tr( "Edit feature form" ) : tr( "View feature form" ) );
+  a->setEnabled( true );
+  a->setData( QVariant::fromValue( -6 ) );
 
   a = mActionPopup->addAction( tr( "Zoom to feature" ) );
   a->setEnabled( true );
@@ -454,7 +410,7 @@
     switch ( action )
     {
       case -6:
-        editFeature( item );
+        featureForm( item );
         break;
 
       case -5:
@@ -694,8 +650,8 @@
   {
     disconnect( vlayer, SIGNAL( layerDeleted() ), this, SLOT( layerDestroyed() ) );
     disconnect( vlayer, SIGNAL( featureDeleted( int ) ), this, SLOT( featureDeleted( int ) ) );
-    disconnect( vlayer, SIGNAL( editingStarted() ), this, SLOT( addEditAction() ) );
-    disconnect( vlayer, SIGNAL( editingStopped() ), this, SLOT( removeEditAction() ) );
+    disconnect( vlayer, SIGNAL( editingStarted() ), this, SLOT( changeEditAction() ) );
+    disconnect( vlayer, SIGNAL( editingStopped() ), this, SLOT( changeEditAction() ) );
   }
   else
   {
@@ -810,10 +766,10 @@
 }
 
 
-void QgsIdentifyResults::editFeature( QTreeWidgetItem *item )
+void QgsIdentifyResults::featureForm( QTreeWidgetItem *item )
 {
   QgsVectorLayer *layer = vectorLayer( item );
-  if ( !layer || !layer->isEditable() )
+  if ( !layer )
     return;
 
   QTreeWidgetItem *featItem = featureItem( item );

Modified: trunk/qgis/src/app/qgsidentifyresults.h
===================================================================
--- trunk/qgis/src/app/qgsidentifyresults.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsidentifyresults.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -80,7 +80,7 @@
     void popupItemSelected( QAction* menuAction );
 
     void layerDestroyed();
-
+    void editingToggled();
     void featureDeleted( int fid );
 
     //! Context help
@@ -96,9 +96,6 @@
     /* Item in tree was clicked */
     void itemClicked( QTreeWidgetItem *lvi, int column );
 
-    void addEditAction();
-    void removeEditAction();
-
   private:
     QMenu *mActionPopup;
     QgsVectorLayer *mRubberBandLayer;
@@ -113,8 +110,6 @@
     QTreeWidgetItem *layerItem( QObject *layer );
     QTreeWidgetItem *retrieveAttributes( QTreeWidgetItem *item, std::vector< std::pair<QString, QString> > &attributes );
     void clearRubberBand();
-    void addEditAction( QTreeWidgetItem * );
-    void addOrRemoveEditAction( bool addItem );
     void disconnectLayer( QObject *object );
 
     void setColumnText( int column, const QString & label );
@@ -124,7 +119,7 @@
 
     void highlightFeature( QTreeWidgetItem *item );
     void zoomToFeature( QTreeWidgetItem *item );
-    void editFeature( QTreeWidgetItem *item );
+    void featureForm( QTreeWidgetItem *item );
 
     void doAction( QTreeWidgetItem *item, int action );
 

Modified: trunk/qgis/src/app/qgsmaptooladdfeature.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooladdfeature.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsmaptooladdfeature.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -189,7 +189,7 @@
       }
       else
       {
-        QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
+        QgsAttributeDialog *mypDialog = new QgsAttributeDialog( vlayer, f );
         if ( mypDialog->exec() )
         {
           QgsDebugMsg( "Adding feature to layer" );

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -125,6 +125,8 @@
   leSpatialRefSys->setText( layer->srs().toProj4() );
   leSpatialRefSys->setCursorPosition( 0 );
 
+  leEditForm->setText( layer->editForm() );
+
   connect( sliderTransparency, SIGNAL( valueChanged( int ) ), this, SLOT( sliderTransparency_valueChanged( int ) ) );
 
   //for each overlay plugin create a new tab
@@ -236,6 +238,11 @@
     attributeTypeDialog.setIndex( index );
   }
 
+  if ( mCheckedStates.contains( index ) )
+  {
+    attributeTypeDialog.setCheckedState( mCheckedStates[index].first, mCheckedStates[index].second );
+  }
+
   if ( !attributeTypeDialog.exec() )
     return;
 
@@ -253,6 +260,8 @@
     case QgsVectorLayer::SliderRange:
       mRanges.insert( index, attributeTypeDialog.rangeData() );
       break;
+    case QgsVectorLayer::CheckBox:
+      mCheckedStates.insert( index, attributeTypeDialog.checkedState() );
     default:
       break;
   }
@@ -550,6 +559,7 @@
   editTypeMap.insert( QgsVectorLayer::Enumeration, tr( "Enumeration" ) );
   editTypeMap.insert( QgsVectorLayer::Immutable, tr( "Immutable" ) );
   editTypeMap.insert( QgsVectorLayer::Hidden, tr( "Hidden" ) );
+  editTypeMap.insert( QgsVectorLayer::CheckBox, tr( "Checkbox" ) );
 }
 
 QString QgsVectorLayerProperties::editTypeButtonText( QgsVectorLayer::EditType type )
@@ -586,6 +596,8 @@
   // update the display field
   layer->setDisplayField( displayFieldComboBox->currentText() );
 
+  layer->setEditForm( leEditForm->text() );
+
   actionDialog->apply();
 
   labelDialog->apply();
@@ -620,6 +632,13 @@
         layer->range( idx ) = mRanges[idx];
       }
     }
+    else if ( editType == QgsVectorLayer::CheckBox )
+    {
+      if ( mCheckedStates.contains( idx ) )
+      {
+        layer->setCheckedState( idx, mCheckedStates[idx].first, mCheckedStates[idx].second );
+      }
+    }
   }
 
   QgsSingleSymbolDialog *sdialog =
@@ -1053,6 +1072,18 @@
   calc.exec();
 }
 
+void QgsVectorLayerProperties::on_pbnSelectEditForm_clicked()
+{
+  QSettings myQSettings;
+  QString lastUsedDir = myQSettings.value( "style/lastUIDir", "." ).toString();
+  QString uifilename = QFileDialog::getOpenFileName( this, tr( "Select edit form" ), lastUsedDir, tr( "UI file (*.ui)" ) );
+
+  if ( uifilename.isNull() )
+    return;
+
+  leEditForm->setText( uifilename );
+}
+
 QList<QgsVectorOverlayPlugin*> QgsVectorLayerProperties::overlayPlugins() const
 {
   QList<QgsVectorOverlayPlugin*> pluginList;

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.h
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -102,6 +102,7 @@
     void on_pbnSaveStyleAs_clicked();
     void on_tblAttributes_cellChanged( int row, int column );
     void on_mCalculateFieldButton_clicked();
+    void on_pbnSelectEditForm_clicked();
 
     void addAttribute();
     void deleteAttribute();
@@ -145,6 +146,7 @@
     QMap<int, QgsVectorLayer::EditType> mEditTypeMap;
     QMap<int, QMap<QString, QVariant> > mValueMaps;
     QMap<int, QgsVectorLayer::RangeData> mRanges;
+    QMap<int, QPair<QString, QString> > mCheckedStates;
 
     void updateButtons();
     void loadRows();

Modified: trunk/qgis/src/core/qgsvectorlayer.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.cpp	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/core/qgsvectorlayer.cpp	2009-11-10 18:30:57 UTC (rev 12077)
@@ -1128,7 +1128,7 @@
 void QgsVectorLayer::updateFeatureAttributes( QgsFeature &f )
 {
   // do not update when we aren't in editing mode
-  if ( ! mEditable )
+  if ( !mEditable )
     return;
 
   if ( mChangedAttributeValues.contains( f.id() ) )
@@ -2357,9 +2357,20 @@
 
         mRanges[ name ] = RangeData( min, max, step );
       }
+      else if( editType == CheckBox )
+      {
+        mCheckedStates[ name ] = QPair<QString, QString>( editTypeElement.attribute( "checked" ), editTypeElement.attribute( "unchecked" ) );
+      }
     }
   }
 
+  QDomNode editFormNode = node.namedItem( "editform" );
+  if ( !editFormNode.isNull() )
+  {
+    QDomElement e = editFormNode.toElement();
+    mEditForm = e.text();
+  }
+
   mAttributeAliasMap.clear();
   QDomNode aliasesNode = node.namedItem( "aliases" );
   if ( !aliasesNode.isNull() )
@@ -2504,6 +2515,14 @@
           editTypeElement.setAttribute( "step", mRanges[ it.key()].mStep.toString() );
         }
       }
+      else if ( it.value() == CheckBox )
+      {
+        if ( mCheckedStates.contains( it.key() ) )
+        {
+          editTypeElement.setAttribute( "checked", mCheckedStates[ it.key()].first );
+          editTypeElement.setAttribute( "unchecked", mCheckedStates[ it.key()].second );
+        }
+      }
 
       editTypesElement.appendChild( editTypeElement );
     }
@@ -2511,6 +2530,11 @@
     node.appendChild( editTypesElement );
   }
 
+  QDomElement efField  = doc.createElement( "editform" );
+  QDomText efText = doc.createTextNode( mEditForm );
+  efField.appendChild( efText );
+  node.appendChild( efField );
+
   //attribute aliases
   if ( mAttributeAliasMap.size() > 0 )
   {
@@ -3708,6 +3732,16 @@
     mEditTypes[ fields[idx].name()] = type;
 }
 
+QString QgsVectorLayer::editForm()
+{
+  return mEditForm;
+}
+
+void QgsVectorLayer::setEditForm( QString ui )
+{
+  mEditForm = ui;
+}
+
 QMap< QString, QVariant > &QgsVectorLayer::valueMap( int idx )
 {
   const QgsFieldMap &fields = pendingFields();
@@ -4091,3 +4125,19 @@
   // it's not ideal to trigger refresh from here
   triggerRepaint();
 }
+
+void QgsVectorLayer::setCheckedState( int idx, QString checked, QString unchecked )
+{
+  const QgsFieldMap &fields = pendingFields();
+  if ( fields.contains( idx ) )
+    mCheckedStates[ fields[idx].name() ] = QPair<QString, QString>( checked, unchecked );
+}
+
+QPair<QString, QString> QgsVectorLayer::checkedState( int idx )
+{
+  const QgsFieldMap &fields = pendingFields();
+  if ( fields.contains( idx ) && mCheckedStates.contains( fields[idx].name() ) )
+    return mCheckedStates[ fields[idx].name() ];
+  else
+    return QPair<QString,QString>( "1", "0" );
+}

Modified: trunk/qgis/src/core/qgsvectorlayer.h
===================================================================
--- trunk/qgis/src/core/qgsvectorlayer.h	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/core/qgsvectorlayer.h	2009-11-10 18:30:57 UTC (rev 12077)
@@ -53,9 +53,6 @@
 typedef QSet<int> QgsAttributeIds;
 
 
-
-
-
 /** \ingroup core
  * Vector layer backed by a data source provider.
  */
@@ -73,6 +70,7 @@
       Classification,
       EditRange,
       SliderRange,
+      CheckBox,    /* added in 1.4 */
       FileName,
       Enumeration,
       Immutable,   /*The attribute value should not be changed in the attribute form*/
@@ -450,7 +448,19 @@
 
     /**set edit type*/
     void setEditType( int idx, EditType edit );
+ 
+    /** set string representing 'true' for a checkbox (added in 1.4) */
+    void setCheckedState( int idx, QString checked, QString notChecked );
+    
+    /** return string representing 'true' for a checkbox (added in 1.4) */
+    QPair<QString, QString> checkedState( int idx );
 
+    /** get edit form (added in 1.4) */
+    QString editForm();
+
+    /** set edit form (added in 1.4) */
+    void setEditForm( QString ui );
+
     /**access value map*/
     QMap<QString, QVariant> &valueMap( int idx );
 
@@ -719,6 +729,8 @@
     QMap< QString, EditType > mEditTypes;
     QMap< QString, QMap<QString, QVariant> > mValueMaps;
     QMap< QString, RangeData > mRanges;
+    QMap< QString, QPair<QString,QString> > mCheckedStates;
+    QString mEditForm;
 
     bool mFetching;
     QgsRectangle mFetchRect;

Deleted: trunk/qgis/src/ui/qgsattributedialogbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsattributedialogbase.ui	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/ui/qgsattributedialogbase.ui	2009-11-10 18:30:57 UTC (rev 12077)
@@ -1,71 +0,0 @@
-<ui version="4.0" >
- <class>QgsAttributeDialogBase</class>
- <widget class="QDialog" name="QgsAttributeDialogBase" >
-  <property name="geometry" >
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>447</width>
-    <height>343</height>
-   </rect>
-  </property>
-  <property name="windowTitle" >
-   <string>Enter Attribute Values</string>
-  </property>
-  <layout class="QGridLayout" >
-   <item row="0" column="0" >
-    <widget class="QFrame" name="mFrame" >
-     <property name="frameShape" >
-      <enum>QFrame::StyledPanel</enum>
-     </property>
-     <property name="frameShadow" >
-      <enum>QFrame::Raised</enum>
-     </property>
-    </widget>
-   </item>
-   <item row="2" column="0" >
-    <widget class="QDialogButtonBox" name="buttonBox" >
-     <property name="standardButtons" >
-      <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
-     </property>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <layoutdefault spacing="6" margin="11" />
- <resources/>
- <connections>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>accepted()</signal>
-   <receiver>QgsAttributeDialogBase</receiver>
-   <slot>accept()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>277</x>
-     <y>318</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>325</x>
-     <y>279</y>
-    </hint>
-   </hints>
-  </connection>
-  <connection>
-   <sender>buttonBox</sender>
-   <signal>rejected()</signal>
-   <receiver>QgsAttributeDialogBase</receiver>
-   <slot>reject()</slot>
-   <hints>
-    <hint type="sourcelabel" >
-     <x>208</x>
-     <y>308</y>
-    </hint>
-    <hint type="destinationlabel" >
-     <x>163</x>
-     <y>284</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
-</ui>

Modified: trunk/qgis/src/ui/qgsattributetypeedit.ui
===================================================================
--- trunk/qgis/src/ui/qgsattributetypeedit.ui	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/ui/qgsattributetypeedit.ui	2009-11-10 18:30:57 UTC (rev 12077)
@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>401</width>
+    <width>471</width>
     <height>428</height>
    </rect>
   </property>
@@ -61,12 +61,23 @@
        <string>Hidden</string>
       </property>
      </item>
+     <item>
+      <property name="text">
+       <string>Checkbox</string>
+      </property>
+     </item>
     </widget>
    </item>
    <item>
     <widget class="QStackedWidget" name="stackedWidget">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
      <property name="currentIndex">
-      <number>0</number>
+      <number>9</number>
      </property>
      <widget class="QWidget" name="lineEditPage">
       <layout class="QVBoxLayout" name="verticalLayout_1">
@@ -486,6 +497,53 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="checkBoxPage">
+      <property name="maximumSize">
+       <size>
+        <width>453</width>
+        <height>333</height>
+       </size>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_13">
+       <item>
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="2">
+          <widget class="QLineEdit" name="leCheckedState"/>
+         </item>
+         <item row="0" column="1">
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Representation for checked state</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="1">
+          <widget class="QLabel" name="label_3">
+           <property name="text">
+            <string>Representation for unchecked state</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="2">
+          <widget class="QLineEdit" name="leUncheckedState"/>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer name="verticalSpacer_8">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
    <item>

Modified: trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui	2009-11-10 18:16:35 UTC (rev 12076)
+++ trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui	2009-11-10 18:30:57 UTC (rev 12077)
@@ -94,7 +94,7 @@
       <enum>QTabWidget::Rounded</enum>
      </property>
      <property name="currentIndex">
-      <number>0</number>
+      <number>3</number>
      </property>
      <widget class="QWidget" name="tab2">
       <property name="sizePolicy">
@@ -410,21 +410,21 @@
             </property>
            </widget>
           </item>
-          <item row="2" column="0" colspan="3">
+          <item row="3" column="0" colspan="3">
            <widget class="QLineEdit" name="leSpatialRefSys">
             <property name="readOnly">
              <bool>true</bool>
             </property>
            </widget>
           </item>
-          <item row="3" column="1">
+          <item row="4" column="1">
            <widget class="QPushButton" name="pbnIndex">
             <property name="text">
              <string>Create Spatial Index</string>
             </property>
            </widget>
           </item>
-          <item row="3" column="2">
+          <item row="4" column="2">
            <widget class="QPushButton" name="pbnChangeSpatialRefSys">
             <property name="toolTip">
              <string>Specify the coordinate reference system of the layer's geometry.</string>
@@ -437,6 +437,23 @@
             </property>
            </widget>
           </item>
+          <item row="2" column="0">
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Edit UI</string>
+            </property>
+           </widget>
+          </item>
+          <item row="2" column="1">
+           <widget class="QLineEdit" name="leEditForm"/>
+          </item>
+          <item row="2" column="2">
+           <widget class="QPushButton" name="pbnSelectEditForm">
+            <property name="text">
+             <string>...</string>
+            </property>
+           </widget>
+          </item>
          </layout>
         </widget>
        </item>



More information about the QGIS-commit mailing list