Skip to content

Commit

Permalink
Added Filter search for WFS layers. Also improved the treeView to hav…
Browse files Browse the repository at this point in the history
…e better column and row layout
  • Loading branch information
palmerj committed Apr 2, 2013
1 parent 16b1e93 commit 84f4346
Show file tree
Hide file tree
Showing 3 changed files with 299 additions and 159 deletions.
231 changes: 172 additions & 59 deletions src/providers/wfs/qgswfssourceselect.cpp
Expand Up @@ -35,6 +35,7 @@
#include <QMessageBox>
#include <QSettings>
#include <QFileDialog>
#include <QPainter>


QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, Qt::WFlags fl, bool embeddedMode )
Expand All @@ -43,30 +44,57 @@ QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, Qt::WFlags fl, bool emb
{
setupUi( this );

btnAdd = buttonBox->button( QDialogButtonBox::Apply );
btnAdd->setEnabled( false );

if ( embeddedMode )
{
buttonBox->button( QDialogButtonBox::Apply )->hide();
buttonBox->button( QDialogButtonBox::Close )->hide();
}

connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( addLayer() ) );
mAddButton = new QPushButton( tr( "&Add" ) );
mAddButton->setEnabled( false );

mBuildQueryButton = new QPushButton( tr( "&Build query" ) );
mBuildQueryButton->setToolTip( tr( "Build query" ) );
mBuildQueryButton->setDisabled( true );


buttonBox->addButton( mAddButton, QDialogButtonBox::ActionRole );
connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addLayer() ) );

buttonBox->addButton( mBuildQueryButton, QDialogButtonBox::ActionRole );
connect( mBuildQueryButton, SIGNAL( clicked() ), this, SLOT( on_mBuildQueryButton_clicked() ) );

connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
connect( btnNew, SIGNAL( clicked() ), this, SLOT( addEntryToServerList() ) );
connect( btnEdit, SIGNAL( clicked() ), this, SLOT( modifyEntryOfServerList() ) );
connect( btnDelete, SIGNAL( clicked() ), this, SLOT( deleteEntryOfServerList() ) );
connect( btnConnect, SIGNAL( clicked() ), this, SLOT( connectToServer() ) );
connect( btnChangeSpatialRefSys, SIGNAL( clicked() ), this, SLOT( changeCRS() ) );
connect( treeWidget, SIGNAL( currentItemChanged( QTreeWidgetItem*, QTreeWidgetItem* ) ), this, SLOT( changeCRSFilter() ) );
connect( lineFilter, SIGNAL( textChanged( QString ) ), this, SLOT( filterChanged( QString ) ) );
populateConnectionList();
mProjectionSelector = new QgsGenericProjectionSelector( this );
mProjectionSelector->setMessage();

mItemDelegate = new QgsWFSItemDelegate( treeView );
treeView->setItemDelegate( mItemDelegate );

QSettings settings;
QgsDebugMsg( "restoring geometry" );
restoreGeometry( settings.value( "/Windows/WFSSourceSelect/geometry" ).toByteArray() );

mModel = new QStandardItemModel();
mModel->setHorizontalHeaderItem( 0, new QStandardItem( "Title" ) );
mModel->setHorizontalHeaderItem( 1, new QStandardItem( "Name" ) );
mModel->setHorizontalHeaderItem( 2, new QStandardItem( "Abstract" ) );
mModel->setHorizontalHeaderItem( 3, new QStandardItem( "Cache Feature" ) );
mModel->setHorizontalHeaderItem( 4, new QStandardItem( "Filter" ) );

mModelProxy = new QSortFilterProxyModel( this );
mModelProxy->setSourceModel( mModel );
mModelProxy->setSortCaseSensitivity( Qt::CaseInsensitive );
treeView->setModel( mModelProxy );

connect( treeView, SIGNAL( doubleClicked(const QModelIndex&) ), this, SLOT( on_treeWidget_itemDoubleClicked(const QModelIndex&) ) );
connect( treeView->selectionModel(), SIGNAL( currentRowChanged ( QModelIndex, QModelIndex) ), this, SLOT( on_treeWidget_currentRowChanged(const QModelIndex&, const QModelIndex&) ) );
}

QgsWFSSourceSelect::~QgsWFSSourceSelect()
Expand All @@ -75,8 +103,13 @@ QgsWFSSourceSelect::~QgsWFSSourceSelect()
QgsDebugMsg( "saving geometry" );
settings.setValue( "/Windows/WFSSourceSelect/geometry", saveGeometry() );

delete mItemDelegate;
delete mProjectionSelector;
delete mCapabilities;
delete mModel;
delete mModelProxy;
delete mAddButton;
delete mBuildQueryButton;
}

void QgsWFSSourceSelect::populateConnectionList()
Expand Down Expand Up @@ -183,13 +216,18 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
foreach ( QgsWFSCapabilities::FeatureType featureType, caps.featureTypes )
{
// insert the typenames, titles and abstracts into the tree view
QTreeWidgetItem* newItem = new QTreeWidgetItem();
newItem->setText( 0, featureType.title );
newItem->setText( 1, featureType.name );
newItem->setText( 2, featureType.abstract );
newItem->setToolTip( 2, "<font color=black>" + featureType.abstract + "</font>" );
newItem->setCheckState( 3, Qt::Checked );
treeWidget->addTopLevelItem( newItem );
QStandardItem* titleItem = new QStandardItem( featureType.title );
QStandardItem* nameItem = new QStandardItem( featureType.name );
QStandardItem* abstractItem = new QStandardItem( featureType.abstract );
abstractItem->setToolTip( "<font color=black>" + featureType.abstract + "</font>" );
abstractItem->setTextAlignment( Qt::AlignLeft | Qt::AlignTop );
QStandardItem* cachedItem = new QStandardItem();
QStandardItem* filterItem = new QStandardItem();
cachedItem->setCheckable( true );
cachedItem->setCheckState( Qt::Checked );

typedef QList< QStandardItem* > StandardItemList;
mModel->appendRow( StandardItemList() << titleItem << nameItem << abstractItem << cachedItem << filterItem);

// insert the available CRS into mAvailableCRS
std::list<QString> currentCRSList;
Expand All @@ -202,14 +240,30 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()

if ( caps.featureTypes.count() > 0 )
{
btnAdd->setEnabled( true );
treeWidget->setCurrentItem( treeWidget->topLevelItem( 0 ) );
treeView->resizeColumnToContents( 0 );
treeView->resizeColumnToContents( 1 );
treeView->resizeColumnToContents( 2 );
treeView->resizeColumnToContents( 3 );
for ( int i = 0; i < 2; i++ )
{
if ( treeView->columnWidth( i ) > 300 )
{
treeView->setColumnWidth( i, 300 );
}
}
if ( treeView->columnWidth( 2 ) > 150 )
{
treeView->setColumnWidth( 2, 150 );
}
btnChangeSpatialRefSys->setEnabled( true );
treeView->selectionModel()->select( mModel->index( 0, 0 ), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows );
treeView->setFocus();
}
else
{
QMessageBox::information( 0, tr( "No Layers" ), tr( "capabilities document contained no layers." ) );
btnAdd->setEnabled( false );
mAddButton->setEnabled( false );
mBuildQueryButton->setEnabled( false );
}
}

Expand Down Expand Up @@ -253,8 +307,10 @@ void QgsWFSSourceSelect::deleteEntryOfServerList()
void QgsWFSSourceSelect::connectToServer()
{
btnConnect->setEnabled( false );
treeWidget->clear();

if ( mModel )
{
mModel->removeRows( 0, mModel->rowCount() );
}
if ( mCapabilities )
{
mCapabilities->requestCapabilities();
Expand All @@ -264,16 +320,13 @@ void QgsWFSSourceSelect::connectToServer()

void QgsWFSSourceSelect::addLayer()
{
//get selected entry in lstWidget
QTreeWidgetItem* tItem = treeWidget->currentItem();
if ( !tItem )
//get selected entry in treeview
QModelIndex currentIndex = treeView->selectionModel()->currentIndex();
if ( !currentIndex.isValid() )
{
return;
}

QList<QTreeWidgetItem*> selectedItems = treeWidget->selectedItems();
QList<QTreeWidgetItem*>::const_iterator sIt = selectedItems.constBegin();

QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
QgsWFSCapabilities conn( connection.uri().encodedUri() );

Expand Down Expand Up @@ -312,13 +365,22 @@ void QgsWFSSourceSelect::addLayer()
}
}
}

//create layers that user selected from this WFS source
for ( ; sIt != selectedItems.constEnd(); ++sIt )
QModelIndexList list = treeView->selectionModel()->selectedRows();
for ( int i = 0; i < list.size(); i++ )
{ //add a wfs layer to the map
QString typeName = ( *sIt )->text( 1 ); //WFS repository's name for layer
QString filter = ( *sIt )->text( 4 ); //optional filter specified by user
QModelIndex idx = mModelProxy->mapToSource( list[i] );
if ( !idx.isValid() )
{
continue;
}
int row = idx.row();
QString typeName = mModel->item( row, 1 )->text(); //WFS repository's name for layer
QString filter = mModel->item( row, 4 )->text(); //optional filter specified by user
QgsDebugMsg( "Layer " + typeName + " Filter is " + filter );
//is "cache features" checked?
if (( *sIt )->checkState( 3 ) == Qt::Checked )
if ( mModel->item( row, 3 )->checkState() == Qt::Checked )
{ //yes: entire WFS layer will be retrieved and cached
mUri = conn.uriGetFeature( typeName, pCrsString, filter );
}
Expand All @@ -331,6 +393,48 @@ void QgsWFSSourceSelect::addLayer()
accept();
}

void QgsWFSSourceSelect::buildQuery( const QModelIndex& index )
{
if ( !index.isValid() )
{
return;
}
QModelIndex filterIndex = index.sibling( index.row(), 4 );
QString typeName = index.sibling( index.row(), 1 ).data().toString();

//get available fields for wfs layer
QgsWFSProvider p( "" ); //bypasses most provider instantiation logic
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
QgsWFSCapabilities conn( connection.uri().encodedUri() );
QString uri = conn.uriDescribeFeatureType( typeName );

QgsFields fields;
QString geometryAttribute;
QGis::WkbType geomType;
if ( p.describeFeatureType( uri, geometryAttribute, fields, geomType ) != 0 )
{
return;
}

//show expression builder
QgsExpressionBuilderDialog d( 0, filterIndex.data().toString() );

//add available attributes to expression builder
QgsExpressionBuilderWidget* w = d.expressionBuilder();
if ( !w )
{
return;
}

w->loadFieldNames( fields );

if ( d.exec() == QDialog::Accepted )
{
QgsDebugMsg( "Expression text = " + w->expressionText() );
mModelProxy->setData( filterIndex, QVariant( w->expressionText() ) );
}
}

void QgsWFSSourceSelect::changeCRS()
{
if ( mProjectionSelector->exec() )
Expand All @@ -342,11 +446,12 @@ void QgsWFSSourceSelect::changeCRS()

void QgsWFSSourceSelect::changeCRSFilter()
{
QgsDebugMsg("changeCRSFilter called");
//evaluate currently selected typename and set the CRS filter in mProjectionSelector
QTreeWidgetItem* currentTreeItem = treeWidget->currentItem();
if ( currentTreeItem )
QModelIndex currentIndex = treeView->selectionModel()->currentIndex();
if ( currentIndex.isValid() )
{
QString currentTypename = currentTreeItem->text( 1 );
QString currentTypename = currentIndex.sibling( currentIndex.row(), 1 ).data().toString();
QgsDebugMsg( QString( "the current typename is: %1" ).arg( currentTypename ) );

std::map<QString, std::list<QString> >::const_iterator crsIterator = mAvailableCRS.find( currentTypename );
Expand Down Expand Up @@ -410,39 +515,47 @@ void QgsWFSSourceSelect::on_btnLoad_clicked()
emit connectionsChanged();
}

void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked( QTreeWidgetItem* item, int column )
void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked( const QModelIndex& index )
{
if ( item && column == 4 )
{
//get available fields for wfs layer
QgsWFSProvider p( "" ); //bypasses most provider instantiation logic
QgsOWSConnection connection( "WFS", cmbConnections->currentText() );
QgsWFSCapabilities conn( connection.uri().encodedUri() );
QString uri = conn.uriDescribeFeatureType( item->text( 1 ) );

QgsFields fields;
QString geometryAttribute;
QGis::WkbType geomType;
if ( p.describeFeatureType( uri, geometryAttribute, fields, geomType ) != 0 )
{
return;
}
QgsDebugMsg( "double click called" );
buildQuery( index );
}

//show expression builder
QgsExpressionBuilderDialog d( 0, item->text( 3 ) );
void QgsWFSSourceSelect::on_treeWidget_currentRowChanged( const QModelIndex & current, const QModelIndex & previous)
{
Q_UNUSED( previous )
QgsDebugMsg( "treeWidget_currentRowChanged called" );
changeCRSFilter();
mBuildQueryButton->setEnabled( current.isValid() );
mAddButton->setEnabled( current.isValid() );
}

//add available attributes to expression builder
QgsExpressionBuilderWidget* w = d.expressionBuilder();
if ( !w )
{
return;
}
void QgsWFSSourceSelect::on_mBuildQueryButton_clicked()
{
QgsDebugMsg( "mBuildQueryButton click called" );
buildQuery( treeView->selectionModel()->currentIndex() );
}

w->loadFieldNames( fields );
void QgsWFSSourceSelect::filterChanged(QString text)
{
QgsDebugMsg( "WFS FeatureType filter changed to :" + text );
QRegExp::PatternSyntax mySyntax = QRegExp::PatternSyntax( QRegExp::RegExp );
Qt::CaseSensitivity myCaseSensitivity = Qt::CaseInsensitive;
QRegExp myRegExp( text, myCaseSensitivity, mySyntax );
mModelProxy->setFilterRegExp( myRegExp );
mModelProxy->sort( mModelProxy->sortColumn(), mModelProxy->sortOrder() );
}

if ( d.exec() == QDialog::Accepted )
QSize QgsWFSItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
QVariant indexData;
indexData = index.data(Qt::DisplayRole);
if ( indexData.isNull() )
{
item->setText( 4, w->expressionText() );
return QSize();
}
}
QString data = indexData.toString();
QSize size = option.fontMetrics.boundingRect(data).size();
size.setHeight(size.height() + 2);
return size;
}

0 comments on commit 84f4346

Please sign in to comment.