mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-16 00:03:12 -04: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();
|
||||
|
||||
//! 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 @@ class QgsSearchTreeNode
|
||||
//! @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();
|
||||
|
@ -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 @@ QgsSearchQueryBuilder::QgsSearchQueryBuilder( QgsVectorLayer* layer,
|
||||
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 @@ void QgsSearchQueryBuilder::on_btnILike_clicked()
|
||||
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 saveQuery();
|
||||
void loadQuery();
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
|
@ -228,25 +228,36 @@ QString QgsSearchTreeNode::makeSearchString()
|
||||
|
||||
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()
|
||||
|
@ -103,19 +103,19 @@ class CORE_EXPORT QgsSearchTreeNode
|
||||
~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 @@ class CORE_EXPORT QgsSearchTreeNode
|
||||
//! @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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user