mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-01 00:03:42 -05:00
[FEATURE]: Load/save queries created in the query builder. Added method columnRefNodes() in qgssearchtreenode and added some consts
git-svn-id: http://svn.osgeo.org/qgis/trunk@13571 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
61008a6753
commit
c143ca1cb5
@ -65,19 +65,19 @@ class QgsSearchTreeNode
|
|||||||
~QgsSearchTreeNode();
|
~QgsSearchTreeNode();
|
||||||
|
|
||||||
//! returns type of current node
|
//! returns type of current node
|
||||||
Type type();
|
Type type() const;
|
||||||
|
|
||||||
//! node value getters
|
//! node value getters
|
||||||
Operator op();
|
Operator op() const;
|
||||||
double number();
|
double number() const;
|
||||||
QString columnRef();
|
QString columnRef() const;
|
||||||
QString string();
|
QString string() const;
|
||||||
|
|
||||||
//! node value setters (type is set also)
|
//! node value setters (type is set also)
|
||||||
void setOp( Operator o );
|
void setOp( Operator o );
|
||||||
void setNumber( double number );
|
void setNumber( double number );
|
||||||
void setColumnRef( QString& str );
|
void setColumnRef( const QString& str );
|
||||||
void setString( QString& str );
|
void setString( const QString& str );
|
||||||
|
|
||||||
//! children
|
//! children
|
||||||
QgsSearchTreeNode* Left();
|
QgsSearchTreeNode* Left();
|
||||||
@ -107,6 +107,10 @@ class QgsSearchTreeNode
|
|||||||
//! @note added in 1.5
|
//! @note added in 1.5
|
||||||
QStringList referencedColumns();
|
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)
|
//! check whether there are any operators that need geometry (for area, length)
|
||||||
//! @note added in 1.5
|
//! @note added in 1.5
|
||||||
bool needsGeometry();
|
bool needsGeometry();
|
||||||
|
|||||||
@ -14,9 +14,16 @@
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QDomElement>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QSettings>
|
||||||
#include <QStandardItem>
|
#include <QStandardItem>
|
||||||
|
#include <QTextStream>
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
#include "qgsfield.h"
|
#include "qgsfield.h"
|
||||||
#include "qgssearchquerybuilder.h"
|
#include "qgssearchquerybuilder.h"
|
||||||
@ -43,6 +50,16 @@ QgsSearchQueryBuilder::QgsSearchQueryBuilder( QgsVectorLayer* layer,
|
|||||||
buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
|
buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
|
||||||
connect( pbn, SIGNAL( clicked() ), this, SLOT( on_btnClear_clicked() ) );
|
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
|
// disable unsupported operators
|
||||||
btnIn->setHidden( true );
|
btnIn->setHidden( true );
|
||||||
btnNotIn->setHidden( true );
|
btnNotIn->setHidden( true );
|
||||||
@ -327,3 +344,132 @@ void QgsSearchQueryBuilder::on_btnILike_clicked()
|
|||||||
txtSQL->insertPlainText( " ~ " );
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -87,6 +87,9 @@ class QgsSearchQueryBuilder : public QDialog, private Ui::QgsQueryBuilderBase
|
|||||||
*/
|
*/
|
||||||
void on_btnSampleValues_clicked();
|
void on_btnSampleValues_clicked();
|
||||||
|
|
||||||
|
void saveQuery();
|
||||||
|
void loadQuery();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|||||||
@ -228,25 +228,36 @@ QString QgsSearchTreeNode::makeSearchString()
|
|||||||
|
|
||||||
QStringList QgsSearchTreeNode::referencedColumns()
|
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 )
|
if ( mType == tOperator )
|
||||||
{
|
{
|
||||||
QStringList lst;
|
|
||||||
if ( mLeft )
|
if ( mLeft )
|
||||||
lst += mLeft->referencedColumns();
|
{
|
||||||
|
nodeList += mLeft->columnRefNodes();
|
||||||
|
}
|
||||||
if ( mRight )
|
if ( mRight )
|
||||||
lst += mRight->referencedColumns();
|
{
|
||||||
return lst.toSet().toList(); // make union and convert back to list
|
nodeList += mRight->columnRefNodes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( mType == tColumnRef )
|
else if ( mType == tColumnRef )
|
||||||
{
|
{
|
||||||
return QStringList( mText );
|
nodeList.push_back( this );
|
||||||
}
|
}
|
||||||
else
|
return nodeList;
|
||||||
{
|
|
||||||
// string or number - do nothing
|
|
||||||
return QStringList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsSearchTreeNode::needsGeometry()
|
bool QgsSearchTreeNode::needsGeometry()
|
||||||
|
|||||||
@ -103,19 +103,19 @@ class CORE_EXPORT QgsSearchTreeNode
|
|||||||
~QgsSearchTreeNode();
|
~QgsSearchTreeNode();
|
||||||
|
|
||||||
//! returns type of current node
|
//! returns type of current node
|
||||||
Type type() { return mType; }
|
Type type() const { return mType; }
|
||||||
|
|
||||||
//! node value getters
|
//! node value getters
|
||||||
Operator op() { return mOp; }
|
Operator op() const { return mOp; }
|
||||||
double number() { return mNumber; }
|
double number() const { return mNumber; }
|
||||||
QString columnRef() { return mText; }
|
QString columnRef() const { return mText; }
|
||||||
QString string() { return mText; }
|
QString string() const { return mText; }
|
||||||
|
|
||||||
//! node value setters (type is set also)
|
//! node value setters (type is set also)
|
||||||
void setOp( Operator op ) { mType = tOperator; mOp = op; }
|
void setOp( Operator op ) { mType = tOperator; mOp = op; }
|
||||||
void setNumber( double number ) { mType = tNumber; mNumber = number; }
|
void setNumber( double number ) { mType = tNumber; mNumber = number; }
|
||||||
void setColumnRef( QString& str ) { mType = tColumnRef; mText = str; }
|
void setColumnRef( const QString& str ) { mType = tColumnRef; mText = str; }
|
||||||
void setString( QString& str ) { mType = tString; mText = str; stripText(); }
|
void setString( const QString& str ) { mType = tString; mText = str; stripText(); }
|
||||||
|
|
||||||
//! children
|
//! children
|
||||||
QgsSearchTreeNode* Left() { return mLeft; }
|
QgsSearchTreeNode* Left() { return mLeft; }
|
||||||
@ -145,6 +145,10 @@ class CORE_EXPORT QgsSearchTreeNode
|
|||||||
//! @note added in 1.5
|
//! @note added in 1.5
|
||||||
QStringList referencedColumns();
|
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)
|
//! check whether there are any operators that need geometry (for area, length)
|
||||||
//! @note added in 1.5
|
//! @note added in 1.5
|
||||||
bool needsGeometry();
|
bool needsGeometry();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user