QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsowssourceselect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsowssourceselect.cpp - selector for WMS,WFS,WCS
3  -------------------
4  begin : 3 April 2005
5  copyright :
6  original : (C) 2005 by Brendan Morley email : morb at ozemail dot com dot au
7  wms search : (C) 2009 Mathias Walker <mwa at sourcepole.ch>, Sourcepole AG
8  wms-c support : (C) 2010 Juergen E. Fischer < jef at norbit dot de >, norBIT GmbH
9 
10  generalized : (C) 2012 Radim Blazek, based on qgswmssourceselect.cpp
11 
12  ***************************************************************************/
13 
14 /***************************************************************************
15  * *
16  * This program is free software; you can redistribute it and/or modify *
17  * it under the terms of the GNU General Public License as published by *
18  * the Free Software Foundation; either version 2 of the License, or *
19  * (at your option) any later version. *
20  * *
21  ***************************************************************************/
22 
23 #include "qgis.h" // GEO_EPSG_CRS_ID
24 #include "qgscontexthelp.h"
26 #include "qgsdatasourceuri.h"
28 #include "qgslogger.h"
30 #include "qgsmessageviewer.h"
31 #include "qgsnewhttpconnection.h"
33 #include "qgsproject.h"
34 #include "qgsproviderregistry.h"
35 #include "qgsowsconnection.h"
36 #include "qgsdataprovider.h"
37 #include "qgsowssourceselect.h"
39 
40 #include <QButtonGroup>
41 #include <QFileDialog>
42 #include <QRadioButton>
43 #include <QDomDocument>
44 #include <QHeaderView>
45 #include <QImageReader>
46 #include <QInputDialog>
47 #include <QMap>
48 #include <QMessageBox>
49 #include <QPicture>
50 #include <QSettings>
51 #include <QUrl>
52 #include <QValidator>
53 
54 #include <QNetworkRequest>
55 #include <QNetworkReply>
56 
57 QgsOWSSourceSelect::QgsOWSSourceSelect( QString service, QWidget * parent, Qt::WFlags fl, bool managerMode, bool embeddedMode )
58  : QDialog( parent, fl )
59  , mService( service )
60  , mManagerMode( managerMode )
61  , mEmbeddedMode( embeddedMode )
62  , mCurrentTileset( 0 )
63 {
64  setupUi( this );
65 
66  if ( mEmbeddedMode )
67  {
68  mDialogButtonBox->button( QDialogButtonBox::Close )->hide();
69  }
70 
71  mAddButton = mDialogButtonBox->button( QDialogButtonBox::Apply );
72  mAddButton->setText( tr( "&Add" ) );
73  mAddButton->setToolTip( tr( "Add selected layers to map" ) );
74  mAddButton->setEnabled( false );
75 
76  clearCRS();
77 
78  mTileWidthLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
79  mTileHeightLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
80  mFeatureCountLineEdit->setValidator( new QIntValidator( 0, 9999, this ) );
81 
82  mCacheComboBox->addItem( tr( "Always cache" ), QNetworkRequest::AlwaysCache );
83  mCacheComboBox->addItem( tr( "Prefer cache" ), QNetworkRequest::PreferCache );
84  mCacheComboBox->addItem( tr( "Prefer network" ), QNetworkRequest::PreferNetwork );
85  mCacheComboBox->addItem( tr( "Always network" ), QNetworkRequest::AlwaysNetwork );
86 
87  if ( !mManagerMode )
88  {
89  connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addClicked() ) );
90  //set the current project CRS if available
91  long currentCRS = QgsProject::instance()->readNumEntry( "SpatialRefSys", "/ProjectCRSID", -1 );
92  if ( currentCRS != -1 )
93  {
94  //convert CRS id to epsg
96  if ( currentRefSys.isValid() )
97  {
98  mSelectedCRS = currentRefSys.authid();
99  }
100  }
101  }
102  else
103  {
104  mTabWidget->removeTab( mTabWidget->indexOf( mLayerOrderTab ) );
105  mTabWidget->removeTab( mTabWidget->indexOf( mTilesetsTab ) );
106  mTimeWidget->hide();
107  mFormatWidget->hide();
108  mCRSWidget->hide();
109  mAddButton->hide();
110  mCacheWidget->hide();
111  }
112 
113  // set up the WMS connections we already know about
115 
116  QSettings settings;
117  QgsDebugMsg( "restoring geometry" );
118  restoreGeometry( settings.value( "/Windows/WMSSourceSelect/geometry" ).toByteArray() );
119 }
120 
122 {
123  QSettings settings;
124  QgsDebugMsg( "saving geometry" );
125  settings.setValue( "/Windows/WMSSourceSelect/geometry", saveGeometry() );
126 }
127 
129 {
130  mFormatComboBox->clear();
131  mFormatComboBox->setEnabled( false );
132 }
133 
135 {
136  QgsDebugMsg( "entered" );
137 
138  // A server may offer more similar formats, which are mapped
139  // to the same GDAL format, e.g. GeoTIFF and TIFF
140  // -> recreate always buttons for all available formats, enable supported
141 
142  clearFormats();
143 
144  if ( mProviderFormats.size() == 0 )
145  {
147  for ( int i = 0; i < mProviderFormats.size(); i++ )
148  {
149  // GDAL mime types may be image/tiff, image/png, ...
150  mMimeLabelMap.insert( mProviderFormats[i].format, mProviderFormats[i].label );
151  }
152  }
153 
154  // selectedLayersFormats may come in various forms:
155  // image/tiff, GTiff, GeoTIFF, TIFF, geotiff_int16, geotiff_rgb,
156  // PNG, GTOPO30, ARCGRID, IMAGEMOSAIC
157  // and even any string defined in server configuration, for example the
158  // value used in UMN Mapserver for OUTPUTFORMAT->NAME is used in
159  // WCS 1.0.0 SupportedFormats/Format
160 
161  // TODO: It is impossible to cover all possible formats comming from server
162  // -> enabled all formats, GDAL may be able to open them
163 
164  QMap<QString, QString> formatsMap;
165  formatsMap.insert( "geotiff", "tiff" );
166  formatsMap.insert( "gtiff", "tiff" );
167  formatsMap.insert( "tiff", "tiff" );
168  formatsMap.insert( "tif", "tiff" );
169  formatsMap.insert( "gif", "gif" );
170  formatsMap.insert( "jpeg", "jpeg" );
171  formatsMap.insert( "jpg", "jpeg" );
172  formatsMap.insert( "png", "png" );
173 
174  int preferred = -1;
175  QStringList layersFormats = selectedLayersFormats();
176  for ( int i = 0; i < layersFormats.size(); i++ )
177  {
178  QString format = layersFormats.value( i );
179  QgsDebugMsg( "server format = " + format );
180  QString simpleFormat = format.toLower().replace( "image/", "" ).replace( QRegExp( "_.*" ), "" );
181  QgsDebugMsg( "server simpleFormat = " + simpleFormat );
182  QString mimeFormat = "image/" + formatsMap.value( simpleFormat );
183  QgsDebugMsg( "server mimeFormat = " + mimeFormat );
184 
185  QString label = format;
186 
187  if ( mMimeLabelMap.contains( mimeFormat ) )
188  {
189  if ( format != mMimeLabelMap.value( mimeFormat ) )
190  {
191  // Append name of GDAL driver
192  label += " / " + mMimeLabelMap.value( mimeFormat );
193  }
194 
195  if ( simpleFormat.contains( "tif" ) ) // prefer *tif*
196  {
197  if ( preferred < 0 || simpleFormat.startsWith( "g" ) ) // prefer geotiff
198  {
199  preferred = i;
200  }
201  }
202  }
203  else
204  {
205  // We cannot always say that the format is not supported by GDAL because
206  // server can use strange names, but format itself is supported
207  QgsDebugMsg( QString( "format %1 unknown" ).arg( format ) );
208  }
209 
210  mFormatComboBox->insertItem( i, label );
211  }
212  // Set preferred
213  // TODO: all enabled for now, see above
214  preferred = preferred >= 0 ? preferred : 0;
215  mFormatComboBox->setCurrentIndex( preferred );
216 
217  mFormatComboBox->setEnabled( true );
218 }
219 
221 {
222  QgsDebugMsg( "entered" );
223  mTimeComboBox->clear();
224  mTimeComboBox->insertItems( 0, selectedLayersTimes() );
225  mTimeComboBox->setEnabled( !selectedLayersTimes().isEmpty() );
226 }
227 
229 {
230  mTimeComboBox->clear();
231  mTimeComboBox->setEnabled( false );
232 }
233 
235 {
236  mConnectionsComboBox->clear();
237  mConnectionsComboBox->addItems( QgsOWSConnection::connectionList( mService ) );
238 
240 
241  if ( mConnectionsComboBox->count() == 0 )
242  {
243  // No connections - disable various buttons
244  mConnectButton->setEnabled( false );
245  mEditButton->setEnabled( false );
246  mDeleteButton->setEnabled( false );
247  }
248  else
249  {
250  // Connections - enable various buttons
251  mConnectButton->setEnabled( true );
252  mEditButton->setEnabled( true );
253  mDeleteButton->setEnabled( true );
254  }
255 }
257 {
258  QgsNewHttpConnection *nc = new QgsNewHttpConnection( this, "/Qgis/connections-" + mService.toLower() + "/" );
259 
260  if ( nc->exec() )
261  {
263  emit connectionsChanged();
264  }
265 
266  delete nc;
267 }
268 
270 {
271  QgsNewHttpConnection *nc = new QgsNewHttpConnection( this, "/Qgis/connections-" + mService.toLower() + "/", mConnectionsComboBox->currentText() );
272 
273  if ( nc->exec() )
274  {
276  emit connectionsChanged();
277  }
278 
279  delete nc;
280 }
281 
283 {
284  QString msg = tr( "Are you sure you want to remove the %1 connection and all associated settings?" )
285  .arg( mConnectionsComboBox->currentText() );
286  QMessageBox::StandardButton result = QMessageBox::information( this, tr( "Confirm Delete" ), msg, QMessageBox::Ok | QMessageBox::Cancel );
287  if ( result == QMessageBox::Ok )
288  {
289  QgsOWSConnection::deleteConnection( mService, mConnectionsComboBox->currentText() );
290  mConnectionsComboBox->removeItem( mConnectionsComboBox->currentIndex() ); // populateConnectionList();
292  emit connectionsChanged();
293  }
294 }
295 
297 {
299  dlg.exec();
300 }
301 
303 {
304  QString fileName = QFileDialog::getOpenFileName( this, tr( "Load connections" ), ".",
305  tr( "XML files (*.xml *XML)" ) );
306  if ( fileName.isEmpty() )
307  {
308  return;
309  }
310 
312  dlg.exec();
314  emit connectionsChanged();
315 }
316 
318  int id,
319  const QStringList &names,
320  QMap<int, QgsNumericSortTreeWidgetItem *> &items,
321  int &layerAndStyleCount,
322  const QMap<int, int> &layerParents,
323  const QMap<int, QStringList> &layerParentNames )
324 {
325  QgsDebugMsg( QString( "id = %1 layerAndStyleCount = %2 names = %3 " ).arg( id ).arg( layerAndStyleCount ).arg( names.join( "," ) ) );
326  if ( items.contains( id ) )
327  return items[id];
328 
329 
331  if ( layerParents.contains( id ) )
332  {
333  // it has parent -> create first its parent
334  int parent = layerParents[ id ];
335  item = new QgsNumericSortTreeWidgetItem( createItem( parent, layerParentNames[ parent ], items, layerAndStyleCount, layerParents, layerParentNames ) );
336  }
337  else
338  item = new QgsNumericSortTreeWidgetItem( mLayersTreeWidget );
339 
340  item->setText( 0, QString::number( ++layerAndStyleCount ) );
341  item->setText( 1, names[0].simplified() );
342  item->setText( 2, names[1].simplified() );
343  item->setText( 3, names[2].simplified() );
344  item->setToolTip( 3, "<font color=black>" + names[2].simplified() + "</font>" );
345 
346  items[ id ] = item;
347 
348  return item;
349 }
350 
352 {
353 }
354 
356 {
357  QgsDebugMsg( "entered" );
358 
359  mLayersTreeWidget->clear();
360  clearFormats();
361  clearTimes();
362  clearCRS();
363 
364  mConnName = mConnectionsComboBox->currentText();
365 
366  QgsOWSConnection connection( mService, mConnectionsComboBox->currentText() );
367  //QgsDataProvider *theProvider = connection.provider( );
368  mConnectionInfo = connection.connectionInfo();
369  mUri = connection.uri();
370 
371  QApplication::setOverrideCursor( Qt::WaitCursor );
372 
373  QgsDebugMsg( "call populateLayerList" );
375 
376  QApplication::restoreOverrideCursor();
377 }
378 
380 {
381  QgsDebugMsg( "entered" );
382 }
383 
384 void QgsOWSSourceSelect::enableLayersForCrs( QTreeWidgetItem * )
385 {
386 }
387 
389 {
390  QStringList layers;
391  foreach ( QTreeWidgetItem *item, mLayersTreeWidget->selectedItems() )
392  {
393  QString layer = item->data( 0, Qt::UserRole + 0 ).toString();
394  if ( !layer.isEmpty() )
395  layers << layer;
396  }
397 
399  mySelector->setMessage();
401 
402  QString myDefaultCrs = QgsProject::instance()->readEntry( "SpatialRefSys", "/ProjectCrs", GEO_EPSG_CRS_AUTHID );
403  QgsCoordinateReferenceSystem defaultCRS;
404  if ( defaultCRS.createFromOgcWmsCrs( myDefaultCrs ) )
405  {
406  mySelector->setSelectedCrsId( defaultCRS.srsid() );
407  }
408 
409  if ( !mySelector->exec() )
410  return;
411 
412  mSelectedCRS = mySelector->selectedAuthId();
413  delete mySelector;
414 
415  mSelectedCRSLabel->setText( descriptionForAuthId( mSelectedCRS ) );
416 
417  for ( int i = 0; i < mLayersTreeWidget->topLevelItemCount(); i++ )
418  {
419  enableLayersForCrs( mLayersTreeWidget->topLevelItem( i ) );
420  }
421 
422  updateButtons();
423 }
424 
426 {
427 }
428 
430 {
431  QgsDebugMsg( "Entered" );
432  clearCRS();
434  mCRSLabel->setText( tr( "Coordinate Reference System (%n available)", "crs count", mSelectedLayersCRSs.count() ) + ":" );
435 
436  mChangeCRSButton->setDisabled( mSelectedLayersCRSs.isEmpty() );
437 
438  if ( !mSelectedLayersCRSs.isEmpty() )
439  {
440  // check whether current CRS is supported
441  // if not, use one of the available CRS
442  QString defaultCRS;
443  QSet<QString>::const_iterator it = mSelectedLayersCRSs.begin();
444  for ( ; it != mSelectedLayersCRSs.end(); it++ )
445  {
446  if ( it->compare( mSelectedCRS, Qt::CaseInsensitive ) == 0 )
447  break;
448 
449  // save first CRS in case the current CRS is not available
450  if ( it == mSelectedLayersCRSs.begin() )
451  defaultCRS = *it;
452 
453  // prefer value of DEFAULT_GEO_EPSG_CRS_ID if available
454  if ( *it == GEO_EPSG_CRS_AUTHID )
455  defaultCRS = *it;
456  }
457 
458  if ( it == mSelectedLayersCRSs.end() )
459  {
460  // not found
461  mSelectedCRS = defaultCRS;
462  }
463  mSelectedCRSLabel->setText( descriptionForAuthId( mSelectedCRS ) );
464  mChangeCRSButton->setEnabled( true );
465  }
466  QgsDebugMsg( "mSelectedCRS = " + mSelectedCRS );
467 }
468 
470 {
471  mCRSLabel->setText( tr( "Coordinate Reference System" ) + ":" );
472  mSelectedCRS = "";
473  mSelectedCRSLabel->setText( "" );
474  mChangeCRSButton->setEnabled( false );
475 }
476 
478 {
479  Q_UNUSED( item );
480 
481  QTableWidgetItem *rowItem = mTilesetsTableWidget->item( mTilesetsTableWidget->currentRow(), 0 );
482  bool wasSelected = mCurrentTileset == rowItem;
483 
484  mTilesetsTableWidget->blockSignals( true );
485  mTilesetsTableWidget->clearSelection();
486  if ( !wasSelected )
487  {
488  QgsDebugMsg( QString( "selecting current row %1" ).arg( mTilesetsTableWidget->currentRow() ) );
489  mTilesetsTableWidget->selectRow( mTilesetsTableWidget->currentRow() );
490  mCurrentTileset = rowItem;
491  }
492  else
493  {
494  mCurrentTileset = 0;
495  }
496  mTilesetsTableWidget->blockSignals( false );
497 
498  updateButtons();
499 }
500 
501 
502 
504 {
505  return mConnName;
506 }
507 
509 {
510  return mConnectionInfo;
511 }
512 
514 {
515  return selectedLayersFormats().value( mFormatComboBox->currentIndex() );
516 }
517 
518 QNetworkRequest::CacheLoadControl QgsOWSSourceSelect::selectedCacheLoadControl()
519 {
520  int cache = mCacheComboBox->itemData( mCacheComboBox->currentIndex() ).toInt();
521  return static_cast<QNetworkRequest::CacheLoadControl>( cache );
522 }
523 
525 {
526  return mSelectedCRS;
527 }
528 
530 {
531  return mTimeComboBox->currentText();
532 }
533 
535 {
536  QString toSelect = QgsOWSConnection::selectedConnection( mService );
537 
538  mConnectionsComboBox->setCurrentIndex( mConnectionsComboBox->findText( toSelect ) );
539 
540  if ( mConnectionsComboBox->currentIndex() < 0 )
541  {
542  if ( toSelect.isNull() )
543  mConnectionsComboBox->setCurrentIndex( 0 );
544  else
545  mConnectionsComboBox->setCurrentIndex( mConnectionsComboBox->count() - 1 );
546  }
547  QgsOWSConnection::setSelectedConnection( mService, mConnectionsComboBox->currentText() );
548 }
549 
550 void QgsOWSSourceSelect::showStatusMessage( QString const &theMessage )
551 {
552  mStatusLabel->setText( theMessage );
553 
554  // update the display of this widget
555  update();
556 }
557 
558 
559 void QgsOWSSourceSelect::showError( QString const &theTitle, QString const &theFormat, QString const &theError )
560 {
561  QgsMessageViewer * mv = new QgsMessageViewer( this );
562  mv->setWindowTitle( theTitle );
563 
564  if ( theFormat == "text/html" )
565  {
566  mv->setMessageAsHtml( theError );
567  }
568  else
569  {
570  mv->setMessageAsPlainText( tr( "Could not understand the response:\n%1" ).arg( theError ) );
571  }
572  mv->showMessage( true ); // Is deleted when closed
573 }
574 
576 {
577  // Remember which server was selected.
578  QgsOWSConnection::setSelectedConnection( mService, mConnectionsComboBox->currentText() );
579 }
580 
582 {
584 }
585 
587 {
588  if ( mCrsNames.contains( authId ) )
589  return mCrsNames[ authId ];
590 
592  qgisSrs.createFromOgcWmsCrs( authId );
593  mCrsNames.insert( authId, qgisSrs.description() );
594  return qgisSrs.description();
595 }
596 
598 {
599  QMap<QString, QString> exampleServers;
600  exampleServers["DM Solutions GMap"] = "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap";
601  exampleServers["Lizardtech server"] = "http://wms.lizardtech.com/lizardtech/iserv/ows";
602  // Nice to have the qgis users map, but I'm not sure of the URL at the moment.
603  // exampleServers["Qgis users map"] = "http://qgis.org/wms.cgi";
604 
605  QSettings settings;
606  settings.beginGroup( "/Qgis/connections-" + mService.toLower() );
607  QMap<QString, QString>::const_iterator i = exampleServers.constBegin();
608  for ( ; i != exampleServers.constEnd(); ++i )
609  {
610  // Only do a server if it's name doesn't already exist.
611  QStringList keys = settings.childGroups();
612  if ( !keys.contains( i.key() ) )
613  {
614  QString path = i.key();
615  settings.setValue( path + "/url", i.value() );
616  }
617  }
618  settings.endGroup();
620 
621  QMessageBox::information( this, tr( "WMS proxies" ), "<p>" + tr( "Several WMS servers have "
622  "been added to the server list. Note that if "
623  "you access the internet via a web proxy, you will "
624  "need to set the proxy settings in the QGIS options dialog." ) + "</p>" );
625 }
626 
627 void QgsOWSSourceSelect::addWMSListRow( const QDomElement& item, int row )
628 {
629  QDomElement title = item.firstChildElement( "title" );
630  addWMSListItem( title, row, 0 );
631  QDomElement description = item.firstChildElement( "description" );
632  addWMSListItem( description, row, 1 );
633  QDomElement link = item.firstChildElement( "link" );
634  addWMSListItem( link, row, 2 );
635 }
636 
637 void QgsOWSSourceSelect::addWMSListItem( const QDomElement& el, int row, int column )
638 {
639  if ( !el.isNull() )
640  {
641  QTableWidgetItem* tableItem = new QTableWidgetItem( el.text() );
642  // TODO: add linebreaks to long tooltips?
643  tableItem->setToolTip( el.text() );
644  mSearchTableWidget->setItem( row, column, tableItem );
645  }
646 }
647 
649 {
650  // clear results
651  mSearchTableWidget->clearContents();
652  mSearchTableWidget->setRowCount( 0 );
653 
654  // disable Add WMS button
655  mSearchAddButton->setEnabled( false );
656 
657  QApplication::setOverrideCursor( Qt::WaitCursor );
658 
659  QSettings settings;
660  // geopole.org (geopole.ch) 25.4.2012 : 503 Service Unavailable, archive: Recently added 20 Jul 2011
661  QString mySearchUrl = settings.value( "/qgis/WMSSearchUrl", "http://geopole.org/wms/search?search=%1&type=rss" ).toString();
662  QUrl url( mySearchUrl.arg( mSearchTermLineEdit->text() ) );
663  QgsDebugMsg( url.toString() );
664 
665  QNetworkReply *r = QgsNetworkAccessManager::instance()->get( QNetworkRequest( url ) );
666  connect( r, SIGNAL( finished() ), SLOT( searchFinished() ) );
667 }
668 
670 {
671  QApplication::restoreOverrideCursor();
672 
673  QNetworkReply *r = qobject_cast<QNetworkReply *>( sender() );
674  if ( !r )
675  return;
676 
677  if ( r->error() == QNetworkReply::NoError )
678  {
679  // parse results
680  QDomDocument doc( "RSS" );
681  QByteArray res = r->readAll();
682  QString error;
683  int line, column;
684  if ( doc.setContent( res, &error, &line, &column ) )
685  {
686  QDomNodeList list = doc.elementsByTagName( "item" );
687  mSearchTableWidget->setRowCount( list.size() );
688  for ( int i = 0; i < list.size(); i++ )
689  {
690  if ( list.item( i ).isElement() )
691  {
692  QDomElement item = list.item( i ).toElement();
693  addWMSListRow( item, i );
694  }
695  }
696 
697  mSearchTableWidget->resizeColumnsToContents();
698  }
699  else
700  {
701  QgsDebugMsg( "setContent failed" );
702  showStatusMessage( tr( "parse error at row %1, column %2: %3" ).arg( line ).arg( column ).arg( error ) );
703  }
704  }
705  else
706  {
707  showStatusMessage( tr( "network error: %1" ).arg( r->error() ) );
708  }
709 
710  r->deleteLater();
711 }
712 
714 {
715  mSearchAddButton->setEnabled( mSearchTableWidget->currentRow() != -1 );
716 }
717 
719 {
720  QList<QTreeWidgetItem *> selectionList = mLayerOrderTreeWidget->selectedItems();
721  if ( selectionList.size() < 1 )
722  {
723  return;
724  }
725  int selectedIndex = mLayerOrderTreeWidget->indexOfTopLevelItem( selectionList[0] );
726  if ( selectedIndex < 1 )
727  {
728  return; //item not existing or already on top
729  }
730 
731  QTreeWidgetItem* selectedItem = mLayerOrderTreeWidget->takeTopLevelItem( selectedIndex );
732  mLayerOrderTreeWidget->insertTopLevelItem( selectedIndex - 1, selectedItem );
733  mLayerOrderTreeWidget->clearSelection();
734  selectedItem->setSelected( true );
735 }
736 
738 {
739  QList<QTreeWidgetItem *> selectionList = mLayerOrderTreeWidget->selectedItems();
740  if ( selectionList.size() < 1 )
741  {
742  return;
743  }
744  int selectedIndex = mLayerOrderTreeWidget->indexOfTopLevelItem( selectionList[0] );
745  if ( selectedIndex < 0 || selectedIndex > mLayerOrderTreeWidget->topLevelItemCount() - 2 )
746  {
747  return; //item not existing or already at bottom
748  }
749 
750  QTreeWidgetItem* selectedItem = mLayerOrderTreeWidget->takeTopLevelItem( selectedIndex );
751  mLayerOrderTreeWidget->insertTopLevelItem( selectedIndex + 1, selectedItem );
752  mLayerOrderTreeWidget->clearSelection();
753  selectedItem->setSelected( true );
754 }
755 
756 QList<QgsOWSSourceSelect::SupportedFormat> QgsOWSSourceSelect::providerFormats()
757 {
758  return QList<SupportedFormat>();
759 }
760 
762 {
763  return QStringList();
764 }
765 
767 {
768  return QStringList();
769 }
770 
772 {
773  return QStringList();
774 }
775 
777 {
778 }