Improvements to WMS - users can now see what projections are available for their chosen layers. (However, the projection they select is not hooked up to anything yet.) Also, the projection selector now shows groupings in italics, for better visual distinction.

* QgsServerSourceSelect is now hooked up to QgsLayerProjectionSelector.
* QgsLayerProjectionSelector and QgsProjectionSelector can now filter their results by a list of WMS-format CRSs (Coordinate Reference Systems).
* QgsProjectionSelector now delays the calling of getProjList() and getUserProjList() until the filter has a chance to be set (using the new setOgcWmsCrsFilter).
* The projection databases now have epsg added to the view so that it too can be searched upon.
* Early works on the WMS Provider itself to accept new CRSs.  Not hooked up to anything useful yet though.



git-svn-id: http://svn.osgeo.org/qgis/trunk@4937 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
morb_au 2006-03-02 13:40:04 +00:00
parent a303b57842
commit 90f7f6b8f2
11 changed files with 643 additions and 89 deletions

Binary file not shown.

Binary file not shown.

View File

@ -23,7 +23,8 @@
* \class QgsLayerProjectionSelector - Set user layerprojectionselector and preferences
* Constructor
*/
QgsLayerProjectionSelector::QgsLayerProjectionSelector(QWidget *parent, Qt::WFlags fl)
QgsLayerProjectionSelector::QgsLayerProjectionSelector(QWidget *parent,
Qt::WFlags fl)
: QDialog(parent, fl)
{
setupUi(this);
@ -40,10 +41,12 @@ void QgsLayerProjectionSelector::setSelectedSRSName(QString theName)
{
projectionSelector->setSelectedSRSName(theName);
}
void QgsLayerProjectionSelector::setSelectedSRSID(long theID)
{
projectionSelector->setSelectedSRSID(theID);
}
QString QgsLayerProjectionSelector::getCurrentProj4String()
{
//@NOTE dont use getSelectedWKT as that just returns the name part!
@ -55,3 +58,14 @@ long QgsLayerProjectionSelector::getCurrentSRSID()
//@NOTE dont use getSelectedWKT as that just returns the name part!
return projectionSelector->getCurrentSRSID();
}
long QgsLayerProjectionSelector::getCurrentEpsg()
{
return projectionSelector->getCurrentEpsg();
}
void QgsLayerProjectionSelector::setOgcWmsCrsFilter(QSet<QString> crsFilter)
{
projectionSelector->setOgcWmsCrsFilter(crsFilter);
}

View File

@ -20,10 +20,14 @@
#define QGSLAYERPROJECTIONSELECTOR_H
#include "ui_qgslayerprojectionselectorbase.h"
#include "qgisgui.h"
#include <QSet>
/**
* \class QgsLayerProjectionSelector
* \brief Set Projection system for a layer
*/
class QgsLayerProjectionSelector : public QDialog, private Ui::QgsLayerProjectionSelectorBase
{
Q_OBJECT;
@ -31,15 +35,37 @@ class QgsLayerProjectionSelector : public QDialog, private Ui::QgsLayerProjectio
/**
* Constructor
*/
QgsLayerProjectionSelector(QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
QgsLayerProjectionSelector(QWidget *parent = 0,
Qt::WFlags fl = QgisGui::ModalDialogFlags);
//! Destructor
~QgsLayerProjectionSelector();
public slots:
QString getCurrentProj4String();
long getCurrentSRSID();
long getCurrentEpsg();
void setSelectedSRSName(QString theName);
void setSelectedSRSID(long theID);
/**
* \brief filters this dialog by the given CRSs
*
* Sets this dialog to filter the available projections to those listed
* by the given Coordinate Reference Systems.
*
* \param crsFilter a list of OGC Coordinate Reference Systems to filter the
* list of projections by. This is useful in (e.g.) WMS situations
* where you just want to offer what the WMS server can support.
*
* \note This function only deals with EPSG labels only at this time.
*
* \warning This function's behaviour is undefined if it is called after the dialog is shown.
*/
void setOgcWmsCrsFilter(QSet<QString> crsFilter);
};
#endif // #ifndef QGSLAYERPROJECTIONSELECTOR_H

View File

@ -18,12 +18,16 @@
#include "qgsserversourceselect.h"
#include "qgslayerprojectionselector.h"
#include "qgsnewhttpconnection.h"
#include "qgsnumericsortlistviewitem.h"
#include "qgsproviderregistry.h"
#include "../providers/wms/qgswmsprovider.h"
#include "qgscontexthelp.h"
#include "qgsproject.h"
#include <QMessageBox>
#include <QPicture>
#include <QSettings>
@ -33,7 +37,9 @@
QgsServerSourceSelect::QgsServerSourceSelect(QgisApp * app, QWidget * parent, Qt::WFlags fl)
: QDialog(parent, fl),
qgisApp(app)
qgisApp(app),
wmsProvider(0),
m_Epsg(0)
{
setupUi(this);
connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject()));
@ -153,7 +159,7 @@ void QgsServerSourceSelect::populateLayerList(QgsWmsProvider* wmsProvider)
{
#ifdef QGISDEBUG
std::cout << "QgsServerSourceSelect::populateLayerList: got layer name " << layer->name.toLocal8Bit().data() << " and title '" << layer->title.toLocal8Bit().data() << "'." << std::endl;
// std::cout << "QgsServerSourceSelect::populateLayerList: got layer name " << layer->name.toLocal8Bit().data() << " and title '" << layer->title.toLocal8Bit().data() << "'." << std::endl;
#endif
layerAndStyleCount++;
@ -266,6 +272,36 @@ void QgsServerSourceSelect::populateImageEncodingGroup(QgsWmsProvider* wmsProvid
}
std::set<QString> QgsServerSourceSelect::crsForSelection()
{
std::set<QString> crsCandidates;;
QStringList::const_iterator i;
for (i = m_selectedLayers.constBegin(); i != m_selectedLayers.constEnd(); ++i)
{
/*
for ( int j = 0; j < ilayerProperty.boundingBox.size(); i++ )
{
#ifdef QGISDEBUG
std::cout << "QgsWmsProvider::parseLayer: testing bounding box CRS which is "
<< layerProperty.boundingBox[i].crs.toLocal8Bit().data() << "." << std::endl;
#endif
if ( layerProperty.boundingBox[i].crs == DEFAULT_LATLON_CRS )
{
extentForLayer[ layerProperty.name ] =
layerProperty.boundingBox[i].box;
}
}
if
cout << (*i).ascii() << endl;*/
}
}
void QgsServerSourceSelect::on_btnConnect_clicked()
{
// populate the table list
@ -301,19 +337,26 @@ void QgsServerSourceSelect::on_btnConnect_clicked()
#ifdef QGISDEBUG
std::cout << "QgsServerSourceSelect::serverConnect: Connection info: '" << m_connInfo.toLocal8Bit().data() << "'." << std::endl;
#endif
// TODO: Create and bind to data provider
// load the server data provider plugin
QgsProviderRegistry * pReg = QgsProviderRegistry::instance();
QgsWmsProvider* wmsProvider =
wmsProvider =
(QgsWmsProvider*) pReg->getProvider( "wms", m_connInfo );
connect(wmsProvider, SIGNAL(setStatus(QString)), this, SLOT(showStatusMessage(QString)));
if (wmsProvider)
{
connect(wmsProvider, SIGNAL(setStatus(QString)), this, SLOT(showStatusMessage(QString)));
populateLayerList(wmsProvider);
populateLayerList(wmsProvider);
}
else
{
// TODO: Let user know we couldn't initialise the WMS provider
}
}
@ -330,6 +373,43 @@ void QgsServerSourceSelect::on_btnAdd_clicked()
}
void QgsServerSourceSelect::on_btnChangeSpatialRefSys_clicked()
{
if (!wmsProvider)
{
return;
}
QSet<QString> crsFilter = wmsProvider->supportedCrsForLayers(m_selectedLayers);
QgsLayerProjectionSelector * mySelector =
new QgsLayerProjectionSelector(this);
mySelector->setOgcWmsCrsFilter(crsFilter);
long myDefaultSRS = QgsProject::instance()->readNumEntry("SpatialRefSys", "/ProjectSRSID", GEOSRS_ID);
mySelector->setSelectedSRSID(myDefaultSRS);
if (mySelector->exec())
{
// TODO: assign EPSG back to the WMS provider
m_Epsg = mySelector->getCurrentEpsg();
}
else
{
// NOOP
}
labelSpatialRefSys->setText( mySelector->getCurrentProj4String() );
delete mySelector;
// update the display of this widget
this->update();
}
/**
* This function is used to:
* 1. Store the list of selected layers and visual styles as appropriate.
@ -347,10 +427,9 @@ void QgsServerSourceSelect::on_lstLayers_selectionChanged()
// Iterate through the layers
Q3ListViewItemIterator it( lstLayers );
while ( it.current() )
while ( it.current() )
{
Q3ListViewItem *item = it.current();
++it;
// save the name of the layer (in case only one of its styles was
// selected)
@ -391,6 +470,18 @@ void QgsServerSourceSelect::on_lstLayers_selectionChanged()
#endif
}
++it;
}
// If we got some selected items, let the user play with projections
if (newSelectedLayers.count() > 0)
{
btnChangeSpatialRefSys->setEnabled(TRUE);
}
else
{
btnChangeSpatialRefSys->setEnabled(FALSE);
}
m_selectedLayers = newSelectedLayers;
@ -434,6 +525,19 @@ QString QgsServerSourceSelect::selectedImageEncoding()
}
QString QgsServerSourceSelect::selectedCrs()
{
if (m_Epsg)
{
return QString("EPSG:%1")
.arg(m_Epsg);
}
else
{
return QString();
}
}
void QgsServerSourceSelect::showStatusMessage(QString const & theMessage)
{
labelStatus->setText(theMessage);
@ -443,5 +547,4 @@ void QgsServerSourceSelect::showStatusMessage(QString const & theMessage)
}
// ENDS

View File

@ -23,6 +23,7 @@
#include <vector>
#include <map>
#include <set>
class QgisApp;
class QgsWmsProvider;
@ -62,6 +63,10 @@ public:
//! String containing the MIME type of the preferred image encoding
QString selectedImageEncoding();
//! String containing the selected WMS-format CRS
QString selectedCrs();
public slots:
//! Opens the create connection dialog to build a new connection
@ -79,6 +84,9 @@ public slots:
//! Determines the layers the user selected and closes the dialog
void on_btnAdd_clicked();
//! Opens the Spatial Reference System dialog.
void on_btnChangeSpatialRefSys_clicked();
//! Opens help application
void on_btnHelp_clicked();
@ -97,10 +105,14 @@ private:
//! Populate the image encoding button group - private for now.
void populateImageEncodingGroup(QgsWmsProvider* wmsProvider);
//! Returns the common CRSs for the selected layers.
std::set<QString> crsForSelection();
QString m_connName;
QString m_connInfo;
QStringList m_selectedLayers;
QStringList m_selectedStylesForSelectedLayers;
long m_Epsg;
std::map<QString, QString> m_selectedStyleIdForLayer;
@ -113,6 +125,9 @@ private:
//! The widget that controls the image format radio buttons
QButtonGroup* m_imageFormatBtns;
//! The WMS provider that retreives information for this dialog
QgsWmsProvider * wmsProvider;
static const int context_id = 710979116;
};

View File

@ -183,7 +183,38 @@ std::vector<QgsWmsLayerProperty> QgsWmsProvider::supportedLayers()
}
QSet<QString> QgsWmsProvider::supportedCrsForLayers(QStringList const & layers)
{
QSet<QString> crsCandidates;
QStringList::const_iterator i;
for (i = layers.constBegin(); i != layers.constEnd(); ++i)
{
std::vector<QString> crsVector = crsForLayer[*i];
QSet<QString> crsSet;
// convert std::vector to std::set for set comparisons
for (int j = 0; j < crsVector.size(); j++)
{
crsSet.insert( crsVector[j] );
}
// first time through?
if ( i == layers.constBegin() )
{
// do initial population of set
crsCandidates = crsSet;
}
else
{
// do lowest common denominator (set intersection)
crsCandidates.intersect(crsSet);
}
}
return crsCandidates;
}
size_t QgsWmsProvider::layerCount() const
@ -192,8 +223,6 @@ size_t QgsWmsProvider::layerCount() const
} // QgsWmsProvider::layerCount()
void QgsWmsProvider::addLayers(QStringList const & layers,
QStringList const & styles)
{
@ -261,6 +290,16 @@ void QgsWmsProvider::setImageEncoding(QString const & mimeType)
}
void QgsWmsProvider::setImageCrs(QString const & crs)
{
#ifdef QGISDEBUG
std::cout << "QgsWmsProvider::setImageCrs: Setting image CRS to " << crs.toLocal8Bit().data() << "." <<
std::endl;
#endif
imageCrs = crs;
}
QImage* QgsWmsProvider::draw(QgsRect const & viewExtent, int pixelWidth, int pixelHeight)
{
#ifdef QGISDEBUG
@ -1311,6 +1350,10 @@ void QgsWmsProvider::parseLayer(QDomElement const & e, QgsWmsLayerProperty& laye
// TODO: Save this somewhere
// Store the available Coordinate Reference Systems for the layer so that it
// can be combined with others later in supportedCrsForLayers()
crsForLayer[ layerProperty.name ] = layerProperty.crs;
// Store the WGS84 (CRS:84) extent so that it can be combined with others later
// in calculateExtent()

View File

@ -24,6 +24,8 @@
#include <map>
#include <vector>
#include <QSet>
#include "qgsrasterdataprovider.h"
#include "qgsrect.h"
@ -356,10 +358,18 @@ public:
virtual ~QgsWmsProvider();
// TODO: Document this better, make static
/** \brief Returns a list of the supported layers of this WMS
/** \brief Returns a list of the supported layers of the WMS server
*/
virtual std::vector<QgsWmsLayerProperty> supportedLayers();
// TODO: Document this better
/** \brief Returns a list of the supported CRSs of the given layers
* \note Since WMS can specify CRSs per layer, this may change depending
on which layers are specified! The "lowest common denominator" between
all specified layers is returned.
*/
virtual QSet<QString> supportedCrsForLayers(QStringList const & layers);
/**
* Add the list of WMS layer names to be rendered by this server
*/
@ -380,17 +390,22 @@ public:
* (in order from bottom to top)
* \note layers must have been previously added.
*/
void setLayerOrder(QStringList const & layers);
void setLayerOrder(QStringList const & layers);
/**
* Set the visibility of the given sublayer name
*/
void setSubLayerVisibility(QString const & name, bool vis);
void setSubLayerVisibility(QString const & name, bool vis);
/**
* Set the image encoding (as a MIME type) used in the transfer from the WMS server
*/
void setImageEncoding(QString const & mimeType);
void setImageEncoding(QString const & mimeType);
/**
* Set the image projection (in WMS CRS format) used in the transfer from the WMS server
*/
void setImageCrs(QString const & crs);
// TODO: Document this better.
/** \brief Renders the layer as an image
@ -654,7 +669,12 @@ private:
* extents per layer (in WMS CRS:84 datum)
*/
std::map<QString, QgsRect> extentForLayer;
/**
* available CRSs per layer
*/
std::map<QString, std::vector<QString> > crsForLayer;
/**
* Active sublayers managed by this provider in a draw function, in order from bottom to top
* (some may not be visible in a draw function, cf. activeSubLayerVisibility)
@ -673,6 +693,11 @@ private:
*/
QString imageMimeType;
/**
* WMS CRS type of the image CRS used from the WMS server
*/
QString imageCrs;
/**
* The previously retrieved image from the WMS server.
* This can be reused if draw() is called consecutively

View File

@ -9,7 +9,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
<height>505</height>
</rect>
</property>
<property name="windowTitle" >
@ -240,6 +240,21 @@
</layout>
</widget>
</item>
<item row="5" column="0" colspan="4" >
<widget class="QLabel" name="labelStatus" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>Ready</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4" >
<widget class="QGroupBox" name="btnGrpSrs" >
<property name="title" >
@ -252,10 +267,17 @@
<property name="spacing" >
<number>6</number>
</property>
<item>
<widget class="QLabel" name="labelSpatialRefSys" >
<property name="text" >
<string>CRS is </string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioButtonEspg4326" >
<property name="text" >
<string>ESPG:4326</string>
<string>EPSG:4326</string>
</property>
</widget>
</item>
@ -275,24 +297,19 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnChangeSpatialRefSys" >
<property name="enabled" >
<bool>false</bool>
</property>
<property name="text" >
<string>Change ...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="4" >
<widget class="QLabel" name="labelStatus" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<string>Ready</string>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11" />

View File

@ -26,8 +26,15 @@
#include <QHeaderView>
#include <QResizeEvent>
QgsProjectionSelector::QgsProjectionSelector( QWidget* parent , const char* name , Qt::WFlags fl )
: QWidget(parent, fl)
QgsProjectionSelector::QgsProjectionSelector(QWidget* parent,
const char * name,
Qt::WFlags fl)
: QWidget(parent, fl),
mProjListDone(FALSE),
mUserProjListDone(FALSE),
mSRSNameSelectionPending(FALSE),
mSRSIDSelectionPending(FALSE)
{
setupUi(this);
connect(lstCoordinateSystems, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
@ -37,57 +44,177 @@ QgsProjectionSelector::QgsProjectionSelector( QWidget* parent , const char* name
// Get the full path name to the sqlite3 spatial reference database.
mSrsDatabaseFileName = QgsApplication::srsDbFilePath();
lstCoordinateSystems->header()->setResizeMode(1,QHeaderView::Stretch);
// Populate the projection list view
getProjList();
getUserProjList();
}
QgsProjectionSelector::~QgsProjectionSelector()
{}
void QgsProjectionSelector::resizeEvent ( QResizeEvent * theEvent )
{
lstCoordinateSystems->header()->resizeSection(0,(theEvent->size().width()-120));
lstCoordinateSystems->header()->resizeSection(1,120);
}
void QgsProjectionSelector::setSelectedSRSName(QString theSRSNAme)
{
//get the srid given the wkt so we can pick the correct list item
#ifdef QGISDEBUG
std::cout << "QgsProjectionSelector::setSelectedSRSName called with \n" << theSRSNAme.toLocal8Bit().data() << std::endl;
#endif
QList<QTreeWidgetItem*> nodes = lstCoordinateSystems->findItems(theSRSNAme, Qt::MatchExactly|Qt::MatchRecursive, 0);
if (nodes.count() > 0)
void QgsProjectionSelector::showEvent ( QShowEvent * theEvent )
{
// ensure the projection list view is actually populated
// before we show this widget
if (!mProjListDone)
{
lstCoordinateSystems->setCurrentItem(nodes.first());
lstCoordinateSystems->scrollToItem(nodes.first());
applyProjList(&mCrsFilter);
}
else // unselect the selected item to avoid confusing the user
{
lstCoordinateSystems->clearSelection();
teProjection->setText("");
if (!mUserProjListDone)
{
applyUserProjList(&mCrsFilter);
}
// Pass up the inheritance heirarchy
QWidget::showEvent(theEvent);
}
QString QgsProjectionSelector::ogcWmsCrsFilterAsSqlExpression(QSet<QString> * crsFilter)
{
QString sqlExpression = "1"; // it's "SQL" for "true"
QStringList epsgParts = QStringList();
if (!crsFilter)
{
return sqlExpression;
}
/*
Ref: WMS 1.3.0, section 6.7.3 "Layer CRS":
Every Layer CRS has an identifier that is a character string. Two types of
Layer CRS identifiers are permitted: "label" and "URL" identifiers:
Label: The identifier includes a namespace prefix, a colon, a numeric or
string code, and in some instances a comma followed by additional
parameters. This International Standard defines three namespaces:
CRS, EPSG and AUTO2 [...]
URL: The identifier is a fully-qualified Uniform Resource Locator that
references a publicly-accessible file containing a definition of the CRS
that is compliant with ISO 19111.
*/
// iterate through all incoming CRSs
QSet<QString>::const_iterator i = crsFilter->begin();
while (i != crsFilter->end())
{
QStringList parts = i->split(":");
if (parts.at(0) == "EPSG")
{
epsgParts.push_back( parts.at(1) );
}
++i;
}
// for ( int i = 0; i < crsFilter->size(); i++ )
// {
// QStringList parts = crsFilter->at(i).split(":");
//
// if (parts.at(0) == "EPSG")
// {
// epsgParts.push_back( parts.at(1) );
// }
// }
if (epsgParts.size())
{
sqlExpression = "epsg in (";
sqlExpression += epsgParts.join(",");
sqlExpression += ")";
}
#ifdef QGISDEBUG
std::cout << "QgsProjectionSelector::crsFilterAsSqlExpression: exiting with '"
<< sqlExpression.toLocal8Bit().data() << "'." << std::endl;
#endif
return sqlExpression;
}
void QgsProjectionSelector::setSelectedSRSName(QString theSRSName)
{
mSRSNameSelection = theSRSName;
mSRSNameSelectionPending = TRUE;
}
void QgsProjectionSelector::setSelectedSRSID(long theSRSID)
{
QString mySRSIDString=QString::number(theSRSID);
mSRSIDSelection = theSRSID;
mSRSIDSelectionPending = TRUE;
}
QList<QTreeWidgetItem*> nodes = lstCoordinateSystems->findItems(mySRSIDString, Qt::MatchExactly|Qt::MatchRecursive, 1);
if (nodes.count() > 0)
void QgsProjectionSelector::applySRSNameSelection()
{
if (
(mSRSNameSelectionPending) and
(mProjListDone) and
(mUserProjListDone)
)
{
lstCoordinateSystems->setCurrentItem(nodes.first());
lstCoordinateSystems->scrollToItem(nodes.first());
}
else // unselect the selected item to avoid confusing the user
{
lstCoordinateSystems->clearSelection();
teProjection->setText("");
//get the srid given the wkt so we can pick the correct list item
#ifdef QGISDEBUG
std::cout << "QgsProjectionSelector::applySRSNameSelection called with \n" << mSRSNameSelection.toLocal8Bit().data() << std::endl;
#endif
QList<QTreeWidgetItem*> nodes = lstCoordinateSystems->findItems(mSRSNameSelection, Qt::MatchExactly|Qt::MatchRecursive, 0);
if (nodes.count() > 0)
{
lstCoordinateSystems->setCurrentItem(nodes.first());
lstCoordinateSystems->scrollToItem(nodes.first());
}
else // unselect the selected item to avoid confusing the user
{
lstCoordinateSystems->clearSelection();
teProjection->setText("");
}
mSRSNameSelectionPending = FALSE;
}
}
void QgsProjectionSelector::applySRSIDSelection()
{
if (
(mSRSIDSelectionPending) and
(mProjListDone) and
(mUserProjListDone)
)
{
QString mySRSIDString = QString::number(mSRSIDSelection);
QList<QTreeWidgetItem*> nodes = lstCoordinateSystems->findItems(mySRSIDString, Qt::MatchExactly|Qt::MatchRecursive, 1);
if (nodes.count() > 0)
{
lstCoordinateSystems->setCurrentItem(nodes.first());
lstCoordinateSystems->scrollToItem(nodes.first());
}
else // unselect the selected item to avoid confusing the user
{
lstCoordinateSystems->clearSelection();
teProjection->setText("");
}
mSRSIDSelectionPending = FALSE;
}
}
//note this line just returns the projection name!
QString QgsProjectionSelector::getSelectedName()
{
@ -198,10 +325,10 @@ QString QgsProjectionSelector::getCurrentProj4String()
}
long QgsProjectionSelector::getCurrentSRID()
long QgsProjectionSelector::getCurrentLongAttribute(QString attributeName)
{
// Only return the projection if there is a node in the tree
// selected that has an srid. This prevents error if the user
// Only return the attribute if there is a node in the tree
// selected that has an srs_id. This prevents error if the user
// selects a top-level node rather than an actual coordinate
// system
//
@ -210,7 +337,6 @@ long QgsProjectionSelector::getCurrentSRID()
if(lvi)
{
// Make sure the selected node is a srs and not a top-level projection node
//TODO - blast this outta here: std::cout << lvi->text(1).toLocal8Bit().data() << std::endl;
if(lvi->text(1).length() > 0)
{
QString myDatabaseFileName;
@ -251,11 +377,13 @@ long QgsProjectionSelector::getCurrentSRID()
// prepare the sql statement
const char *pzTail;
sqlite3_stmt *ppStmt;
QString sql = "select srid from tbl_srs where srs_id = ";
QString sql = "select ";
sql += attributeName;
sql += " from tbl_srs where srs_id = ";
sql += lvi->text(1);
#ifdef QGISDEBUG
std::cout << "Finding selected srid using : " << sql.toLocal8Bit().data() << std::endl;
std::cout << "Finding selected attribute using : " << sql.toLocal8Bit().data() << std::endl;
#endif
rc = sqlite3_prepare(db, sql.utf8(), sql.length(), &ppStmt, &pzTail);
// XXX Need to free memory from the error msg if one is set
@ -285,6 +413,19 @@ long QgsProjectionSelector::getCurrentSRID()
}
long QgsProjectionSelector::getCurrentSRID()
{
return getCurrentLongAttribute("srid");
}
long QgsProjectionSelector::getCurrentEpsg()
{
return getCurrentLongAttribute("epsg");
}
long QgsProjectionSelector::getCurrentSRSID()
{
QTreeWidgetItem* item = lstCoordinateSystems->currentItem();
@ -299,13 +440,30 @@ long QgsProjectionSelector::getCurrentSRSID()
}
}
void QgsProjectionSelector::getUserProjList()
void QgsProjectionSelector::setOgcWmsCrsFilter(QSet<QString> crsFilter)
{
mCrsFilter = crsFilter;
}
void QgsProjectionSelector::applyUserProjList(QSet<QString> * crsFilter)
{
#ifdef QGISDEBUG
std::cout << "Fetching user projection list..." << std::endl;
#endif
// convert our Coordinate Reference System filter into the SQL expression
QString sqlFilter = ogcWmsCrsFilterAsSqlExpression(crsFilter);
// User defined coordinate system node
mUserProjList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("User Defined Coordinate System"));
// Make in an italic font to distinguish them from real projections
mUserProjList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("User Defined Coordinate Systems"));
QFont fontTemp = mUserProjList->font(0);
fontTemp.setItalic(TRUE);
mUserProjList->setFont(0, fontTemp);
//determine where the user proj database lives for this user. If none is found an empty
//now only will be shown
QString myQGisSettingsDir = QDir::homeDirPath () + "/.qgis/";
@ -319,6 +477,8 @@ void QgsProjectionSelector::getUserProjList()
#ifdef QGISDEBUG
std::cout << "Users qgis.db not found...skipping" << std::endl;
#endif
mUserProjListDone = TRUE;
return;
}
@ -339,7 +499,10 @@ void QgsProjectionSelector::getUserProjList()
}
// Set up the query to retreive the projection information needed to populate the list
QString mySql = "select description,srs_id,is_geo, name,parameters from vw_srs";
QString mySql = "select description, srs_id, is_geo, name, parameters from vw_srs ";
mySql += "where ";
mySql += sqlFilter;
#ifdef QGISDEBUG
std::cout << "User projection list sql" << mySql.toLocal8Bit().data() << std::endl;
#endif
@ -358,16 +521,31 @@ void QgsProjectionSelector::getUserProjList()
// close the sqlite3 statement
sqlite3_finalize(myPreparedStatement);
sqlite3_close(myDatabase);
mUserProjListDone = TRUE;
}
void QgsProjectionSelector::getProjList()
void QgsProjectionSelector::applyProjList(QSet<QString> * crsFilter)
{
// convert our Coordinate Reference System filter into the SQL expression
QString sqlFilter = ogcWmsCrsFilterAsSqlExpression(crsFilter);
// Create the top-level nodes for the list view of projections
// Make in an italic font to distinguish them from real projections
//
// Geographic coordinate system node
mGeoList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("Geographic Coordinate System"));
mGeoList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("Geographic Coordinate Systems"));
QFont fontTemp = mGeoList->font(0);
fontTemp.setItalic(TRUE);
mGeoList->setFont(0, fontTemp);
// Projected coordinate system node
mProjList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("Projected Coordinate System"));
mProjList = new QTreeWidgetItem(lstCoordinateSystems,QStringList("Projected Coordinate Systems"));
fontTemp = mProjList->font(0);
fontTemp.setItalic(TRUE);
mProjList->setFont(0, fontTemp);
//bail out in case the projections db does not exist
//this is neccessary in case the pc is running linux with a
@ -378,6 +556,7 @@ void QgsProjectionSelector::getProjList()
myFileInfo.setFile(mSrsDatabaseFileName);
if ( !myFileInfo.exists( ) )
{
mProjListDone = TRUE;
return;
}
@ -411,7 +590,11 @@ void QgsProjectionSelector::getProjList()
// Set up the query to retreive the projection information needed to populate the list
//note I am giving the full field names for clarity here and in case someown
//changes the underlying view TS
sql = "select description,srs_id,is_geo, name,parameters from vw_srs order by name, description";
sql = "select description, srs_id, is_geo, name, parameters from vw_srs ";
sql += "where ";
sql += sqlFilter;
sql += " order by name, description";
#ifdef QGISDEBUG
std::cout << "SQL for projection list:\n" << sql.toLocal8Bit().data() << std::endl;
#endif
@ -460,7 +643,12 @@ void QgsProjectionSelector::getProjList()
if(nodes.count() == 0)
{
// the node doesn't exist -- create it
// Make in an italic font to distinguish them from real projections
node = new QTreeWidgetItem(mProjList, QStringList(srsType));
QFont fontTemp = node->font(0);
fontTemp.setItalic(TRUE);
node->setFont(0, fontTemp);
}
else
{
@ -488,6 +676,8 @@ void QgsProjectionSelector::getProjList()
sqlite3_finalize(ppStmt);
// close the database
sqlite3_close(db);
mProjListDone = TRUE;
}
//this is a little helper function to populate the (well give you a sql script to populate)
@ -560,6 +750,7 @@ void QgsProjectionSelector::coordinateSystemSelected( QTreeWidgetItem * theItem)
// hence is just a grouping thingy, not an actual SRS.
if (theItem != NULL && theItem->childCount() == 0)
{
// Found a real SRS
QString myDescription = tr("QGIS SRSID: ") + QString::number(getCurrentSRSID()) +"\n";
myDescription += tr("PostGIS SRID: ") + QString::number(getCurrentSRID()) +"\n";
emit sridSelected(QString::number(getCurrentSRSID()));
@ -572,7 +763,11 @@ void QgsProjectionSelector::coordinateSystemSelected( QTreeWidgetItem * theItem)
teProjection->setText(myDescription);
}
else
{
// Not an SRS - remove the highlight so the user doesn't get too confused
lstCoordinateSystems->setItemSelected(theItem, FALSE); // TODO - make this work.
teProjection->setText("");
}
}
void QgsProjectionSelector::on_pbnFind_clicked()

View File

@ -12,6 +12,8 @@
#include "ui_qgsprojectionselectorbase.h"
#include <QSet>
class QResizeEvent;
/**
@ -21,13 +23,36 @@ class QgsProjectionSelector: public QWidget, private Ui::QgsProjectionSelectorBa
{
Q_OBJECT
public:
QgsProjectionSelector( QWidget* parent , const char* name="", Qt::WFlags fl =0 );
QgsProjectionSelector(QWidget* parent,
const char * name = "",
Qt::WFlags fl = 0);
~QgsProjectionSelector();
//! Populate the proj tree view with user defined projection names...
void getUserProjList();
//! Populate the proj tree view with system projection names...
void getProjList();
void updateProjAndEllipsoidAcronyms(int theSrsid,QString theProj4String);
/**
* \brief Populate the proj tree view with user defined projection names...
*
* \param crsFilter a list of OGC Coordinate Reference Systems to filter the
* list of projections by. This is useful in (e.g.) WMS situations
* where you just want to offer what the WMS server can support.
*
* \todo Should this be public?
*/
void applyUserProjList(QSet<QString> * crsFilter = 0);
/**
* \brief Populate the proj tree view with system projection names...
*
* \param crsFilter a list of OGC Coordinate Reference Systems to filter the
* list of projections by. This is useful in (e.g.) WMS situations
* where you just want to offer what the WMS server can support.
*
* \todo Should this be public?
*/
void applyProjList(QSet<QString> * crsFilter = 0);
void updateProjAndEllipsoidAcronyms(int theSrsid, QString theProj4String);
/*!
* \brief Make the string safe for use in SQL statements.
* This involves escaping single quotes, double quotes, backslashes,
@ -39,18 +64,87 @@ class QgsProjectionSelector: public QWidget, private Ui::QgsProjectionSelectorBa
*/
const QString stringSQLSafe(const QString theSQL);
//! Gets the current EPSG-style projection identifier
long getCurrentEpsg();
public slots:
void setSelectedSRSName(QString theSRSName);
QString getSelectedName();
void setSelectedSRSID(long theSRSID);
QString getCurrentProj4String();
long getCurrentSRID(); //posgis style projection identifier
long getCurrentSRSID();//qgis projection identfier
//! Gets the current PostGIS-style projection identifier
long getCurrentSRID();
//! Gets the current QGIS projection identfier
long getCurrentSRSID();
/**
* \brief filters this widget by the given CRSs
*
* Sets this widget to filter the available projections to those listed
* by the given Coordinate Reference Systems.
*
* \param crsFilter a list of OGC Coordinate Reference Systems to filter the
* list of projections by. This is useful in (e.g.) WMS situations
* where you just want to offer what the WMS server can support.
*
* \note This function only deals with EPSG labels only at this time.
*
* \warning This function's behaviour is undefined if it is called after the widget is shown.
*/
void setOgcWmsCrsFilter(QSet<QString> crsFilter);
void on_pbnFind_clicked();
protected:
/** Used to ensure the projection list view is actually populated */
void showEvent ( QShowEvent * theEvent );
private:
/** Used to manage column sizes */
void resizeEvent ( QResizeEvent * theEvent );
/**
* \brief converts the CRS group to a SQL expression fragment
*
* Converts the given Coordinate Reference Systems to a format suitable
* for use in SQL for querying against the QGIS SRS database.
*
* \param crsFilter a list of OGC Coordinate Reference Systems to filter the
* list of projections by. This is useful in (e.g.) WMS situations
* where you just want to offer what the WMS server can support.
*
* \note This function only deals with EPSG labels only at this time.
*/
QString ogcWmsCrsFilterAsSqlExpression(QSet<QString> * crsFilter);
/**
* \brief does the legwork of applying the SRS Name Selection
*
* \warning This function does nothing unless getUserList() and getUserProjList()
* Have already been called
*/
void applySRSNameSelection();
/**
* \brief does the legwork of applying the SRS ID Selection
*
* \warning This function does nothing unless getUserList() and getUserProjList()
* Have already been called
*/
void applySRSIDSelection();
/**
* \brief gets an arbitrary sqlite3 attribute of type "long" from the selection
*
* \param attributeName The sqlite3 column name, typically "srid" or "epsg"
*/
long getCurrentLongAttribute(QString attributeName);
// List view nodes for the tree view of projections
//! User defined projections node
QTreeWidgetItem *mUserProjList;
@ -58,6 +152,7 @@ class QgsProjectionSelector: public QWidget, private Ui::QgsProjectionSelectorBa
QTreeWidgetItem *mGeoList;
//! PROJCS node
QTreeWidgetItem *mProjList;
//! Users custom coordinate system file
QString mCustomCsFile;
//! File name of the sqlite3 database
@ -68,6 +163,27 @@ class QgsProjectionSelector: public QWidget, private Ui::QgsProjectionSelectorBa
*/
long getLargestSRSIDMatch(QString theSql);
//! Has the Projection List been populated?
bool mProjListDone;
//! Has the User Projection List been populated?
bool mUserProjListDone;
//! Is there a pending selection to be made by SRS Name?
bool mSRSNameSelectionPending;
//! Is there a pending selection to be made by SRS ID?
bool mSRSIDSelectionPending;
//! The SRS Name that wants to be selected on this widget
QString mSRSNameSelection;
//! The SRS ID that wants to be selected on this widget
long mSRSIDSelection;
//! The set of OGC WMS CRSs that want to be applied to this widget
QSet<QString> mCrsFilter;
private slots:
/**private handler for when user selects a cs
*it will cause wktSelected and sridSelected events to be spawned