QGIS API Documentation  master-6227475
src/gui/qgsquerybuilder.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                 qgsquerybuilder.cpp - Query Builder
00003                      --------------------------------------
00004                Date                 : 2004-11-19
00005                Copyright            : (C) 2004 by Gary E.Sherman
00006                Email                : sherman at mrcc.com
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 #include "qgsquerybuilder.h"
00016 #include "qgslogger.h"
00017 #include <QListView>
00018 #include <QMessageBox>
00019 #include <QRegExp>
00020 #include <QPushButton>
00021 #include <QSettings>
00022 #include "qgsvectorlayer.h"
00023 #include "qgsvectordataprovider.h"
00024 
00025 // constructor used when the query builder must make its own
00026 // connection to the database
00027 QgsQueryBuilder::QgsQueryBuilder( QgsVectorLayer *layer,
00028                                   QWidget *parent, Qt::WFlags fl )
00029     : QDialog( parent, fl )
00030     , mPreviousFieldRow( -1 )
00031     , mLayer( layer )
00032 {
00033   setupUi( this );
00034 
00035   QSettings settings;
00036   restoreGeometry( settings.value( "/Windows/QueryBuilder/geometry" ).toByteArray() );
00037 
00038   QPushButton *pbn = new QPushButton( tr( "&Test" ) );
00039   buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
00040   connect( pbn, SIGNAL( clicked() ), this, SLOT( test() ) );
00041 
00042   pbn = new QPushButton( tr( "&Clear" ) );
00043   buttonBox->addButton( pbn, QDialogButtonBox::ActionRole );
00044   connect( pbn, SIGNAL( clicked() ), this, SLOT( clear() ) );
00045 
00046   setupGuiViews();
00047 
00048   mOrigSubsetString = layer->subsetString();
00049 
00050   mUseUnfilteredLayer->setDisabled( mLayer->subsetString().isEmpty() );
00051 
00052   lblDataUri->setText( layer->name() );
00053   txtSQL->setText( mOrigSubsetString );
00054 
00055   populateFields();
00056 }
00057 
00058 QgsQueryBuilder::~QgsQueryBuilder()
00059 {
00060   QSettings settings;
00061   settings.setValue( "/Windows/QueryBuilder/geometry", saveGeometry() );
00062 }
00063 
00064 void QgsQueryBuilder::populateFields()
00065 {
00066   const QgsFields& fields = mLayer->pendingFields();
00067   for ( int idx = 0; idx < fields.count(); ++idx )
00068   {
00069     QStandardItem *myItem = new QStandardItem( fields[idx].name() );
00070     myItem->setData( idx );
00071     myItem->setEditable( false );
00072     mModelFields->insertRow( mModelFields->rowCount(), myItem );
00073   }
00074 
00075   // All fields get ... setup
00076   setupLstFieldsModel();
00077 }
00078 
00079 void QgsQueryBuilder::setupLstFieldsModel()
00080 {
00081   lstFields->setModel( mModelFields );
00082 }
00083 
00084 void QgsQueryBuilder::setupGuiViews()
00085 {
00086   //Initialize the models
00087   mModelFields = new QStandardItemModel();
00088   mModelValues = new QStandardItemModel();
00089   // Modes
00090   lstFields->setViewMode( QListView::ListMode );
00091   lstValues->setViewMode( QListView::ListMode );
00092   lstFields->setSelectionBehavior( QAbstractItemView::SelectRows );
00093   lstValues->setSelectionBehavior( QAbstractItemView::SelectRows );
00094   // Performance tip since Qt 4.1
00095   lstFields->setUniformItemSizes( true );
00096   lstValues->setUniformItemSizes( true );
00097   // Colored rows
00098   lstFields->setAlternatingRowColors( true );
00099   lstValues->setAlternatingRowColors( true );
00100 }
00101 
00102 void QgsQueryBuilder::fillValues( int idx, int limit )
00103 {
00104   // clear the model
00105   mModelValues->clear();
00106 
00107   // determine the field type
00108   QList<QVariant> values;
00109   mLayer->uniqueValues( idx, values, limit );
00110 
00111   QSettings settings;
00112   QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
00113 
00114   QgsDebugMsg( QString( "nullValue: %1" ).arg( nullValue ) );
00115 
00116   for ( int i = 0; i < values.size(); i++ )
00117   {
00118     QStandardItem *myItem = new QStandardItem( values[i].isNull() ? nullValue : values[i].toString() );
00119     myItem->setEditable( false );
00120     myItem->setData( values[i], Qt::UserRole + 1 );
00121     mModelValues->insertRow( mModelValues->rowCount(), myItem );
00122     QgsDebugMsg( QString( "Value is null: %1\nvalue: %2" ).arg( values[i].isNull() ).arg( values[i].isNull() ? nullValue : values[i].toString() ) );
00123   }
00124 }
00125 
00126 void QgsQueryBuilder::on_btnSampleValues_clicked()
00127 {
00128   lstValues->setCursor( Qt::WaitCursor );
00129 
00130   QString prevSubsetString = mLayer->subsetString();
00131   if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
00132   {
00133     mLayer->setSubsetString( "" );
00134   }
00135 
00136   //delete connection mModelValues and lstValues
00137   QStandardItemModel *tmp = new QStandardItemModel();
00138   lstValues->setModel( tmp );
00139   //Clear and fill the mModelValues
00140   fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), 25 );
00141   lstValues->setModel( mModelValues );
00142   //delete the tmp
00143   delete tmp;
00144 
00145   if ( prevSubsetString != mLayer->subsetString() )
00146   {
00147     mLayer->setSubsetString( prevSubsetString );
00148   }
00149 
00150   lstValues->setCursor( Qt::ArrowCursor );
00151 }
00152 
00153 void QgsQueryBuilder::on_btnGetAllValues_clicked()
00154 {
00155   lstValues->setCursor( Qt::WaitCursor );
00156 
00157   QString prevSubsetString = mLayer->subsetString();
00158   if ( mUseUnfilteredLayer->isChecked() && !prevSubsetString.isEmpty() )
00159   {
00160     mLayer->setSubsetString( "" );
00161   }
00162 
00163   //delete connection mModelValues and lstValues
00164   QStandardItemModel *tmp = new QStandardItemModel();
00165   lstValues->setModel( tmp );
00166   //Clear and fill the mModelValues
00167   fillValues( mModelFields->data( lstFields->currentIndex(), Qt::UserRole + 1 ).toInt(), -1 );
00168   lstValues->setModel( mModelValues );
00169   //delete the tmp
00170   delete tmp;
00171 
00172   if ( prevSubsetString != mLayer->subsetString() )
00173   {
00174     mLayer->setSubsetString( prevSubsetString );
00175   }
00176 
00177   lstValues->setCursor( Qt::ArrowCursor );
00178 }
00179 
00180 void QgsQueryBuilder::test()
00181 {
00182   // test the sql statement to see if it works
00183   // by counting the number of records that would be
00184   // returned
00185 
00186   if ( mLayer->setSubsetString( txtSQL->toPlainText() ) )
00187   {
00188     mUseUnfilteredLayer->setDisabled( mLayer->subsetString().isEmpty() );
00189 
00190     QMessageBox::information( this,
00191                               tr( "Query Result" ),
00192                               tr( "The where clause returned %n row(s).", "returned test rows", mLayer->featureCount() ) );
00193   }
00194   else if ( mLayer->dataProvider()->hasErrors() )
00195   {
00196     QMessageBox::warning( this,
00197                           tr( "Query Failed" ),
00198                           tr( "An error occurred when executing the query." )
00199                           + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( "\n" ) ) );
00200     mLayer->dataProvider()->clearErrors();
00201   }
00202   else
00203   {
00204     QMessageBox::warning( this,
00205                           tr( "Query Failed" ),
00206                           tr( "An error occurred when executing the query." ) );
00207   }
00208 }
00209 
00210 void QgsQueryBuilder::accept()
00211 {
00212   if ( !mLayer->setSubsetString( txtSQL->toPlainText() ) )
00213   {
00214     //error in query - show the problem
00215     if ( mLayer->dataProvider()->hasErrors() )
00216     {
00217       QMessageBox::warning( this,
00218                             tr( "Query Failed" ),
00219                             tr( "An error occurred when executing the query." )
00220                             + tr( "\nThe data provider said:\n%1" ).arg( mLayer->dataProvider()->errors().join( "\n" ) ) );
00221       mLayer->dataProvider()->clearErrors();
00222     }
00223     else
00224     {
00225       QMessageBox::warning( this, tr( "Error in Query" ), tr( "The subset string could not be set" ) );
00226     }
00227 
00228     return;
00229   }
00230 
00231   QDialog::accept();
00232 }
00233 
00234 void QgsQueryBuilder::reject()
00235 {
00236   if ( mLayer->subsetString() != mOrigSubsetString )
00237     mLayer->setSubsetString( mOrigSubsetString );
00238 
00239   QDialog::reject();
00240 }
00241 
00242 void QgsQueryBuilder::on_btnEqual_clicked()
00243 {
00244   txtSQL->insertPlainText( " = " );
00245 }
00246 
00247 void QgsQueryBuilder::on_btnLessThan_clicked()
00248 {
00249   txtSQL->insertPlainText( " < " );
00250 }
00251 
00252 void QgsQueryBuilder::on_btnGreaterThan_clicked()
00253 {
00254   txtSQL->insertPlainText( " > " );
00255 }
00256 
00257 void QgsQueryBuilder::on_btnPct_clicked()
00258 {
00259   txtSQL->insertPlainText( "%" );
00260 }
00261 
00262 void QgsQueryBuilder::on_btnIn_clicked()
00263 {
00264   txtSQL->insertPlainText( " IN " );
00265 }
00266 
00267 void QgsQueryBuilder::on_btnNotIn_clicked()
00268 {
00269   txtSQL->insertPlainText( " NOT IN " );
00270 }
00271 
00272 void QgsQueryBuilder::on_btnLike_clicked()
00273 {
00274   txtSQL->insertPlainText( " LIKE " );
00275 }
00276 
00277 QString QgsQueryBuilder::sql()
00278 {
00279   return txtSQL->toPlainText();
00280 }
00281 
00282 void QgsQueryBuilder::setSql( QString sqlStatement )
00283 {
00284   txtSQL->setText( sqlStatement );
00285 }
00286 
00287 void QgsQueryBuilder::on_lstFields_clicked( const QModelIndex &index )
00288 {
00289   if ( mPreviousFieldRow != index.row() )
00290   {
00291     mPreviousFieldRow = index.row();
00292 
00293     btnSampleValues->setEnabled( true );
00294     btnGetAllValues->setEnabled( true );
00295 
00296     mModelValues->clear();
00297   }
00298 }
00299 
00300 void QgsQueryBuilder::on_lstFields_doubleClicked( const QModelIndex &index )
00301 {
00302   txtSQL->insertPlainText( "\"" + mLayer->pendingFields()[ mModelFields->data( index, Qt::UserRole+1 ).toInt()].name() + "\"" );
00303 }
00304 
00305 void QgsQueryBuilder::on_lstValues_doubleClicked( const QModelIndex &index )
00306 {
00307   QVariant value = mModelValues->data( index, Qt::UserRole + 1 );
00308   if ( value.isNull() )
00309     txtSQL->insertPlainText( "NULL" );
00310   else if ( value.type() == QVariant::Int || value.type() == QVariant::Double || value.type() == QVariant::LongLong )
00311     txtSQL->insertPlainText( value.toString() );
00312   else
00313     txtSQL->insertPlainText( "'" + value.toString().replace( "'", "''" ) + "'" );
00314 }
00315 
00316 void QgsQueryBuilder::on_btnLessEqual_clicked()
00317 {
00318   txtSQL->insertPlainText( " <= " );
00319 }
00320 
00321 void QgsQueryBuilder::on_btnGreaterEqual_clicked()
00322 {
00323   txtSQL->insertPlainText( " >= " );
00324 }
00325 
00326 void QgsQueryBuilder::on_btnNotEqual_clicked()
00327 {
00328   txtSQL->insertPlainText( " != " );
00329 }
00330 
00331 void QgsQueryBuilder::on_btnAnd_clicked()
00332 {
00333   txtSQL->insertPlainText( " AND " );
00334 }
00335 
00336 void QgsQueryBuilder::on_btnNot_clicked()
00337 {
00338   txtSQL->insertPlainText( " NOT " );
00339 }
00340 
00341 void QgsQueryBuilder::on_btnOr_clicked()
00342 {
00343   txtSQL->insertPlainText( " OR " );
00344 }
00345 
00346 void QgsQueryBuilder::clear()
00347 {
00348   txtSQL->clear();
00349   mLayer->setSubsetString( "" );
00350   mUseUnfilteredLayer->setDisabled( true );
00351 }
00352 
00353 void QgsQueryBuilder::on_btnILike_clicked()
00354 {
00355   txtSQL->insertPlainText( " ILIKE " );
00356 }
00357 
00358 void QgsQueryBuilder::setDatasourceDescription( QString uri )
00359 {
00360   lblDataUri->setText( uri );
00361 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines