[QGIS Commit] r14867 - in trunk/qgis: python/gui src/app src/gui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Wed Dec 8 12:38:01 EST 2010
Author: jef
Date: 2010-12-08 09:38:01 -0800 (Wed, 08 Dec 2010)
New Revision: 14867
Added:
trunk/qgis/python/gui/qgssearchquerybuilder.sip
trunk/qgis/src/gui/qgssearchquerybuilder.cpp
trunk/qgis/src/gui/qgssearchquerybuilder.h
Removed:
trunk/qgis/src/app/qgssearchquerybuilder.cpp
trunk/qgis/src/app/qgssearchquerybuilder.h
Modified:
trunk/qgis/python/gui/gui.sip
trunk/qgis/src/app/CMakeLists.txt
trunk/qgis/src/gui/CMakeLists.txt
Log:
move QgsSearchQuery builder from app to gui
Modified: trunk/qgis/python/gui/gui.sip
===================================================================
--- trunk/qgis/python/gui/gui.sip 2010-12-08 17:23:15 UTC (rev 14866)
+++ trunk/qgis/python/gui/gui.sip 2010-12-08 17:38:01 UTC (rev 14867)
@@ -32,5 +32,6 @@
%Include qgsrubberband.sip
%Include qgstextannotationitem.sip
%Include qgsvertexmarker.sip
+%Include qgssearchquerybuilder.sip
%Include symbology-ng-gui.sip
Added: trunk/qgis/python/gui/qgssearchquerybuilder.sip
===================================================================
--- trunk/qgis/python/gui/qgssearchquerybuilder.sip (rev 0)
+++ trunk/qgis/python/gui/qgssearchquerybuilder.sip 2010-12-08 17:38:01 UTC (rev 14867)
@@ -0,0 +1,16 @@
+class QgsSearchQueryBuilder : QDialog
+{
+%TypeHeaderCode
+#include <qgssearchquerybuilder.h>
+%End
+
+ public:
+ QgsSearchQueryBuilder( QgsVectorLayer* layer, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
+ ~QgsSearchQueryBuilder();
+
+ //! returns newly created search string
+ QString searchString();
+
+ //! change search string shown in text field
+ void setSearchString( QString searchString );
+};
Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt 2010-12-08 17:23:15 UTC (rev 14866)
+++ trunk/qgis/src/app/CMakeLists.txt 2010-12-08 17:38:01 UTC (rev 14867)
@@ -78,7 +78,6 @@
qgsprojectproperties.cpp
qgsrastercalcdialog.cpp
qgsrasterlayerproperties.cpp
- qgssearchquerybuilder.cpp
qgstextannotationdialog.cpp
qgswmssourceselect.cpp
qgsshortcutsmanager.cpp
@@ -214,7 +213,6 @@
qgsprojectproperties.h
qgsrastercalcdialog.h
qgsrasterlayerproperties.h
- qgssearchquerybuilder.h
qgstextannotationdialog.h
qgswmssourceselect.h
qgssinglesymboldialog.h
Deleted: trunk/qgis/src/app/qgssearchquerybuilder.cpp
===================================================================
--- trunk/qgis/src/app/qgssearchquerybuilder.cpp 2010-12-08 17:23:15 UTC (rev 14866)
+++ trunk/qgis/src/app/qgssearchquerybuilder.cpp 2010-12-08 17:38:01 UTC (rev 14867)
@@ -1,484 +0,0 @@
-/***************************************************************************
- qgssearchquerybuilder.cpp - Query builder for search strings
- ----------------------
- begin : March 2006
- copyright : (C) 2006 by Martin Dobias
- email : wonder.sk at gmail dot com
- ***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-/* $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"
-#include "qgssearchstring.h"
-#include "qgssearchtreenode.h"
-#include "qgsvectordataprovider.h"
-#include "qgsvectorlayer.h"
-#include "qgslogger.h"
-
-QgsSearchQueryBuilder::QgsSearchQueryBuilder( QgsVectorLayer* layer,
- QWidget *parent, Qt::WFlags fl )
- : QDialog( parent, fl ), mLayer( layer )
-{
- setupUi( this );
- setupListViews();
-
- setWindowTitle( tr( "Search query builder" ) );
-
- QPushButton *pbn = new QPushButton( tr( "&Test" ) );
- buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
- connect( pbn, SIGNAL( clicked() ), this, SLOT( on_btnTest_clicked() ) );
-
- pbn = new QPushButton( tr( "&Clear" ) );
- 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() ) );
-
- lblDataUri->setText( layer->name() );
- populateFields();
-}
-
-QgsSearchQueryBuilder::~QgsSearchQueryBuilder()
-{
-}
-
-
-void QgsSearchQueryBuilder::populateFields()
-{
- QgsDebugMsg( "entering." );
- QRegExp reQuote( "[A-Za-z_][A-Za-z0-9_]*" );
- const QgsFieldMap& fields = mLayer->pendingFields();
- for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
- {
- QString fieldName = it->name();
- mFieldMap[fieldName] = it.key();
- if ( !reQuote.exactMatch( fieldName ) ) // quote if necessary
- fieldName = QgsSearchTreeNode::quotedColumnRef( fieldName );
- QStandardItem *myItem = new QStandardItem( fieldName );
- myItem->setEditable( false );
- mModelFields->insertRow( mModelFields->rowCount(), myItem );
- }
-}
-
-void QgsSearchQueryBuilder::setupListViews()
-{
- QgsDebugMsg( "entering." );
- //Models
- mModelFields = new QStandardItemModel();
- mModelValues = new QStandardItemModel();
- lstFields->setModel( mModelFields );
- lstValues->setModel( mModelValues );
- // Modes
- lstFields->setViewMode( QListView::ListMode );
- lstValues->setViewMode( QListView::ListMode );
- lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
- lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
- // Performance tip since Qt 4.1
- lstFields->setUniformItemSizes( true );
- lstValues->setUniformItemSizes( true );
-}
-
-void QgsSearchQueryBuilder::getFieldValues( int limit )
-{
- if ( !mLayer )
- {
- return;
- }
- // clear the values list
- mModelValues->clear();
-
- // determine the field type
- QString fieldName = mModelFields->data( lstFields->currentIndex() ).toString();
- int fieldIndex = mFieldMap[fieldName];
- QgsField field = mLayer->pendingFields()[fieldIndex];//provider->fields()[fieldIndex];
- bool numeric = ( field.type() == QVariant::Int || field.type() == QVariant::Double );
-
- QgsFeature feat;
- QString value;
-
- QgsAttributeList attrs;
- attrs.append( fieldIndex );
-
- mLayer->select( attrs, QgsRectangle(), false );
-
- lstValues->setCursor( Qt::WaitCursor );
- // Block for better performance
- mModelValues->blockSignals( true );
- lstValues->setUpdatesEnabled( false );
-
- /**MH: keep already inserted values in a set. Querying is much faster compared to QStandardItemModel::findItems*/
- QSet<QString> insertedValues;
-
- while ( mLayer->nextFeature( feat ) &&
- ( limit == 0 || mModelValues->rowCount() != limit ) )
- {
- const QgsAttributeMap& attributes = feat.attributeMap();
- value = attributes[fieldIndex].toString();
-
- if ( !numeric )
- {
- // put string in single quotes and escape single quotes in the string
- value = "'" + value.replace( "'", "''" ) + "'";
- }
-
- // add item only if it's not there already
- if ( !insertedValues.contains( value ) )
- {
- QStandardItem *myItem = new QStandardItem( value );
- myItem->setEditable( false );
- mModelValues->insertRow( mModelValues->rowCount(), myItem );
- insertedValues.insert( value );
- }
- }
- // Unblock for normal use
- mModelValues->blockSignals( false );
- lstValues->setUpdatesEnabled( true );
- // TODO: already sorted, signal emit to refresh model
- mModelValues->sort( 0 );
- lstValues->setCursor( Qt::ArrowCursor );
-}
-
-void QgsSearchQueryBuilder::on_btnSampleValues_clicked()
-{
- getFieldValues( 25 );
-}
-
-void QgsSearchQueryBuilder::on_btnGetAllValues_clicked()
-{
- getFieldValues( 0 );
-}
-
-void QgsSearchQueryBuilder::on_btnTest_clicked()
-{
- long count = countRecords( txtSQL->toPlainText() );
-
- // error?
- if ( count == -1 )
- return;
-
- QMessageBox::information( this, tr( "Search results" ), tr( "Found %n matching feature(s).", "test result", count ) );
-}
-
-// This method tests the number of records that would be returned
-long QgsSearchQueryBuilder::countRecords( QString searchString )
-{
- QgsSearchString search;
- if ( !search.setString( searchString ) )
- {
- QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
- return -1;
- }
-
- QgsSearchTreeNode* searchTree = search.tree();
- if ( searchTree == NULL )
- {
- // entered empty search string
- return mLayer->featureCount();
- }
-
- bool fetchGeom = searchTree->needsGeometry();
-
- QApplication::setOverrideCursor( Qt::WaitCursor );
-
- int count = 0;
- QgsFeature feat;
- QgsVectorDataProvider* provider = mLayer->dataProvider();
- const QgsFieldMap& fields = provider->fields();
- QgsAttributeList allAttributes = provider->attributeIndexes();
-
- provider->select( allAttributes, QgsRectangle(), fetchGeom );
-
- while ( provider->nextFeature( feat ) )
- {
- if ( searchTree->checkAgainst( fields, feat ) )
- {
- count++;
- }
-
- // check if there were errors during evaulating
- if ( searchTree->hasError() )
- break;
- }
-
- QApplication::restoreOverrideCursor();
-
- return count;
-}
-
-
-void QgsSearchQueryBuilder::on_btnOk_clicked()
-{
- // if user hits Ok and there is no query, skip the validation
- if ( txtSQL->toPlainText().trimmed().length() > 0 )
- {
- accept();
- return;
- }
-
- // test the query to see if it will result in a valid layer
- long numRecs = countRecords( txtSQL->toPlainText() );
- if ( numRecs == -1 )
- {
- // error shown in countRecords
- }
- else if ( numRecs == 0 )
- {
- QMessageBox::warning( this, tr( "No Records" ), tr( "The query you specified results in zero records being returned." ) );
- }
- else
- {
- accept();
- }
-
-}
-
-void QgsSearchQueryBuilder::on_btnEqual_clicked()
-{
- txtSQL->insertPlainText( " = " );
-}
-
-void QgsSearchQueryBuilder::on_btnLessThan_clicked()
-{
- txtSQL->insertPlainText( " < " );
-}
-
-void QgsSearchQueryBuilder::on_btnGreaterThan_clicked()
-{
- txtSQL->insertPlainText( " > " );
-}
-
-void QgsSearchQueryBuilder::on_btnPct_clicked()
-{
- txtSQL->insertPlainText( "%" );
-}
-
-void QgsSearchQueryBuilder::on_btnIn_clicked()
-{
- txtSQL->insertPlainText( " IN " );
-}
-
-void QgsSearchQueryBuilder::on_btnNotIn_clicked()
-{
- txtSQL->insertPlainText( " NOT IN " );
-}
-
-void QgsSearchQueryBuilder::on_btnLike_clicked()
-{
- txtSQL->insertPlainText( " LIKE " );
-}
-
-QString QgsSearchQueryBuilder::searchString()
-{
- return txtSQL->toPlainText();
-}
-
-void QgsSearchQueryBuilder::setSearchString( QString searchString )
-{
- txtSQL->setPlainText( searchString );
-}
-
-void QgsSearchQueryBuilder::on_lstFields_doubleClicked( const QModelIndex &index )
-{
- txtSQL->insertPlainText( mModelFields->data( index ).toString() );
-}
-
-void QgsSearchQueryBuilder::on_lstValues_doubleClicked( const QModelIndex &index )
-{
- txtSQL->insertPlainText( mModelValues->data( index ).toString() );
-}
-
-void QgsSearchQueryBuilder::on_btnLessEqual_clicked()
-{
- txtSQL->insertPlainText( " <= " );
-}
-
-void QgsSearchQueryBuilder::on_btnGreaterEqual_clicked()
-{
- txtSQL->insertPlainText( " >= " );
-}
-
-void QgsSearchQueryBuilder::on_btnNotEqual_clicked()
-{
- txtSQL->insertPlainText( " != " );
-}
-
-void QgsSearchQueryBuilder::on_btnAnd_clicked()
-{
- txtSQL->insertPlainText( " AND " );
-}
-
-void QgsSearchQueryBuilder::on_btnNot_clicked()
-{
- txtSQL->insertPlainText( " NOT " );
-}
-
-void QgsSearchQueryBuilder::on_btnOr_clicked()
-{
- txtSQL->insertPlainText( " OR " );
-}
-
-void QgsSearchQueryBuilder::on_btnClear_clicked()
-{
- txtSQL->clear();
-}
-
-void QgsSearchQueryBuilder::on_btnILike_clicked()
-{
- txtSQL->insertPlainText( " ILIKE " );
-}
-
-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 );
-}
-
Deleted: trunk/qgis/src/app/qgssearchquerybuilder.h
===================================================================
--- trunk/qgis/src/app/qgssearchquerybuilder.h 2010-12-08 17:23:15 UTC (rev 14866)
+++ trunk/qgis/src/app/qgssearchquerybuilder.h 2010-12-08 17:38:01 UTC (rev 14867)
@@ -1,129 +0,0 @@
-/***************************************************************************
- qgssearchquerybuilder.h - Query builder for search strings
- ----------------------
- begin : March 2006
- copyright : (C) 2006 by Martin Dobias
- email : wonder.sk at gmail dot com
- ***************************************************************************
- * *
- * 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. *
- * *
- ***************************************************************************/
-/* $Id$ */
-
-#ifndef QGSSEARCHQUERYBUILDER_H
-#define QGSSEARCHQUERYBUILDER_H
-
-#include <map>
-#include <vector>
-#include <QStandardItemModel>
-#include <QModelIndex>
-
-#include "ui_qgsquerybuilderbase.h"
-#include "qgisgui.h"
-
-class QgsField;
-class QgsVectorLayer;
-
-/*!
- * \class QgsSearchQueryBuilder
- * \brief Query Builder for search strings
- *
- */
-class QgsSearchQueryBuilder : public QDialog, private Ui::QgsQueryBuilderBase
-{
- Q_OBJECT
-
- public:
- //! Constructor - takes pointer to vector layer as a parameter
- QgsSearchQueryBuilder( QgsVectorLayer* layer, QWidget *parent = 0,
- Qt::WFlags fl = QgisGui::ModalDialogFlags );
-
- ~QgsSearchQueryBuilder();
-
- //! returns newly created search string
- QString searchString();
-
- //! change search string shown in text field
- void setSearchString( QString searchString );
-
- public slots:
- void on_btnEqual_clicked();
- void on_btnOk_clicked();
- void on_btnLessThan_clicked();
- void on_btnGreaterThan_clicked();
- void on_btnLike_clicked();
- void on_btnILike_clicked();
- void on_btnPct_clicked();
- void on_btnIn_clicked();
- void on_btnNotIn_clicked();
-
- void on_lstFields_doubleClicked( const QModelIndex &index );
- void on_lstValues_doubleClicked( const QModelIndex &index );
- void on_btnLessEqual_clicked();
- void on_btnGreaterEqual_clicked();
- void on_btnNotEqual_clicked();
- void on_btnAnd_clicked();
- void on_btnNot_clicked();
- void on_btnOr_clicked();
- void on_btnClear_clicked();
-
- /*! Test the constructed search string to see if it's correct.
- * The number of rows that would be returned is displayed in a message box.
- * @param showResults If true, the results are displayed in a QMessageBox
- */
- void on_btnTest_clicked();
-
- /*!
- * Get all distinct values for the field. Values are inserted
- * into the value list box
- */
- void on_btnGetAllValues_clicked();
-
- /*!
- * Get sample distinct values for the selected field. The sample size is
- * limited to an arbitrary value (currently set to 25). The values
- * are inserted into the values list box.
- */
- void on_btnSampleValues_clicked();
-
- void saveQuery();
- void loadQuery();
-
- private:
-
- /*!
- * Populate the field list for the selected table
- */
- void populateFields();
- /*!
- * Setup models for listviews
- */
- void setupListViews();
-
- /*! Get the number of records that would be returned by the current SQL
- * @return Number of records or -1 if an error was encountered
- */
- long countRecords( QString sql );
-
- /*!
- * populates list box with values of selected field
- * @param limit if not zero, inserts only this count of values
- */
- void getFieldValues( int limit );
-
- private:
-
- //! Layer for which is the query builder opened
- QgsVectorLayer* mLayer;
- //! Map that holds field information, keyed by field name
- QMap<QString, int> mFieldMap;
- //! Model for fields ListView
- QStandardItemModel *mModelFields;
- //! Model for values ListView
- QStandardItemModel *mModelValues;
-};
-#endif //QGSSEARCHQUERYBUILDER_H
Modified: trunk/qgis/src/gui/CMakeLists.txt
===================================================================
--- trunk/qgis/src/gui/CMakeLists.txt 2010-12-08 17:23:15 UTC (rev 14866)
+++ trunk/qgis/src/gui/CMakeLists.txt 2010-12-08 17:38:01 UTC (rev 14867)
@@ -55,6 +55,7 @@
qgstextannotationitem.cpp
qgsvertexmarker.cpp
qgsludialog.cpp
+qgssearchquerybuilder.cpp
)
SET(QGIS_GUI_MOC_HDRS
@@ -98,6 +99,7 @@
qgsludialog.h
qgsprojectbadlayerguihandler.h
qgslonglongvalidator.h
+qgssearchquerybuilder.h
)
QT4_WRAP_CPP(QGIS_GUI_MOC_SRCS ${QGIS_GUI_MOC_HDRS})
@@ -187,12 +189,14 @@
qgsrubberband.h
qgsvertexmarker.h
qgsmaptip.h
+qgssearchquerybuilder.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsdetaileditemwidgetbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgscredentialdialog.h
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsprojectionselectorbase.h
+${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsquerybuilderbase.h
)
Copied: trunk/qgis/src/gui/qgssearchquerybuilder.cpp (from rev 14860, trunk/qgis/src/app/qgssearchquerybuilder.cpp)
===================================================================
--- trunk/qgis/src/gui/qgssearchquerybuilder.cpp (rev 0)
+++ trunk/qgis/src/gui/qgssearchquerybuilder.cpp 2010-12-08 17:38:01 UTC (rev 14867)
@@ -0,0 +1,484 @@
+/***************************************************************************
+ qgssearchquerybuilder.cpp - Query builder for search strings
+ ----------------------
+ begin : March 2006
+ copyright : (C) 2006 by Martin Dobias
+ email : wonder.sk at gmail dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+/* $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"
+#include "qgssearchstring.h"
+#include "qgssearchtreenode.h"
+#include "qgsvectordataprovider.h"
+#include "qgsvectorlayer.h"
+#include "qgslogger.h"
+
+QgsSearchQueryBuilder::QgsSearchQueryBuilder( QgsVectorLayer* layer,
+ QWidget *parent, Qt::WFlags fl )
+ : QDialog( parent, fl ), mLayer( layer )
+{
+ setupUi( this );
+ setupListViews();
+
+ setWindowTitle( tr( "Search query builder" ) );
+
+ QPushButton *pbn = new QPushButton( tr( "&Test" ) );
+ buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
+ connect( pbn, SIGNAL( clicked() ), this, SLOT( on_btnTest_clicked() ) );
+
+ pbn = new QPushButton( tr( "&Clear" ) );
+ 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() ) );
+
+ lblDataUri->setText( layer->name() );
+ populateFields();
+}
+
+QgsSearchQueryBuilder::~QgsSearchQueryBuilder()
+{
+}
+
+
+void QgsSearchQueryBuilder::populateFields()
+{
+ QgsDebugMsg( "entering." );
+ QRegExp reQuote( "[A-Za-z_][A-Za-z0-9_]*" );
+ const QgsFieldMap& fields = mLayer->pendingFields();
+ for ( QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it )
+ {
+ QString fieldName = it->name();
+ mFieldMap[fieldName] = it.key();
+ if ( !reQuote.exactMatch( fieldName ) ) // quote if necessary
+ fieldName = QgsSearchTreeNode::quotedColumnRef( fieldName );
+ QStandardItem *myItem = new QStandardItem( fieldName );
+ myItem->setEditable( false );
+ mModelFields->insertRow( mModelFields->rowCount(), myItem );
+ }
+}
+
+void QgsSearchQueryBuilder::setupListViews()
+{
+ QgsDebugMsg( "entering." );
+ //Models
+ mModelFields = new QStandardItemModel();
+ mModelValues = new QStandardItemModel();
+ lstFields->setModel( mModelFields );
+ lstValues->setModel( mModelValues );
+ // Modes
+ lstFields->setViewMode( QListView::ListMode );
+ lstValues->setViewMode( QListView::ListMode );
+ lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
+ lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
+ // Performance tip since Qt 4.1
+ lstFields->setUniformItemSizes( true );
+ lstValues->setUniformItemSizes( true );
+}
+
+void QgsSearchQueryBuilder::getFieldValues( int limit )
+{
+ if ( !mLayer )
+ {
+ return;
+ }
+ // clear the values list
+ mModelValues->clear();
+
+ // determine the field type
+ QString fieldName = mModelFields->data( lstFields->currentIndex() ).toString();
+ int fieldIndex = mFieldMap[fieldName];
+ QgsField field = mLayer->pendingFields()[fieldIndex];//provider->fields()[fieldIndex];
+ bool numeric = ( field.type() == QVariant::Int || field.type() == QVariant::Double );
+
+ QgsFeature feat;
+ QString value;
+
+ QgsAttributeList attrs;
+ attrs.append( fieldIndex );
+
+ mLayer->select( attrs, QgsRectangle(), false );
+
+ lstValues->setCursor( Qt::WaitCursor );
+ // Block for better performance
+ mModelValues->blockSignals( true );
+ lstValues->setUpdatesEnabled( false );
+
+ /**MH: keep already inserted values in a set. Querying is much faster compared to QStandardItemModel::findItems*/
+ QSet<QString> insertedValues;
+
+ while ( mLayer->nextFeature( feat ) &&
+ ( limit == 0 || mModelValues->rowCount() != limit ) )
+ {
+ const QgsAttributeMap& attributes = feat.attributeMap();
+ value = attributes[fieldIndex].toString();
+
+ if ( !numeric )
+ {
+ // put string in single quotes and escape single quotes in the string
+ value = "'" + value.replace( "'", "''" ) + "'";
+ }
+
+ // add item only if it's not there already
+ if ( !insertedValues.contains( value ) )
+ {
+ QStandardItem *myItem = new QStandardItem( value );
+ myItem->setEditable( false );
+ mModelValues->insertRow( mModelValues->rowCount(), myItem );
+ insertedValues.insert( value );
+ }
+ }
+ // Unblock for normal use
+ mModelValues->blockSignals( false );
+ lstValues->setUpdatesEnabled( true );
+ // TODO: already sorted, signal emit to refresh model
+ mModelValues->sort( 0 );
+ lstValues->setCursor( Qt::ArrowCursor );
+}
+
+void QgsSearchQueryBuilder::on_btnSampleValues_clicked()
+{
+ getFieldValues( 25 );
+}
+
+void QgsSearchQueryBuilder::on_btnGetAllValues_clicked()
+{
+ getFieldValues( 0 );
+}
+
+void QgsSearchQueryBuilder::on_btnTest_clicked()
+{
+ long count = countRecords( txtSQL->toPlainText() );
+
+ // error?
+ if ( count == -1 )
+ return;
+
+ QMessageBox::information( this, tr( "Search results" ), tr( "Found %n matching feature(s).", "test result", count ) );
+}
+
+// This method tests the number of records that would be returned
+long QgsSearchQueryBuilder::countRecords( QString searchString )
+{
+ QgsSearchString search;
+ if ( !search.setString( searchString ) )
+ {
+ QMessageBox::critical( this, tr( "Search string parsing error" ), search.parserErrorMsg() );
+ return -1;
+ }
+
+ QgsSearchTreeNode* searchTree = search.tree();
+ if ( searchTree == NULL )
+ {
+ // entered empty search string
+ return mLayer->featureCount();
+ }
+
+ bool fetchGeom = searchTree->needsGeometry();
+
+ QApplication::setOverrideCursor( Qt::WaitCursor );
+
+ int count = 0;
+ QgsFeature feat;
+ QgsVectorDataProvider* provider = mLayer->dataProvider();
+ const QgsFieldMap& fields = provider->fields();
+ QgsAttributeList allAttributes = provider->attributeIndexes();
+
+ provider->select( allAttributes, QgsRectangle(), fetchGeom );
+
+ while ( provider->nextFeature( feat ) )
+ {
+ if ( searchTree->checkAgainst( fields, feat ) )
+ {
+ count++;
+ }
+
+ // check if there were errors during evaulating
+ if ( searchTree->hasError() )
+ break;
+ }
+
+ QApplication::restoreOverrideCursor();
+
+ return count;
+}
+
+
+void QgsSearchQueryBuilder::on_btnOk_clicked()
+{
+ // if user hits Ok and there is no query, skip the validation
+ if ( txtSQL->toPlainText().trimmed().length() > 0 )
+ {
+ accept();
+ return;
+ }
+
+ // test the query to see if it will result in a valid layer
+ long numRecs = countRecords( txtSQL->toPlainText() );
+ if ( numRecs == -1 )
+ {
+ // error shown in countRecords
+ }
+ else if ( numRecs == 0 )
+ {
+ QMessageBox::warning( this, tr( "No Records" ), tr( "The query you specified results in zero records being returned." ) );
+ }
+ else
+ {
+ accept();
+ }
+
+}
+
+void QgsSearchQueryBuilder::on_btnEqual_clicked()
+{
+ txtSQL->insertPlainText( " = " );
+}
+
+void QgsSearchQueryBuilder::on_btnLessThan_clicked()
+{
+ txtSQL->insertPlainText( " < " );
+}
+
+void QgsSearchQueryBuilder::on_btnGreaterThan_clicked()
+{
+ txtSQL->insertPlainText( " > " );
+}
+
+void QgsSearchQueryBuilder::on_btnPct_clicked()
+{
+ txtSQL->insertPlainText( "%" );
+}
+
+void QgsSearchQueryBuilder::on_btnIn_clicked()
+{
+ txtSQL->insertPlainText( " IN " );
+}
+
+void QgsSearchQueryBuilder::on_btnNotIn_clicked()
+{
+ txtSQL->insertPlainText( " NOT IN " );
+}
+
+void QgsSearchQueryBuilder::on_btnLike_clicked()
+{
+ txtSQL->insertPlainText( " LIKE " );
+}
+
+QString QgsSearchQueryBuilder::searchString()
+{
+ return txtSQL->toPlainText();
+}
+
+void QgsSearchQueryBuilder::setSearchString( QString searchString )
+{
+ txtSQL->setPlainText( searchString );
+}
+
+void QgsSearchQueryBuilder::on_lstFields_doubleClicked( const QModelIndex &index )
+{
+ txtSQL->insertPlainText( mModelFields->data( index ).toString() );
+}
+
+void QgsSearchQueryBuilder::on_lstValues_doubleClicked( const QModelIndex &index )
+{
+ txtSQL->insertPlainText( mModelValues->data( index ).toString() );
+}
+
+void QgsSearchQueryBuilder::on_btnLessEqual_clicked()
+{
+ txtSQL->insertPlainText( " <= " );
+}
+
+void QgsSearchQueryBuilder::on_btnGreaterEqual_clicked()
+{
+ txtSQL->insertPlainText( " >= " );
+}
+
+void QgsSearchQueryBuilder::on_btnNotEqual_clicked()
+{
+ txtSQL->insertPlainText( " != " );
+}
+
+void QgsSearchQueryBuilder::on_btnAnd_clicked()
+{
+ txtSQL->insertPlainText( " AND " );
+}
+
+void QgsSearchQueryBuilder::on_btnNot_clicked()
+{
+ txtSQL->insertPlainText( " NOT " );
+}
+
+void QgsSearchQueryBuilder::on_btnOr_clicked()
+{
+ txtSQL->insertPlainText( " OR " );
+}
+
+void QgsSearchQueryBuilder::on_btnClear_clicked()
+{
+ txtSQL->clear();
+}
+
+void QgsSearchQueryBuilder::on_btnILike_clicked()
+{
+ txtSQL->insertPlainText( " ILIKE " );
+}
+
+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 );
+}
+
Copied: trunk/qgis/src/gui/qgssearchquerybuilder.h (from rev 14860, trunk/qgis/src/app/qgssearchquerybuilder.h)
===================================================================
--- trunk/qgis/src/gui/qgssearchquerybuilder.h (rev 0)
+++ trunk/qgis/src/gui/qgssearchquerybuilder.h 2010-12-08 17:38:01 UTC (rev 14867)
@@ -0,0 +1,129 @@
+/***************************************************************************
+ qgssearchquerybuilder.h - Query builder for search strings
+ ----------------------
+ begin : March 2006
+ copyright : (C) 2006 by Martin Dobias
+ email : wonder.sk at gmail dot com
+ ***************************************************************************
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+/* $Id$ */
+
+#ifndef QGSSEARCHQUERYBUILDER_H
+#define QGSSEARCHQUERYBUILDER_H
+
+#include <map>
+#include <vector>
+#include <QStandardItemModel>
+#include <QModelIndex>
+
+#include "ui_qgsquerybuilderbase.h"
+#include "qgisgui.h"
+
+class QgsField;
+class QgsVectorLayer;
+
+/*!
+ * \class QgsSearchQueryBuilder
+ * \brief Query Builder for search strings
+ *
+ */
+class GUI_EXPORT QgsSearchQueryBuilder : public QDialog, private Ui::QgsQueryBuilderBase
+{
+ Q_OBJECT
+
+ public:
+ //! Constructor - takes pointer to vector layer as a parameter
+ QgsSearchQueryBuilder( QgsVectorLayer* layer, QWidget *parent = 0,
+ Qt::WFlags fl = QgisGui::ModalDialogFlags );
+
+ ~QgsSearchQueryBuilder();
+
+ //! returns newly created search string
+ QString searchString();
+
+ //! change search string shown in text field
+ void setSearchString( QString searchString );
+
+ public slots:
+ void on_btnEqual_clicked();
+ void on_btnOk_clicked();
+ void on_btnLessThan_clicked();
+ void on_btnGreaterThan_clicked();
+ void on_btnLike_clicked();
+ void on_btnILike_clicked();
+ void on_btnPct_clicked();
+ void on_btnIn_clicked();
+ void on_btnNotIn_clicked();
+
+ void on_lstFields_doubleClicked( const QModelIndex &index );
+ void on_lstValues_doubleClicked( const QModelIndex &index );
+ void on_btnLessEqual_clicked();
+ void on_btnGreaterEqual_clicked();
+ void on_btnNotEqual_clicked();
+ void on_btnAnd_clicked();
+ void on_btnNot_clicked();
+ void on_btnOr_clicked();
+ void on_btnClear_clicked();
+
+ /*! Test the constructed search string to see if it's correct.
+ * The number of rows that would be returned is displayed in a message box.
+ * @param showResults If true, the results are displayed in a QMessageBox
+ */
+ void on_btnTest_clicked();
+
+ /*!
+ * Get all distinct values for the field. Values are inserted
+ * into the value list box
+ */
+ void on_btnGetAllValues_clicked();
+
+ /*!
+ * Get sample distinct values for the selected field. The sample size is
+ * limited to an arbitrary value (currently set to 25). The values
+ * are inserted into the values list box.
+ */
+ void on_btnSampleValues_clicked();
+
+ void saveQuery();
+ void loadQuery();
+
+ private:
+
+ /*!
+ * Populate the field list for the selected table
+ */
+ void populateFields();
+ /*!
+ * Setup models for listviews
+ */
+ void setupListViews();
+
+ /*! Get the number of records that would be returned by the current SQL
+ * @return Number of records or -1 if an error was encountered
+ */
+ long countRecords( QString sql );
+
+ /*!
+ * populates list box with values of selected field
+ * @param limit if not zero, inserts only this count of values
+ */
+ void getFieldValues( int limit );
+
+ private:
+
+ //! Layer for which is the query builder opened
+ QgsVectorLayer* mLayer;
+ //! Map that holds field information, keyed by field name
+ QMap<QString, int> mFieldMap;
+ //! Model for fields ListView
+ QStandardItemModel *mModelFields;
+ //! Model for values ListView
+ QStandardItemModel *mModelValues;
+};
+#endif //QGSSEARCHQUERYBUILDER_H
More information about the QGIS-commit
mailing list