[QGIS Commit] r13571 - in trunk/qgis: python/core src/app src/core

svn_qgis at osgeo.org svn_qgis at osgeo.org
Tue May 25 09:57:05 EDT 2010


Author: mhugent
Date: 2010-05-25 09:57:05 -0400 (Tue, 25 May 2010)
New Revision: 13571

Modified:
   trunk/qgis/python/core/qgssearchtreenode.sip
   trunk/qgis/src/app/qgssearchquerybuilder.cpp
   trunk/qgis/src/app/qgssearchquerybuilder.h
   trunk/qgis/src/core/qgssearchtreenode.cpp
   trunk/qgis/src/core/qgssearchtreenode.h
Log:
[FEATURE]: Load/save queries created in the query builder. Added method columnRefNodes() in qgssearchtreenode and added some consts

Modified: trunk/qgis/python/core/qgssearchtreenode.sip
===================================================================
--- trunk/qgis/python/core/qgssearchtreenode.sip	2010-05-25 11:29:12 UTC (rev 13570)
+++ trunk/qgis/python/core/qgssearchtreenode.sip	2010-05-25 13:57:05 UTC (rev 13571)
@@ -65,19 +65,19 @@
     ~QgsSearchTreeNode();
 
     //! returns type of current node
-    Type type();
+    Type type() const;
 
     //! node value getters
-    Operator op();
-    double number();
-    QString columnRef();
-    QString string();
+    Operator op() const;
+    double number() const;
+    QString columnRef() const;
+    QString string() const;
 
     //! node value setters (type is set also)
     void setOp( Operator o );
     void setNumber( double number );
-    void setColumnRef( QString& str );
-    void setString( QString& str );
+    void setColumnRef( const QString& str );
+    void setString( const QString& str );
 
     //! children
     QgsSearchTreeNode* Left();
@@ -107,6 +107,10 @@
     //! @note added in 1.5
     QStringList referencedColumns();
 
+    //! return a list of all attribute nodes
+    //! @note added in 1.5
+    QList<QgsSearchTreeNode*> columnRefNodes();
+
     //! check whether there are any operators that need geometry (for area, length)
     //! @note added in 1.5
     bool needsGeometry();

Modified: trunk/qgis/src/app/qgssearchquerybuilder.cpp
===================================================================
--- trunk/qgis/src/app/qgssearchquerybuilder.cpp	2010-05-25 11:29:12 UTC (rev 13570)
+++ trunk/qgis/src/app/qgssearchquerybuilder.cpp	2010-05-25 13:57:05 UTC (rev 13571)
@@ -14,9 +14,16 @@
  ***************************************************************************/
 /* $Id$ */
 
+#include <QDomDocument>
+#include <QDomElement>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QInputDialog>
 #include <QListView>
 #include <QMessageBox>
+#include <QSettings>
 #include <QStandardItem>
+#include <QTextStream>
 #include "qgsfeature.h"
 #include "qgsfield.h"
 #include "qgssearchquerybuilder.h"
@@ -43,6 +50,16 @@
   buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
   connect( pbn, SIGNAL( clicked() ), this, SLOT( on_btnClear_clicked() ) );
 
+  pbn = new QPushButton( tr( "&Save..." ) );
+  buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
+  pbn->setToolTip( tr( "Save query to an xml file" ) );
+  connect( pbn, SIGNAL( clicked() ), this, SLOT( saveQuery() ) );
+
+  pbn = new QPushButton( tr( "&Load..." ) );
+  buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
+  pbn->setToolTip( tr( "Load query from xml file" ) );
+  connect( pbn, SIGNAL( clicked() ), this, SLOT( loadQuery() ) );
+
   // disable unsupported operators
   btnIn->setHidden( true );
   btnNotIn->setHidden( true );
@@ -327,3 +344,132 @@
   txtSQL->insertPlainText( " ~ " );
 }
 
+void QgsSearchQueryBuilder::saveQuery()
+{
+  QSettings s;
+  QString lastQueryFileDir = s.value( "/UI/lastQueryFileDir", "" ).toString();
+  //save as qqt (QGIS query file)
+  QString saveFileName = QFileDialog::getSaveFileName( 0, tr( "Save query to file" ), lastQueryFileDir, "*.qqf" );
+  if ( saveFileName.isNull() )
+  {
+    return;
+  }
+
+  QFile saveFile( saveFileName );
+  if ( !saveFile.open( QIODevice::WriteOnly ) )
+  {
+    QMessageBox::critical( 0, tr( "Error" ), tr( "Could not open file for writing" ) );
+    return;
+  }
+
+  QDomDocument xmlDoc;
+  QDomElement queryElem = xmlDoc.createElement( "Query" );
+  QDomText queryTextNode = xmlDoc.createTextNode( txtSQL->toPlainText() );
+  queryElem.appendChild( queryTextNode );
+  xmlDoc.appendChild( queryElem );
+
+  QTextStream fileStream( &saveFile );
+  xmlDoc.save( fileStream, 2 );
+
+  QFileInfo fi( saveFile );
+  s.setValue( "/UI/lastQueryFileDir", fi.absolutePath() );
+}
+
+void QgsSearchQueryBuilder::loadQuery()
+{
+  QSettings s;
+  QString lastQueryFileDir = s.value( "/UI/lastQueryFileDir", "" ).toString();
+
+  QString queryFileName = QFileDialog::getOpenFileName( 0, tr( "Load query from file" ), lastQueryFileDir, tr( "Query files" ) + "(*.qqf);;" + tr( "All files" ) + "(*)" );
+  if ( queryFileName.isNull() )
+  {
+    return;
+  }
+
+  QFile queryFile( queryFileName );
+  if ( !queryFile.open( QIODevice::ReadOnly ) )
+  {
+    QMessageBox::critical( 0, tr( "Error" ), tr( "Could not open file for reading" ) );
+    return;
+  }
+  QDomDocument queryDoc;
+  if ( !queryDoc.setContent( &queryFile ) )
+  {
+    QMessageBox::critical( 0, tr( "Error" ), tr( "File is not a valid xml document" ) );
+    return;
+  }
+
+  QDomElement queryElem = queryDoc.firstChildElement( "Query" );
+  if ( queryElem.isNull() )
+  {
+    QMessageBox::critical( 0, tr( "Error" ), tr( "File is not a valid query document" ) );
+    return;
+  }
+
+  QString query = queryElem.text();
+
+  //todo: test if all the attributes are valid
+  QgsSearchString search;
+  if ( !search.setString( query ) )
+  {
+    QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
+    return;
+  }
+
+  QgsSearchTreeNode* searchTree = search.tree();
+  if ( !searchTree )
+  {
+    QMessageBox::critical( this, tr( "Error creating search tree" ), search.parserErrorMsg() );
+    return;
+  }
+
+  QStringList attributes = searchTree->referencedColumns();
+  QMap< QString, QString> attributesToReplace;
+  QStringList existingAttributes;
+
+  //get all existing fields
+  QMap<QString, int>::const_iterator fieldIt = mFieldMap.constBegin();
+  for ( ; fieldIt != mFieldMap.constEnd(); ++fieldIt )
+  {
+    existingAttributes.push_back( fieldIt.key() );
+  }
+
+  //if a field does not exist, ask what field should be used instead
+  QStringList::const_iterator attIt = attributes.constBegin();
+  for ( ; attIt != attributes.constEnd(); ++attIt )
+  {
+    //test if attribute is there
+    if ( !mFieldMap.contains( *attIt ) )
+    {
+      bool ok;
+      QString replaceAttribute = QInputDialog::getItem( 0, tr( "Select attribute" ), tr( "There is no attribute '%1' in the current vector layer. Please select an existing attribute" ).arg( *attIt ),
+                                 existingAttributes, 0, false, &ok );
+      if ( !ok || replaceAttribute.isEmpty() )
+      {
+        return;
+      }
+      attributesToReplace.insert( *attIt, replaceAttribute );
+    }
+  }
+
+  //Now replace all the string in the query
+  QList<QgsSearchTreeNode*> columnRefList = searchTree->columnRefNodes();
+  QList<QgsSearchTreeNode*>::iterator columnIt = columnRefList.begin();
+  for ( ; columnIt != columnRefList.end(); ++columnIt )
+  {
+    QMap< QString, QString>::const_iterator replaceIt = attributesToReplace.find(( *columnIt )->columnRef() );
+    if ( replaceIt != attributesToReplace.constEnd() )
+    {
+      ( *columnIt )->setColumnRef( replaceIt.value() );
+    }
+  }
+
+  txtSQL->clear();
+  QString newQueryText = query;
+  if ( attributesToReplace.size() > 0 )
+  {
+    newQueryText = searchTree->makeSearchString();
+  }
+  txtSQL->insertPlainText( newQueryText );
+}
+

Modified: trunk/qgis/src/app/qgssearchquerybuilder.h
===================================================================
--- trunk/qgis/src/app/qgssearchquerybuilder.h	2010-05-25 11:29:12 UTC (rev 13570)
+++ trunk/qgis/src/app/qgssearchquerybuilder.h	2010-05-25 13:57:05 UTC (rev 13571)
@@ -87,6 +87,9 @@
      */
     void on_btnSampleValues_clicked();
 
+    void saveQuery();
+    void loadQuery();
+
   private:
 
     /*!

Modified: trunk/qgis/src/core/qgssearchtreenode.cpp
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.cpp	2010-05-25 11:29:12 UTC (rev 13570)
+++ trunk/qgis/src/core/qgssearchtreenode.cpp	2010-05-25 13:57:05 UTC (rev 13571)
@@ -228,25 +228,36 @@
 
 QStringList QgsSearchTreeNode::referencedColumns()
 {
+  QList<QgsSearchTreeNode*> columnNodeList = columnRefNodes();
+  QSet<QString> columnStringSet;
+
+  QList<QgsSearchTreeNode*>::const_iterator nodeIt = columnNodeList.constBegin();
+  for ( ; nodeIt != columnNodeList.constEnd(); ++nodeIt )
+  {
+    columnStringSet.insert(( *nodeIt )->columnRef() );
+  }
+  return columnStringSet.toList();
+}
+
+QList<QgsSearchTreeNode*> QgsSearchTreeNode::columnRefNodes()
+{
+  QList<QgsSearchTreeNode*> nodeList;
   if ( mType == tOperator )
   {
-    QStringList lst;
     if ( mLeft )
-      lst += mLeft->referencedColumns();
+    {
+      nodeList += mLeft->columnRefNodes();
+    }
     if ( mRight )
-      lst += mRight->referencedColumns();
-    return lst.toSet().toList(); // make union and convert back to list
+    {
+      nodeList += mRight->columnRefNodes();
+    }
   }
   else if ( mType == tColumnRef )
   {
-    return QStringList( mText );
+    nodeList.push_back( this );
   }
-  else
-  {
-    // string or number - do nothing
-    return QStringList();
-  }
-
+  return nodeList;
 }
 
 bool QgsSearchTreeNode::needsGeometry()

Modified: trunk/qgis/src/core/qgssearchtreenode.h
===================================================================
--- trunk/qgis/src/core/qgssearchtreenode.h	2010-05-25 11:29:12 UTC (rev 13570)
+++ trunk/qgis/src/core/qgssearchtreenode.h	2010-05-25 13:57:05 UTC (rev 13571)
@@ -103,19 +103,19 @@
     ~QgsSearchTreeNode();
 
     //! returns type of current node
-    Type type()   { return mType; }
+    Type type() const  { return mType; }
 
     //! node value getters
-    Operator op() { return mOp; }
-    double number() { return mNumber; }
-    QString columnRef() { return mText; }
-    QString string() { return mText; }
+    Operator op() const { return mOp; }
+    double number() const { return mNumber; }
+    QString columnRef() const { return mText; }
+    QString string() const { return mText; }
 
     //! node value setters (type is set also)
     void setOp( Operator op )         { mType = tOperator;  mOp = op; }
     void setNumber( double number )   { mType = tNumber;    mNumber = number; }
-    void setColumnRef( QString& str ) { mType = tColumnRef; mText = str; }
-    void setString( QString& str )    { mType = tString;    mText = str; stripText(); }
+    void setColumnRef( const QString& str ) { mType = tColumnRef; mText = str; }
+    void setString( const QString& str )    { mType = tString;    mText = str; stripText(); }
 
     //! children
     QgsSearchTreeNode* Left()  { return mLeft;  }
@@ -145,6 +145,10 @@
     //! @note added in 1.5
     QStringList referencedColumns();
 
+    //! return a list of all attribute nodes
+    //! @note added in 1.5
+    QList<QgsSearchTreeNode*> columnRefNodes();
+
     //! check whether there are any operators that need geometry (for area, length)
     //! @note added in 1.5
     bool needsGeometry();



More information about the QGIS-commit mailing list