[QGIS Commit] r11735 - in trunk/qgis: images/themes/default src/app src/core src/ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Wed Sep 30 03:14:57 EDT 2009


Author: mhugent
Date: 2009-09-30 03:14:54 -0400 (Wed, 30 Sep 2009)
New Revision: 11735

Added:
   trunk/qgis/images/themes/default/mActionCalculateField.png
   trunk/qgis/src/app/qgsfieldcalculator.cpp
   trunk/qgis/src/app/qgsfieldcalculator.h
   trunk/qgis/src/ui/qgsfieldcalculatorbase.ui
Modified:
   trunk/qgis/src/app/CMakeLists.txt
   trunk/qgis/src/app/qgsvectorlayerproperties.cpp
   trunk/qgis/src/app/qgsvectorlayerproperties.h
   trunk/qgis/src/core/qgssearchstringlexer.ll
   trunk/qgis/src/core/qgssearchstringparser.yy
   trunk/qgis/src/core/qgssearchtreenode.cpp
   trunk/qgis/src/core/qgssearchtreenode.h
   trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui
Log:
[FEATURE]: A field calculator, accessible with a button in the attribute section of the vector properties

Added: trunk/qgis/images/themes/default/mActionCalculateField.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionCalculateField.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/app/CMakeLists.txt	2009-09-30 07:14:54 UTC (rev 11735)
@@ -20,6 +20,7 @@
   qgsspatialitefilterproxymodel.cpp
   qgsspatialitetablemodel.cpp
   qgsdelattrdialog.cpp
+  qgsfieldcalculator.cpp
   qgsnewvectorlayerdialog.cpp
   qgsgraduatedsymboldialog.cpp
   qgshelpviewer.cpp
@@ -122,6 +123,7 @@
   qgsconfigureshortcutsdialog.h
   qgscustomprojectiondialog.h
   qgsdelattrdialog.h
+  qgsfieldcalculator.h
   qgsnewvectorlayerdialog.h
   qgsgraduatedsymboldialog.h
   qgshelpviewer.h

Added: trunk/qgis/src/app/qgsfieldcalculator.cpp
===================================================================
--- trunk/qgis/src/app/qgsfieldcalculator.cpp	                        (rev 0)
+++ trunk/qgis/src/app/qgsfieldcalculator.cpp	2009-09-30 07:14:54 UTC (rev 11735)
@@ -0,0 +1,353 @@
+/***************************************************************************
+    qgsfieldcalculator.cpp
+    ---------------------
+    begin                : September 2009
+    copyright            : (C) 2009 by Marco Hugentobler
+    email                : marco at hugis dot net
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "qgsfieldcalculator.h"
+#include "qgssearchtreenode.h"
+#include "qgssearchstring.h"
+#include "qgsvectorlayer.h"
+#include <QMessageBox>
+
+QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer* vl ): QDialog(), mVectorLayer( vl )
+{
+  setupUi( this );
+  mOutputFieldTypeComboBox->addItem( tr( "Double" ) );
+  mOutputFieldTypeComboBox->addItem( tr( "Integer" ) );
+  mOutputFieldTypeComboBox->addItem( tr( "String" ) );
+
+  populateFields();
+
+  //default values for field width and precision
+  mOuputFieldWidthSpinBox->setValue( 10 );
+  mOutputFieldPrecisionSpinBox->setValue( 3 );
+
+  //disable ok button until there is text for output field and expression
+  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
+}
+
+QgsFieldCalculator::~QgsFieldCalculator()
+{
+
+}
+
+void QgsFieldCalculator::accept()
+{
+  if ( mVectorLayer && mVectorLayer->isEditable() )
+  {
+    QString calcString = mExpressionTextEdit->toPlainText();
+
+    //create QgsSearchString
+    QgsSearchString searchString;
+    if ( !searchString.setString( calcString ) )
+    {
+      //expression not valid
+      QMessageBox::critical( 0, tr( "Syntax error" ), tr( QString( "Invalid expression syntax. The error message of the parser is: '" + searchString.parserErrorMsg() + "'" ).toLocal8Bit().data() ) );
+      return;
+    }
+
+    //get QgsSearchTreeNode
+    QgsSearchTreeNode* searchTree = searchString.tree();
+    if ( !searchTree )
+    {
+      return;
+    }
+
+    mVectorLayer->beginEditCommand( "Field calculator" );
+
+    //create new field
+    QgsField newField( mOutputFieldNameLineEdit->text() );
+    if ( mOutputFieldTypeComboBox->currentText() == tr( "Double" ) )
+    {
+      newField.setType( QVariant::Double );
+    }
+    else if ( mOutputFieldTypeComboBox->currentText() == tr( "Integer" ) )
+    {
+      newField.setType( QVariant::Int );
+    }
+    else if ( mOutputFieldTypeComboBox->currentText() == tr( "String" ) )
+    {
+      newField.setType( QVariant::String );
+    }
+
+    newField.setLength( mOuputFieldWidthSpinBox->value() );
+    newField.setPrecision( mOutputFieldPrecisionSpinBox->value() );
+
+
+    if ( !mVectorLayer->addAttribute( newField ) )
+    {
+      mVectorLayer->destroyEditCommand();
+      return;
+    }
+
+    //get index of the new field
+    const QgsFieldMap fieldList = mVectorLayer->pendingFields();
+    int attributeId = -1;
+    QgsFieldMap::const_iterator it = fieldList.constBegin();
+    for ( ; it != fieldList.constEnd(); ++it )
+    {
+      if ( it.value().name() == mOutputFieldNameLineEdit->text() )
+      {
+        attributeId = it.key();
+        break;
+      }
+    }
+    if ( attributeId == -1 )
+    {
+      mVectorLayer->destroyEditCommand();
+      return;
+    }
+
+    //go through all the features and change the new attribute
+    QgsFeature feature;
+    bool calculationSuccess = true;
+
+    mVectorLayer->select( mVectorLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
+    while ( mVectorLayer->nextFeature( feature ) )
+    {
+      QgsSearchTreeValue value = searchTree->valueAgainst( mVectorLayer->pendingFields(), feature.attributeMap() );
+      if ( value.isError() )
+      {
+        calculationSuccess = false;
+        break;
+      }
+      if ( value.isNumeric() )
+      {
+        mVectorLayer->changeAttributeValue( feature.id(), attributeId, value.number(), false );
+      }
+      else
+      {
+        mVectorLayer->changeAttributeValue( feature.id(), attributeId, value.string(), false );
+      }
+
+    }
+
+    if ( !calculationSuccess )
+    {
+      QMessageBox::critical( 0, tr( "Error" ), tr( "An error occured while evaluating the calculation string." ) );
+
+      //remove new attribute
+      mVectorLayer->deleteAttribute( attributeId );
+      mVectorLayer->destroyEditCommand();
+      return;
+    }
+
+    mVectorLayer->endEditCommand();
+  }
+  QDialog::accept();
+}
+
+void QgsFieldCalculator::populateFields()
+{
+  if ( !mVectorLayer )
+  {
+    return;
+  }
+
+  const QgsFieldMap fieldMap = mVectorLayer->pendingFields();
+  QgsFieldMap::const_iterator fieldIt = fieldMap.constBegin();
+  for ( ; fieldIt != fieldMap.constEnd(); ++fieldIt )
+  {
+    QString fieldName = fieldIt.value().name();
+    mFieldMap.insert( fieldName, fieldIt.key() );
+    mFieldsListWidget->addItem( fieldName );
+  }
+}
+
+void QgsFieldCalculator::on_mFieldsListWidget_itemDoubleClicked( QListWidgetItem * item )
+{
+  if ( !item )
+  {
+    return;
+  }
+  mExpressionTextEdit->insertPlainText( item->text() );
+}
+
+void QgsFieldCalculator::on_mValueListWidget_itemDoubleClicked( QListWidgetItem * item )
+{
+  if ( !item )
+  {
+    return;
+  }
+  mExpressionTextEdit->insertPlainText( " " + item->text() + " " );
+}
+
+void QgsFieldCalculator::on_mPlusPushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " + " );
+}
+
+void QgsFieldCalculator::on_mMinusPushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " - " );
+}
+
+void QgsFieldCalculator::on_mMultiplyPushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " * " );
+}
+
+void QgsFieldCalculator::on_mDividePushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " / " );
+}
+
+void QgsFieldCalculator::on_mSqrtButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " sqrt ( " );
+}
+
+void QgsFieldCalculator::on_mExpButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " ^ " );
+}
+
+void QgsFieldCalculator::on_mSinButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " sin ( " );
+}
+
+void QgsFieldCalculator::on_mCosButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " cos ( " );
+}
+
+void QgsFieldCalculator::on_mTanButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " tan ( " );
+}
+
+void QgsFieldCalculator::on_mASinButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " asin ( " );
+}
+
+void QgsFieldCalculator::on_mACosButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " acos ( " );
+}
+
+void QgsFieldCalculator::on_mATanButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " atan ( " );
+}
+
+void QgsFieldCalculator::on_mOpenBracketPushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " ( " );
+}
+
+void QgsFieldCalculator::on_mCloseBracketPushButton_clicked()
+{
+  mExpressionTextEdit->insertPlainText( " ) " );
+}
+
+void QgsFieldCalculator::on_mSamplePushButton_clicked()
+{
+  getFieldValues( 25 );
+}
+
+void QgsFieldCalculator::on_mAllPushButton_clicked()
+{
+  getFieldValues( 0 );
+}
+
+void QgsFieldCalculator::on_mOutputFieldNameLineEdit_textChanged( const QString& text )
+{
+  setOkButtonState();
+}
+
+void QgsFieldCalculator::on_mExpressionTextEdit_textChanged()
+{
+  setOkButtonState();
+}
+
+void QgsFieldCalculator::on_mOutputFieldTypeComboBox_currentIndexChanged( const QString& text )
+{
+  if ( text == tr( "Double" ) )
+  {
+    mOutputFieldPrecisionSpinBox->setEnabled( true );
+  }
+  else
+  {
+    mOutputFieldPrecisionSpinBox->setEnabled( false );
+  }
+}
+
+void QgsFieldCalculator::getFieldValues( int limit )
+{
+  mValueListWidget->clear();
+
+  if ( !mVectorLayer )
+  {
+    return;
+  }
+
+  QListWidgetItem* currentItem = mFieldsListWidget->currentItem();
+  if ( !currentItem )
+  {
+    return;
+  }
+
+  QMap<QString, int>::const_iterator attIt = mFieldMap.find( currentItem->text() );
+  if ( attIt == mFieldMap.constEnd() )
+  {
+    return;
+  }
+
+  int attributeIndex = attIt.value();
+  QgsField field = mVectorLayer->pendingFields()[attributeIndex];
+  bool numeric = ( field.type() == QVariant::Int || field.type() == QVariant::Double );
+
+  QgsAttributeList attList;
+  attList << attributeIndex;
+
+  mVectorLayer->select( attList, QgsRectangle(), false );
+  QgsFeature f;
+  int resultCounter = 0;
+
+  mValueListWidget->setUpdatesEnabled( false );
+  mValueListWidget->blockSignals( true );
+  QSet<QString> insertedValues;
+
+  while ( mVectorLayer->nextFeature( f ) && ( limit == 0 || resultCounter != limit ) )
+  {
+    QString value = f.attributeMap()[attributeIndex].toString();
+    if ( !numeric )
+    {
+      value = ( "'" + value + "'" );
+    }
+    //QList<QListWidgetItem *> existingItems = mValueListWidget->findItems(value, Qt::MatchExactly);
+    //if(existingItems.isEmpty())
+    if ( !insertedValues.contains( value ) )
+    {
+      mValueListWidget->addItem( value );
+      insertedValues.insert( value );
+      ++resultCounter;
+    }
+  }
+  mValueListWidget->setUpdatesEnabled( true );
+  mValueListWidget->blockSignals( false );
+}
+
+void QgsFieldCalculator::setOkButtonState()
+{
+  bool okEnabled = true;
+  if ( mOutputFieldNameLineEdit->text().isEmpty() || mExpressionTextEdit->toPlainText().isEmpty() )
+  {
+    okEnabled = false;
+  }
+  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( okEnabled );
+}
+
+

Added: trunk/qgis/src/app/qgsfieldcalculator.h
===================================================================
--- trunk/qgis/src/app/qgsfieldcalculator.h	                        (rev 0)
+++ trunk/qgis/src/app/qgsfieldcalculator.h	2009-09-30 07:14:54 UTC (rev 11735)
@@ -0,0 +1,71 @@
+/***************************************************************************
+    qgsfieldcalculator.h
+    ---------------------
+    begin                : September 2009
+    copyright            : (C) 2009 by Marco Hugentobler
+    email                : marco at hugis dot net
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QGSFIELDCALCULATOR_H
+#define QGSFIELDCALCULATOR_H
+
+#include "ui_qgsfieldcalculatorbase.h"
+
+class QgsVectorLayer;
+
+/**A dialog class that provides calculation of new fields using existing fields, values and a set of operators*/
+class QgsFieldCalculator: public QDialog, private Ui::QgsFieldCalculatorBase
+{
+    Q_OBJECT
+  public:
+    QgsFieldCalculator( QgsVectorLayer* vl );
+    ~QgsFieldCalculator();
+
+  public slots:
+    void accept();
+
+    void on_mFieldsListWidget_itemDoubleClicked( QListWidgetItem * item );
+    void on_mValueListWidget_itemDoubleClicked( QListWidgetItem * item );
+    void on_mPlusPushButton_clicked();
+    void on_mMinusPushButton_clicked();
+    void on_mMultiplyPushButton_clicked();
+    void on_mDividePushButton_clicked();
+    void on_mSqrtButton_clicked();
+    void on_mExpButton_clicked();
+    void on_mSinButton_clicked();
+    void on_mCosButton_clicked();
+    void on_mTanButton_clicked();
+    void on_mASinButton_clicked();
+    void on_mACosButton_clicked();
+    void on_mATanButton_clicked();
+    void on_mOpenBracketPushButton_clicked();
+    void on_mCloseBracketPushButton_clicked();
+    void on_mSamplePushButton_clicked();
+    void on_mAllPushButton_clicked();
+    void on_mOutputFieldNameLineEdit_textChanged( const QString& text );
+    void on_mExpressionTextEdit_textChanged();
+    void on_mOutputFieldTypeComboBox_currentIndexChanged( const QString& text );
+
+  private:
+    //default constructor forbidden
+    QgsFieldCalculator();
+    void populateFields();
+    /**Gets field values and inserts them into mValueListWidget
+    @limit 0: get all feature, != 0 stop after getting limit values*/
+    void getFieldValues( int limit );
+    /**Sets the ok button enabled / disabled*/
+    void setOkButtonState();
+
+    QgsVectorLayer* mVectorLayer;
+    /**Key: field name, Value: field index*/
+    QMap<QString, int> mFieldMap;
+};
+
+#endif // QGSFIELDCALCULATOR_H

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.cpp	2009-09-30 07:14:54 UTC (rev 11735)
@@ -26,6 +26,7 @@
 #include "qgscontexthelp.h"
 #include "qgscontinuouscolordialog.h"
 #include "qgscoordinatetransform.h"
+#include "qgsfieldcalculator.h"
 #include "qgsgraduatedsymboldialog.h"
 #include "qgslabeldialog.h"
 #include "qgslabel.h"
@@ -92,6 +93,7 @@
   mAddAttributeButton->setIcon( QgisApp::getThemeIcon( "/mActionNewAttribute.png" ) );
   mDeleteAttributeButton->setIcon( QgisApp::getThemeIcon( "/mActionDeleteAttribute.png" ) );
   mToggleEditingButton->setIcon( QgisApp::getThemeIcon( "/mActionToggleEditing.png" ) );
+  mCalculateFieldButton->setIcon( QgisApp::getThemeIcon( "/mActionCalculateField.png" ) );
 
 
   // Create the Label dialog tab
@@ -356,6 +358,7 @@
     int cap = layer->dataProvider()->capabilities();
     mAddAttributeButton->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
     mDeleteAttributeButton->setEnabled( cap & QgsVectorDataProvider::DeleteAttributes );
+    mCalculateFieldButton->setEnabled(( cap &  QgsVectorDataProvider::AddAttributes ) && ( cap & QgsVectorDataProvider::ChangeAttributeValues ) );
     mToggleEditingButton->setChecked( true );
   }
   else
@@ -363,6 +366,7 @@
     mAddAttributeButton->setEnabled( false );
     mDeleteAttributeButton->setEnabled( false );
     mToggleEditingButton->setChecked( false );
+    mCalculateFieldButton->setEnabled( false );
   }
 }
 
@@ -1116,6 +1120,17 @@
   }
 }
 
+void QgsVectorLayerProperties::on_mCalculateFieldButton_clicked()
+{
+  if ( !layer )
+  {
+    return;
+  }
+
+  QgsFieldCalculator calc( layer );
+  calc.exec();
+}
+
 QList<QgsVectorOverlayPlugin*> QgsVectorLayerProperties::overlayPlugins() const
 {
   QList<QgsVectorOverlayPlugin*> pluginList;

Modified: trunk/qgis/src/app/qgsvectorlayerproperties.h
===================================================================
--- trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/app/qgsvectorlayerproperties.h	2009-09-30 07:14:54 UTC (rev 11735)
@@ -101,6 +101,7 @@
     void on_pbnLoadStyle_clicked();
     void on_pbnSaveStyleAs_clicked();
     void on_tblAttributes_cellChanged( int row, int column );
+    void on_mCalculateFieldButton_clicked();
 
     void addAttribute();
     void deleteAttribute();

Modified: trunk/qgis/src/core/qgssearchstringlexer.ll
===================================================================
--- trunk/qgis/src/core/qgssearchstringlexer.ll	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/core/qgssearchstringlexer.ll	2009-09-30 07:14:54 UTC (rev 11735)
@@ -68,8 +68,16 @@
 "~"   {  yylval.op = QgsSearchTreeNode::opRegexp; return COMPARISON; }
 "LIKE" { yylval.op = QgsSearchTreeNode::opLike; return COMPARISON; }
 
-[+-/*]    { return yytext[0]; }
+"sqrt" { yylval.op = QgsSearchTreeNode::opSQRT; return FUNCTION;}
+"sin"  { yylval.op = QgsSearchTreeNode::opSIN; return FUNCTION;}
+"cos"  { yylval.op = QgsSearchTreeNode::opCOS; return FUNCTION;}
+"tan"  { yylval.op = QgsSearchTreeNode::opTAN; return FUNCTION;}
+"asin" { yylval.op = QgsSearchTreeNode::opASIN; return FUNCTION;}
+"acos" { yylval.op = QgsSearchTreeNode::opACOS; return FUNCTION;}
+"atan" { yylval.op = QgsSearchTreeNode::opATAN; return FUNCTION;}
 
+[+-/*^]    { return yytext[0]; }
+
 [()]      { return yytext[0]; }
 
 {number}  { yylval.number  = atof(yytext); return NUMBER; }

Modified: trunk/qgis/src/core/qgssearchstringparser.yy
===================================================================
--- trunk/qgis/src/core/qgssearchstringparser.yy	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/core/qgssearchstringparser.yy	2009-09-30 07:14:54 UTC (rev 11735)
@@ -52,7 +52,7 @@
 
 %}
 
-%union { QgsSearchTreeNode* node; double number; QgsSearchTreeNode::Operator op; }
+%union { QgsSearchTreeNode* node; double number; QgsSearchTreeNode::Operator op;}
 
 %start root
 
@@ -60,6 +60,7 @@
 
 %token <number> NUMBER
 %token <op> COMPARISON
+%token <op> FUNCTION
 
 %token STRING
 %token COLUMN_REF
@@ -82,6 +83,7 @@
 // operator precedence
 // all operators have left associativity
 // (right associtativity is used for  assigment)
+%left '^'
 %left '*' '/'
 %left '+' '-'
 %left UMINUS  // fictious symbol (for unary minus)
@@ -94,6 +96,7 @@
 %%
 
 root: search_cond { /*gParserRootNode = $1;*/ }
+      | scalar_exp {}
     ;
 
 search_cond:
@@ -114,7 +117,9 @@
     ;
 
 scalar_exp:
-     scalar_exp '*' scalar_exp    { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMUL,  $1, $3); joinTmpNodes($$,$1,$3); }
+    FUNCTION '(' scalar_exp ')' {$$ = new QgsSearchTreeNode($1, $3, 0); joinTmpNodes($$, $3, 0);}
+    |  scalar_exp '^' scalar_exp   { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPOW, $1, $3); joinTmpNodes($$, $1, $3); }
+    | scalar_exp '*' scalar_exp   { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMUL,  $1, $3); joinTmpNodes($$,$1,$3); }
     | scalar_exp '/' scalar_exp   { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opDIV,  $1, $3); joinTmpNodes($$,$1,$3); }
     | scalar_exp '+' scalar_exp   { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opPLUS, $1, $3); joinTmpNodes($$,$1,$3); }
     | scalar_exp '-' scalar_exp   { $$ = new QgsSearchTreeNode(QgsSearchTreeNode::opMINUS,$1, $3); joinTmpNodes($$,$1,$3); }

Modified: trunk/qgis/src/core/qgssearchtreenode.cpp
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.cpp	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/core/qgssearchtreenode.cpp	2009-09-30 07:14:54 UTC (rev 11735)
@@ -24,7 +24,14 @@
 #include <QObject>
 #include <iostream>
 
+#ifndef Q_OS_MACX
+#include <cmath>
+#else
+#include <math.h>
+#endif
 
+
+
 #define EVAL_STR(x) (x.length() ? x : "(empty)")
 
 QgsSearchTreeNode::QgsSearchTreeNode( double number )
@@ -154,7 +161,11 @@
 
         default: str += " ? ";
       }
-      str += mRight->makeSearchString();
+
+      if ( mRight )
+      {
+        str += mRight->makeSearchString();
+      }
     }
     else
     {
@@ -360,8 +371,14 @@
     case tOperator:
     {
       QgsSearchTreeValue value1, value2;
-      if ( !getValue( value1, mLeft, fields, attributes ) ) return value1;
-      if ( !getValue( value2, mRight, fields, attributes ) ) return value2;
+      if ( mLeft )
+      {
+        if ( !getValue( value1, mLeft, fields, attributes ) ) return value1;
+      }
+      if ( mRight )
+      {
+        if ( !getValue( value2, mRight, fields, attributes ) ) return value2;
+      }
 
       // convert to numbers if needed
       double val1, val2;
@@ -389,6 +406,26 @@
             return QgsSearchTreeValue( val1 / val2 );
         default:
           return QgsSearchTreeValue( 3, QString::number( mOp ) ); // unknown operator
+        case opPOW:
+          if (( val1 == 0 && val2 < 0 ) || ( val2 < 0 && ( val2 - std::floor( val2 ) ) > 0 ) )
+          {
+            return QgsSearchTreeValue( 4, "Error in power function" );
+          }
+          return QgsSearchTreeValue( std::pow( val1, val2 ) );
+        case opSQRT:
+          return QgsSearchTreeValue( std::sqrt( val1 ) );
+        case opSIN:
+          return QgsSearchTreeValue( std::sin( val1 ) );
+        case opCOS:
+          return QgsSearchTreeValue( std::cos( val1 ) );
+        case opTAN:
+          return QgsSearchTreeValue( std::tan( val1 ) );
+        case opASIN:
+          return QgsSearchTreeValue( std::asin( val1 ) );
+        case opACOS:
+          return QgsSearchTreeValue( std::acos( val1 ) );
+        case opATAN:
+          return QgsSearchTreeValue( std::atan( val1 ) );
       }
     }
 

Modified: trunk/qgis/src/core/qgssearchtreenode.h
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.h	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/core/qgssearchtreenode.h	2009-09-30 07:14:54 UTC (rev 11735)
@@ -62,6 +62,14 @@
       opMINUS,
       opMUL,
       opDIV,
+      opPOW,
+      opSQRT,
+      opSIN,
+      opCOS,
+      opTAN,
+      opASIN,
+      opACOS,
+      opATAN,
 
       // comparison
       opEQ,   // =
@@ -118,11 +126,10 @@
     //! returns error message
     const QString& errorMsg() { return mError; }
 
-  protected:
-
     //! returns scalar value of node
     QgsSearchTreeValue valueAgainst( const QgsFieldMap& fields, const QgsAttributeMap& attributes );
 
+  protected:
     //! wrapper around valueAgainst()
     bool getValue( QgsSearchTreeValue& value, QgsSearchTreeNode* node,
                    const QgsFieldMap& fields, const QgsAttributeMap& attributes );

Added: trunk/qgis/src/ui/qgsfieldcalculatorbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsfieldcalculatorbase.ui	                        (rev 0)
+++ trunk/qgis/src/ui/qgsfieldcalculatorbase.ui	2009-09-30 07:14:54 UTC (rev 11735)
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QgsFieldCalculatorBase</class>
+ <widget class="QDialog" name="QgsFieldCalculatorBase">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>383</width>
+    <height>496</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Field calculator</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <widget class="QLabel" name="mFieldNameLabel">
+     <property name="text">
+      <string>Output field name:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="2">
+    <widget class="QLineEdit" name="mOutputFieldNameLineEdit"/>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="mOutputFieldTypeLabel">
+     <property name="text">
+      <string>Output field type:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="2">
+    <widget class="QComboBox" name="mOutputFieldTypeComboBox"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="mOutputFieldWidthLabel">
+     <property name="text">
+      <string>Output field width:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QSpinBox" name="mOuputFieldWidthSpinBox"/>
+   </item>
+   <item row="2" column="2">
+    <widget class="QLabel" name="mOutputFieldPrecisionLabel">
+     <property name="text">
+      <string>Output field precision:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="3">
+    <widget class="QSpinBox" name="mOutputFieldPrecisionSpinBox"/>
+   </item>
+   <item row="3" column="0" colspan="2">
+    <widget class="QGroupBox" name="mFieldsGroupBox">
+     <property name="title">
+      <string>Fields</string>
+     </property>
+     <widget class="QListWidget" name="mFieldsListWidget">
+      <property name="geometry">
+       <rect>
+        <x>10</x>
+        <y>20</y>
+        <width>221</width>
+        <height>151</height>
+       </rect>
+      </property>
+     </widget>
+    </widget>
+   </item>
+   <item row="3" column="2" colspan="2">
+    <widget class="QGroupBox" name="mValuesGroupBox">
+     <property name="title">
+      <string>Values</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0" colspan="2">
+       <widget class="QListWidget" name="mValueListWidget"/>
+      </item>
+      <item row="1" column="0">
+       <widget class="QPushButton" name="mSamplePushButton">
+        <property name="text">
+         <string>Sample</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="mAllPushButton">
+        <property name="text">
+         <string>All</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="4" column="0" colspan="4">
+    <widget class="QGroupBox" name="mOperatorsGroupBox">
+     <property name="title">
+      <string>Operators</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout">
+      <item row="0" column="0">
+       <widget class="QPushButton" name="mPlusPushButton">
+        <property name="text">
+         <string>+</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QPushButton" name="mMultiplyPushButton">
+        <property name="text">
+         <string>*</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QPushButton" name="mSqrtButton">
+        <property name="text">
+         <string>sqrt</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="3">
+       <widget class="QPushButton" name="mSinButton">
+        <property name="text">
+         <string>sin</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="4">
+       <widget class="QPushButton" name="mTanButton">
+        <property name="text">
+         <string>tan</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="5">
+       <widget class="QPushButton" name="mACosButton">
+        <property name="text">
+         <string>acos</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="6">
+       <widget class="QPushButton" name="mOpenBracketPushButton">
+        <property name="text">
+         <string>(</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="0">
+       <widget class="QPushButton" name="mMinusPushButton">
+        <property name="text">
+         <string>-</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QPushButton" name="mDividePushButton">
+        <property name="text">
+         <string>/</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="2">
+       <widget class="QPushButton" name="mExpButton">
+        <property name="text">
+         <string>^</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="3">
+       <widget class="QPushButton" name="mCosButton">
+        <property name="text">
+         <string>cos</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="4">
+       <widget class="QPushButton" name="mASinButton">
+        <property name="text">
+         <string>asin</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="5">
+       <widget class="QPushButton" name="mATanButton">
+        <property name="text">
+         <string>atan</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="6">
+       <widget class="QPushButton" name="mCloseBracketPushButton">
+        <property name="text">
+         <string>)</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="5" column="0" colspan="2">
+    <widget class="QLabel" name="mFieldCalculatorExpressionLabel">
+     <property name="text">
+      <string>Field calculator expression:</string>
+     </property>
+    </widget>
+   </item>
+   <item row="6" column="0" colspan="4">
+    <widget class="QTextEdit" name="mExpressionTextEdit"/>
+   </item>
+   <item row="7" column="0" colspan="2">
+    <widget class="QDialogButtonBox" name="mButtonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>mButtonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>QgsFieldCalculatorBase</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>mButtonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>QgsFieldCalculatorBase</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

Modified: trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui	2009-09-29 14:52:50 UTC (rev 11734)
+++ trunk/qgis/src/ui/qgsvectorlayerpropertiesbase.ui	2009-09-30 07:14:54 UTC (rev 11735)
@@ -32,18 +32,9 @@
      <property name="spacing" >
       <number>3</number>
      </property>
-     <property name="leftMargin" >
+     <property name="margin" >
       <number>1</number>
      </property>
-     <property name="topMargin" >
-      <number>1</number>
-     </property>
-     <property name="rightMargin" >
-      <number>1</number>
-     </property>
-     <property name="bottomMargin" >
-      <number>1</number>
-     </property>
      <item>
       <widget class="QPushButton" name="pbnLoadDefaultStyle" >
        <property name="text" >
@@ -80,7 +71,7 @@
       <enum>Qt::Horizontal</enum>
      </property>
      <property name="standardButtons" >
-      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+      <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
      </property>
     </widget>
    </item>
@@ -102,7 +93,7 @@
       <enum>QTabWidget::Rounded</enum>
      </property>
      <property name="currentIndex" >
-      <number>3</number>
+      <number>0</number>
      </property>
      <widget class="QWidget" name="tab1" >
       <attribute name="title" >
@@ -167,10 +158,10 @@
           </item>
           <item row="3" column="2" >
            <widget class="QPushButton" name="pbnChangeSpatialRefSys" >
-            <property name="toolTip">
+            <property name="toolTip" >
              <string>Specify the coordinate reference system of the layer's geometry.</string>
             </property>
-            <property name="whatsThis">
+            <property name="whatsThis" >
              <string>Specify the coordinate reference system of the layer's geometry.</string>
             </property>
             <property name="text" >
@@ -190,18 +181,9 @@
           <bool>true</bool>
          </property>
          <layout class="QGridLayout" >
-          <property name="leftMargin" >
+          <property name="margin" >
            <number>11</number>
           </property>
-          <property name="topMargin" >
-           <number>11</number>
-          </property>
-          <property name="rightMargin" >
-           <number>11</number>
-          </property>
-          <property name="bottomMargin" >
-           <number>11</number>
-          </property>
           <item row="0" column="2" >
            <widget class="QLabel" name="textLabel1_2_2" >
             <property name="text" >
@@ -257,18 +239,9 @@
           <string>Subset</string>
          </property>
          <layout class="QGridLayout" >
-          <property name="leftMargin" >
+          <property name="margin" >
            <number>11</number>
           </property>
-          <property name="topMargin" >
-           <number>11</number>
-          </property>
-          <property name="rightMargin" >
-           <number>11</number>
-          </property>
-          <property name="bottomMargin" >
-           <number>11</number>
-          </property>
           <item row="0" column="0" colspan="2" >
            <widget class="QTextEdit" name="txtSubsetSQL" >
             <property name="enabled" >
@@ -290,7 +263,7 @@
             <property name="sizeType" >
              <enum>QSizePolicy::Expanding</enum>
             </property>
-            <property name="sizeHint" >
+            <property name="sizeHint" stdset="0" >
              <size>
               <width>480</width>
               <height>21</height>
@@ -428,18 +401,9 @@
        <string>Metadata</string>
       </attribute>
       <layout class="QGridLayout" >
-       <property name="leftMargin" >
+       <property name="margin" >
         <number>11</number>
        </property>
-       <property name="topMargin" >
-        <number>11</number>
-       </property>
-       <property name="rightMargin" >
-        <number>11</number>
-       </property>
-       <property name="bottomMargin" >
-        <number>11</number>
-       </property>
        <item row="0" column="0" >
         <widget class="QTextEdit" name="teMetadata" >
          <property name="lineWidth" >
@@ -518,12 +482,9 @@
       <attribute name="title" >
        <string>Attributes</string>
       </attribute>
-      <layout class="QVBoxLayout" >
-       <item>
-        <layout class="QHBoxLayout" >
-         <property name="sizeConstraint" >
-          <enum>QLayout::SetNoConstraint</enum>
-         </property>
+      <layout class="QGridLayout" name="gridLayout" >
+       <item row="0" column="0" >
+        <layout class="QHBoxLayout" name="horizontalLayout" >
          <item>
           <widget class="QToolButton" name="mAddAttributeButton" >
            <property name="sizePolicy" >
@@ -539,7 +500,8 @@
             <string/>
            </property>
            <property name="icon" >
-            <iconset>../xpm/new_attribute.png</iconset>
+            <iconset>
+             <normaloff>../xpm/new_attribute.png</normaloff>../xpm/new_attribute.png</iconset>
            </property>
            <property name="shortcut" >
             <string>Ctrl+N</string>
@@ -555,7 +517,8 @@
             <string/>
            </property>
            <property name="icon" >
-            <iconset>../xpm/delete_attribute.png</iconset>
+            <iconset>
+             <normaloff>../xpm/delete_attribute.png</normaloff>../xpm/delete_attribute.png</iconset>
            </property>
            <property name="shortcut" >
             <string>Ctrl+X</string>
@@ -579,21 +542,37 @@
           </widget>
          </item>
          <item>
+          <widget class="QToolButton" name="mCalculateFieldButton" >
+           <property name="toolTip" >
+            <string>Field calculator</string>
+           </property>
+           <property name="whatsThis" >
+            <string>Click to toggle table editing</string>
+           </property>
+           <property name="text" >
+            <string/>
+           </property>
+           <property name="checkable" >
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
           <spacer>
            <property name="orientation" >
             <enum>Qt::Horizontal</enum>
            </property>
-           <property name="sizeHint" >
+           <property name="sizeHint" stdset="0" >
             <size>
-             <width>40</width>
-             <height>20</height>
+             <width>658</width>
+             <height>19</height>
             </size>
            </property>
           </spacer>
          </item>
         </layout>
        </item>
-       <item>
+       <item row="1" column="0" >
         <widget class="QTableWidget" name="tblAttributes" >
          <property name="sizePolicy" >
           <sizepolicy vsizetype="Expanding" hsizetype="Expanding" >



More information about the QGIS-commit mailing list