3535#include < QMessageBox>
3636#include < QSettings>
3737#include < QFileDialog>
38+ #include < QPainter>
3839
3940
4041QgsWFSSourceSelect::QgsWFSSourceSelect ( QWidget* parent, Qt::WFlags fl, bool embeddedMode )
@@ -43,40 +44,74 @@ QgsWFSSourceSelect::QgsWFSSourceSelect( QWidget* parent, Qt::WFlags fl, bool emb
4344{
4445 setupUi ( this );
4546
46- btnAdd = buttonBox->button ( QDialogButtonBox::Apply );
47- btnAdd->setEnabled ( false );
48-
4947 if ( embeddedMode )
5048 {
51- buttonBox->button ( QDialogButtonBox::Apply )->hide ();
5249 buttonBox->button ( QDialogButtonBox::Close )->hide ();
5350 }
5451
55- connect ( buttonBox->button ( QDialogButtonBox::Apply ), SIGNAL ( clicked () ), this , SLOT ( addLayer () ) );
52+ mAddButton = new QPushButton ( tr ( " &Add" ) );
53+ mAddButton ->setEnabled ( false );
54+
55+ mBuildQueryButton = new QPushButton ( tr ( " &Build query" ) );
56+ mBuildQueryButton ->setToolTip ( tr ( " Build query" ) );
57+ mBuildQueryButton ->setDisabled ( true );
58+
59+
60+ buttonBox->addButton ( mAddButton , QDialogButtonBox::ActionRole );
61+ connect ( mAddButton , SIGNAL ( clicked () ), this , SLOT ( addLayer () ) );
62+
63+ buttonBox->addButton ( mBuildQueryButton , QDialogButtonBox::ActionRole );
64+ connect ( mBuildQueryButton , SIGNAL ( clicked () ), this , SLOT ( on_mBuildQueryButton_clicked () ) );
65+
5666 connect ( buttonBox, SIGNAL ( rejected () ), this , SLOT ( reject () ) );
5767 connect ( btnNew, SIGNAL ( clicked () ), this , SLOT ( addEntryToServerList () ) );
5868 connect ( btnEdit, SIGNAL ( clicked () ), this , SLOT ( modifyEntryOfServerList () ) );
5969 connect ( btnDelete, SIGNAL ( clicked () ), this , SLOT ( deleteEntryOfServerList () ) );
6070 connect ( btnConnect, SIGNAL ( clicked () ), this , SLOT ( connectToServer () ) );
6171 connect ( btnChangeSpatialRefSys, SIGNAL ( clicked () ), this , SLOT ( changeCRS () ) );
62- connect ( treeWidget , SIGNAL ( currentItemChanged ( QTreeWidgetItem*, QTreeWidgetItem* ) ), this , SLOT ( changeCRSFilter ( ) ) );
72+ connect ( lineFilter , SIGNAL ( textChanged ( QString ) ), this , SLOT ( filterChanged ( QString ) ) );
6373 populateConnectionList ();
6474 mProjectionSelector = new QgsGenericProjectionSelector ( this );
6575 mProjectionSelector ->setMessage ();
6676
77+ mItemDelegate = new QgsWFSItemDelegate ( treeView );
78+ treeView->setItemDelegate ( mItemDelegate );
79+
6780 QSettings settings;
68- QgsDebugMsg ( " restoring geometry " );
81+ QgsDebugMsg ( " restoring settings " );
6982 restoreGeometry ( settings.value ( " /Windows/WFSSourceSelect/geometry" ).toByteArray () );
83+ cbxUseTitleLayerName->setChecked ( settings.value ( " /Windows/WFSSourceSelect/UseTitleLayerName" , false ).toBool () );
84+
85+ mModel = new QStandardItemModel ();
86+ mModel ->setHorizontalHeaderItem ( 0 , new QStandardItem ( " Title" ) );
87+ mModel ->setHorizontalHeaderItem ( 1 , new QStandardItem ( " Name" ) );
88+ mModel ->setHorizontalHeaderItem ( 2 , new QStandardItem ( " Abstract" ) );
89+ mModel ->setHorizontalHeaderItem ( 3 , new QStandardItem ( " Cache Feature" ) );
90+ mModel ->setHorizontalHeaderItem ( 4 , new QStandardItem ( " Filter" ) );
91+
92+ mModelProxy = new QSortFilterProxyModel ( this );
93+ mModelProxy ->setSourceModel ( mModel );
94+ mModelProxy ->setSortCaseSensitivity ( Qt::CaseInsensitive );
95+ treeView->setModel ( mModelProxy );
96+
97+ connect ( treeView, SIGNAL ( doubleClicked (const QModelIndex&) ), this , SLOT ( on_treeWidget_itemDoubleClicked (const QModelIndex&) ) );
98+ connect ( treeView->selectionModel (), SIGNAL ( currentRowChanged ( QModelIndex, QModelIndex) ), this , SLOT ( on_treeWidget_currentRowChanged (const QModelIndex&, const QModelIndex&) ) );
7099}
71100
72101QgsWFSSourceSelect::~QgsWFSSourceSelect ()
73102{
74103 QSettings settings;
75- QgsDebugMsg ( " saving geometry " );
104+ QgsDebugMsg ( " saving settings " );
76105 settings.setValue ( " /Windows/WFSSourceSelect/geometry" , saveGeometry () );
106+ settings.setValue ( " /Windows/WFSSourceSelect/UseTitleLayerName" , cbxUseTitleLayerName->isChecked () );
77107
108+ delete mItemDelegate ;
78109 delete mProjectionSelector ;
79110 delete mCapabilities ;
111+ delete mModel ;
112+ delete mModelProxy ;
113+ delete mAddButton ;
114+ delete mBuildQueryButton ;
80115}
81116
82117void QgsWFSSourceSelect::populateConnectionList ()
@@ -183,13 +218,18 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
183218 foreach ( QgsWFSCapabilities::FeatureType featureType, caps.featureTypes )
184219 {
185220 // insert the typenames, titles and abstracts into the tree view
186- QTreeWidgetItem* newItem = new QTreeWidgetItem ();
187- newItem->setText ( 0 , featureType.title );
188- newItem->setText ( 1 , featureType.name );
189- newItem->setText ( 2 , featureType.abstract );
190- newItem->setToolTip ( 2 , " <font color=black>" + featureType.abstract + " </font>" );
191- newItem->setCheckState ( 3 , Qt::Checked );
192- treeWidget->addTopLevelItem ( newItem );
221+ QStandardItem* titleItem = new QStandardItem ( featureType.title );
222+ QStandardItem* nameItem = new QStandardItem ( featureType.name );
223+ QStandardItem* abstractItem = new QStandardItem ( featureType.abstract );
224+ abstractItem->setToolTip ( " <font color=black>" + featureType.abstract + " </font>" );
225+ abstractItem->setTextAlignment ( Qt::AlignLeft | Qt::AlignTop );
226+ QStandardItem* cachedItem = new QStandardItem ();
227+ QStandardItem* filterItem = new QStandardItem ();
228+ cachedItem->setCheckable ( true );
229+ cachedItem->setCheckState ( Qt::Checked );
230+
231+ typedef QList< QStandardItem* > StandardItemList;
232+ mModel ->appendRow ( StandardItemList () << titleItem << nameItem << abstractItem << cachedItem << filterItem);
193233
194234 // insert the available CRS into mAvailableCRS
195235 std::list<QString> currentCRSList;
@@ -202,14 +242,30 @@ void QgsWFSSourceSelect::capabilitiesReplyFinished()
202242
203243 if ( caps.featureTypes .count () > 0 )
204244 {
205- btnAdd->setEnabled ( true );
206- treeWidget->setCurrentItem ( treeWidget->topLevelItem ( 0 ) );
245+ treeView->resizeColumnToContents ( 0 );
246+ treeView->resizeColumnToContents ( 1 );
247+ treeView->resizeColumnToContents ( 2 );
248+ treeView->resizeColumnToContents ( 3 );
249+ for ( int i = 0 ; i < 2 ; i++ )
250+ {
251+ if ( treeView->columnWidth ( i ) > 300 )
252+ {
253+ treeView->setColumnWidth ( i, 300 );
254+ }
255+ }
256+ if ( treeView->columnWidth ( 2 ) > 150 )
257+ {
258+ treeView->setColumnWidth ( 2 , 150 );
259+ }
207260 btnChangeSpatialRefSys->setEnabled ( true );
261+ treeView->selectionModel ()->select ( mModel ->index ( 0 , 0 ), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows );
262+ treeView->setFocus ();
208263 }
209264 else
210265 {
211266 QMessageBox::information ( 0 , tr ( " No Layers" ), tr ( " capabilities document contained no layers." ) );
212- btnAdd->setEnabled ( false );
267+ mAddButton ->setEnabled ( false );
268+ mBuildQueryButton ->setEnabled ( false );
213269 }
214270}
215271
@@ -253,8 +309,10 @@ void QgsWFSSourceSelect::deleteEntryOfServerList()
253309void QgsWFSSourceSelect::connectToServer ()
254310{
255311 btnConnect->setEnabled ( false );
256- treeWidget->clear ();
257-
312+ if ( mModel )
313+ {
314+ mModel ->removeRows ( 0 , mModel ->rowCount () );
315+ }
258316 if ( mCapabilities )
259317 {
260318 mCapabilities ->requestCapabilities ();
@@ -264,16 +322,13 @@ void QgsWFSSourceSelect::connectToServer()
264322
265323void QgsWFSSourceSelect::addLayer ()
266324{
267- // get selected entry in lstWidget
268- QTreeWidgetItem* tItem = treeWidget-> currentItem ();
269- if ( !tItem )
325+ // get selected entry in treeview
326+ QModelIndex currentIndex = treeView-> selectionModel ()-> currentIndex ();
327+ if ( !currentIndex. isValid () )
270328 {
271329 return ;
272330 }
273331
274- QList<QTreeWidgetItem*> selectedItems = treeWidget->selectedItems ();
275- QList<QTreeWidgetItem*>::const_iterator sIt = selectedItems.constBegin ();
276-
277332 QgsOWSConnection connection ( " WFS" , cmbConnections->currentText () );
278333 QgsWFSCapabilities conn ( connection.uri ().encodedUri () );
279334
@@ -284,8 +339,6 @@ void QgsWFSSourceSelect::addLayer()
284339 QVariant extentVariant = property ( " MapExtent" );
285340 if ( extentVariant.isValid () )
286341 {
287- QString crs;
288- QgsCoordinateTransform xform;
289342 QString extentString = extentVariant.toString ();
290343 QStringList minMaxSplit = extentString.split ( " :" );
291344 if ( minMaxSplit.size () > 1 )
@@ -312,25 +365,82 @@ void QgsWFSSourceSelect::addLayer()
312365 }
313366 }
314367 }
368+
315369 // create layers that user selected from this WFS source
316- for ( ; sIt != selectedItems.constEnd (); ++sIt )
370+ QModelIndexList list = treeView->selectionModel ()->selectedRows ();
371+ for ( int i = 0 ; i < list.size (); i++ )
317372 { // add a wfs layer to the map
318- QString typeName = ( *sIt )->text ( 1 ); // WFS repository's name for layer
319- QString filter = ( *sIt )->text ( 4 ); // optional filter specified by user
373+ QModelIndex idx = mModelProxy ->mapToSource ( list[i] );
374+ if ( !idx.isValid () )
375+ {
376+ continue ;
377+ }
378+ int row = idx.row ();
379+ QString typeName = mModel ->item ( row, 1 )->text (); // WFS repository's name for layer
380+ QString titleName = mModel ->item ( row, 0 )->text (); // WFS type name title for layer name (if option is set)
381+ QString filter = mModel ->item ( row, 4 )->text (); // optional filter specified by user
382+ QString layerName = typeName;
383+ if ( cbxUseTitleLayerName->isChecked () && !titleName.isEmpty () )
384+ {
385+ layerName = titleName;
386+ }
387+ QgsDebugMsg ( " Layer " + typeName + " Filter is " + filter );
320388 // is "cache features" checked?
321- if (( * sIt )->checkState ( 3 ) == Qt::Checked )
389+ if ( mModel -> item ( row, 3 )->checkState () == Qt::Checked )
322390 { // yes: entire WFS layer will be retrieved and cached
323391 mUri = conn.uriGetFeature ( typeName, pCrsString, filter );
324392 }
325393 else
326394 { // no: include BBOX of current canvas extent in URI
327395 mUri = conn.uriGetFeature ( typeName, pCrsString, filter, extent );
328396 }
329- emit addWfsLayer ( mUri , typeName );
397+ emit addWfsLayer ( mUri , layerName );
330398 }
331399 accept ();
332400}
333401
402+ void QgsWFSSourceSelect::buildQuery ( const QModelIndex& index )
403+ {
404+ if ( !index.isValid () )
405+ {
406+ return ;
407+ }
408+ QModelIndex filterIndex = index.sibling ( index.row (), 4 );
409+ QString typeName = index.sibling ( index.row (), 1 ).data ().toString ();
410+
411+ // get available fields for wfs layer
412+ QgsWFSProvider p ( " " ); // bypasses most provider instantiation logic
413+ QgsOWSConnection connection ( " WFS" , cmbConnections->currentText () );
414+ QgsWFSCapabilities conn ( connection.uri ().encodedUri () );
415+ QString uri = conn.uriDescribeFeatureType ( typeName );
416+
417+ QgsFields fields;
418+ QString geometryAttribute;
419+ QGis::WkbType geomType;
420+ if ( p.describeFeatureType ( uri, geometryAttribute, fields, geomType ) != 0 )
421+ {
422+ return ;
423+ }
424+
425+ // show expression builder
426+ QgsExpressionBuilderDialog d ( 0 , filterIndex.data ().toString () );
427+
428+ // add available attributes to expression builder
429+ QgsExpressionBuilderWidget* w = d.expressionBuilder ();
430+ if ( !w )
431+ {
432+ return ;
433+ }
434+
435+ w->loadFieldNames ( fields );
436+
437+ if ( d.exec () == QDialog::Accepted )
438+ {
439+ QgsDebugMsg ( " Expression text = " + w->expressionText () );
440+ mModelProxy ->setData ( filterIndex, QVariant ( w->expressionText () ) );
441+ }
442+ }
443+
334444void QgsWFSSourceSelect::changeCRS ()
335445{
336446 if ( mProjectionSelector ->exec () )
@@ -342,11 +452,12 @@ void QgsWFSSourceSelect::changeCRS()
342452
343453void QgsWFSSourceSelect::changeCRSFilter ()
344454{
455+ QgsDebugMsg (" changeCRSFilter called" );
345456 // evaluate currently selected typename and set the CRS filter in mProjectionSelector
346- QTreeWidgetItem* currentTreeItem = treeWidget-> currentItem ();
347- if ( currentTreeItem )
457+ QModelIndex currentIndex = treeView-> selectionModel ()-> currentIndex ();
458+ if ( currentIndex. isValid () )
348459 {
349- QString currentTypename = currentTreeItem-> text ( 1 );
460+ QString currentTypename = currentIndex. sibling ( currentIndex. row (), 1 ). data (). toString ( );
350461 QgsDebugMsg ( QString ( " the current typename is: %1" ).arg ( currentTypename ) );
351462
352463 std::map<QString, std::list<QString> >::const_iterator crsIterator = mAvailableCRS .find ( currentTypename );
@@ -410,39 +521,47 @@ void QgsWFSSourceSelect::on_btnLoad_clicked()
410521 emit connectionsChanged ();
411522}
412523
413- void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked ( QTreeWidgetItem* item, int column )
524+ void QgsWFSSourceSelect::on_treeWidget_itemDoubleClicked ( const QModelIndex& index )
414525{
415- if ( item && column == 4 )
416- {
417- // get available fields for wfs layer
418- QgsWFSProvider p ( " " ); // bypasses most provider instantiation logic
419- QgsOWSConnection connection ( " WFS" , cmbConnections->currentText () );
420- QgsWFSCapabilities conn ( connection.uri ().encodedUri () );
421- QString uri = conn.uriDescribeFeatureType ( item->text ( 1 ) );
422-
423- QgsFields fields;
424- QString geometryAttribute;
425- QGis::WkbType geomType;
426- if ( p.describeFeatureType ( uri, geometryAttribute, fields, geomType ) != 0 )
427- {
428- return ;
429- }
526+ QgsDebugMsg ( " double click called" );
527+ buildQuery ( index );
528+ }
430529
431- // show expression builder
432- QgsExpressionBuilderDialog d ( 0 , item->text ( 3 ) );
530+ void QgsWFSSourceSelect::on_treeWidget_currentRowChanged ( const QModelIndex & current, const QModelIndex & previous)
531+ {
532+ Q_UNUSED ( previous )
533+ QgsDebugMsg ( " treeWidget_currentRowChanged called" );
534+ changeCRSFilter ();
535+ mBuildQueryButton ->setEnabled ( current.isValid () );
536+ mAddButton ->setEnabled ( current.isValid () );
537+ }
433538
434- // add available attributes to expression builder
435- QgsExpressionBuilderWidget* w = d.expressionBuilder ();
436- if ( !w )
437- {
438- return ;
439- }
539+ void QgsWFSSourceSelect::on_mBuildQueryButton_clicked ()
540+ {
541+ QgsDebugMsg ( " mBuildQueryButton click called" );
542+ buildQuery ( treeView->selectionModel ()->currentIndex () );
543+ }
440544
441- w->loadFieldNames ( fields );
545+ void QgsWFSSourceSelect::filterChanged (QString text)
546+ {
547+ QgsDebugMsg ( " WFS FeatureType filter changed to :" + text );
548+ QRegExp::PatternSyntax mySyntax = QRegExp::PatternSyntax ( QRegExp::RegExp );
549+ Qt::CaseSensitivity myCaseSensitivity = Qt::CaseInsensitive;
550+ QRegExp myRegExp ( text, myCaseSensitivity, mySyntax );
551+ mModelProxy ->setFilterRegExp ( myRegExp );
552+ mModelProxy ->sort ( mModelProxy ->sortColumn (), mModelProxy ->sortOrder () );
553+ }
442554
443- if ( d.exec () == QDialog::Accepted )
555+ QSize QgsWFSItemDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
556+ {
557+ QVariant indexData;
558+ indexData = index.data (Qt::DisplayRole);
559+ if ( indexData.isNull () )
444560 {
445- item-> setText ( 4 , w-> expressionText () );
561+ return QSize ( );
446562 }
447- }
563+ QString data = indexData.toString ();
564+ QSize size = option.fontMetrics .boundingRect (data).size ();
565+ size.setHeight (size.height () + 2 );
566+ return size;
448567}
0 commit comments