9,735 changes: 5,015 additions & 4,720 deletions i18n/qgis_sv.ts

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions postinstall/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

# for included scripts that set policies
INSTALL (CODE "cmake_policy(SET CMP0011 NEW)")

CONFIGURE_FILE("PostInstall.cmake.in" "PostInstall.cmake" @ONLY)
INSTALL(SCRIPT "${CMAKE_BINARY_DIR}/postinstall/PostInstall.cmake")
9 changes: 9 additions & 0 deletions postinstall/PostInstall.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# kill boolean warnings
CMAKE_POLICY(SET CMP0012 NEW)

IF(@WITH_PY_COMPILE@)
MESSAGE(STATUS "Byte-compiling core Python utilities and plugins...")
# exclude Python 3 modules in PyQt4.uic package
EXECUTE_PROCESS(COMMAND @PYTHON_EXECUTABLE@ -m compileall -q -x ".*uic.port_v3.*" "@CMAKE_INSTALL_PREFIX@/@QGIS_DATA_DIR@/python")
ENDIF(@WITH_PY_COMPILE@)
10 changes: 10 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,13 @@ INSTALL(FILES ${PY_FILES} ${PYUI_FILES} DESTINATION "${QGIS_PYTHON_DIR}")

ADD_SUBDIRECTORY(console_help)

# Byte-compile staged PyQGIS utilities
IF(WITH_PY_COMPILE)
ADD_CUSTOM_TARGET(pycompile_pyutils ALL
COMMAND ${PYTHON_EXECUTABLE} -m compileall -q "${PYTHON_OUTPUT_DIRECTORY}/qgis"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
COMMENT "Byte-compiling staged PyQGIS utility modules..."
DEPENDS pyutils
)
ENDIF(WITH_PY_COMPILE)

10 changes: 10 additions & 0 deletions python/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
IF(WITH_PY_COMPILE)
ADD_CUSTOM_TARGET(pycompile_staged ALL
COMMAND ${PYTHON_EXECUTABLE} -m compileall -q "${PYTHON_OUTPUT_DIRECTORY}/plugins"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
COMMENT "Byte-compiling staged Python plugins..."
)
ENDIF(WITH_PY_COMPILE)

MACRO (PLUGIN_INSTALL plugin subdir )
INSTALL(FILES ${ARGN} DESTINATION ${QGIS_DATA_DIR}/python/plugins/${plugin}/${subdir})
STRING(REPLACE "/" "_" subdir_sane "${subdir}")
ADD_CUSTOM_TARGET(${plugin}_${subdir_sane}_stageinstall ALL DEPENDS ${ARGN})
IF(WITH_PY_COMPILE)
ADD_DEPENDENCIES(pycompile_staged ${plugin}_${subdir_sane}_stageinstall)
ENDIF(WITH_PY_COMPILE)
FOREACH(file ${ARGN})
ADD_CUSTOM_COMMAND(TARGET ${plugin}_${subdir_sane}_stageinstall
POST_BUILD
Expand Down
2 changes: 0 additions & 2 deletions python/plugins/sextante/about/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ FILE(GLOB PY_FILES *.py)
FILE(GLOB UI_FILES *.ui)
PYQT4_WRAP_UI(PYUI_FILES ${UI_FILES})



PLUGIN_INSTALL(sextante ./about ${PY_FILES} ${PYUI_FILES})
3 changes: 2 additions & 1 deletion python/plugins/sextante/ftools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ FILE(GLOB PY_FILES *.py)
FILE(GLOB OTHER_FILES copyright.txt)
FILE(GLOB ICON_FILES icons/*.png)

PLUGIN_INSTALL(sextante ./ftools ${PY_FILES} ${OTHER_FILES} ${ICON_FILES})
PLUGIN_INSTALL(sextante ./ftools ${PY_FILES} ${OTHER_FILES})
PLUGIN_INSTALL(sextante ./ftools/icons ${ICON_FILES})
3 changes: 2 additions & 1 deletion python/plugins/sextante/gdal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ FILE(GLOB ICON_FILES icons/*.png)

ADD_SUBDIRECTORY(scripts)

PLUGIN_INSTALL(sextante ./gdal ${PY_FILES} ${ICON_FILES})
PLUGIN_INSTALL(sextante ./gdal ${PY_FILES})
PLUGIN_INSTALL(sextante ./gdal/icons ${ICON_FILES})
4 changes: 3 additions & 1 deletion python/plugins/sextante/help/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ FILE(GLOB OTHER_FILES *.js)
FILE(GLOB IMAGE_FILES _images/*.*)
FILE(GLOB STATIC_FILES _static/*.*)

PLUGIN_INSTALL(sextante ./help ${HTML_FILES} ${OTHER_FILES} ${IMAGE_FILES} ${STATIC_FILES})
PLUGIN_INSTALL(sextante ./help ${HTML_FILES} ${OTHER_FILES})
PLUGIN_INSTALL(sextante ./help/images ${IMAGE_FILES})
PLUGIN_INSTALL(sextante ./help/_static ${STATIC_FILES})
3 changes: 2 additions & 1 deletion python/plugins/sextante/mmqgisx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ FILE(GLOB PY_FILES *.py)
FILE(GLOB OTHER_FILES copyright.txt)
FILE(GLOB ICON_FILES icons/*.png)

PLUGIN_INSTALL(sextante ./mmqgisx ${PY_FILES} ${OTHER_FILES} ${ICON_FILES})
PLUGIN_INSTALL(sextante ./mmqgisx ${PY_FILES} ${OTHER_FILES})
PLUGIN_INSTALL(sextante ./mmqgisx/icons ${ICON_FILES})
7 changes: 6 additions & 1 deletion python/plugins/sextante/pymorph/html/morph/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ FILE(GLOB MMINFO_FILES mminfo/*.*)
FILE(GLOB MMTYPES_FILES mmtype/*.*)
FILE(GLOB MORPH_FILES morph/*.*)

PLUGIN_INSTALL(sextante ./pymorph/html/morph ${HTML_FILES} ${GIF_FILES} ${IMAGES_FILES} ${MMDEMOS_FILES} ${MMINFO_FILES} ${MMTYPES_FILES} ${MORPH_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph ${HTML_FILES} ${GIF_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph/images ${IMAGES_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph/mmdemos ${MMDEMOS_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph/mminfo ${MMINFO_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph/mmtypes ${MMTYPES_FILES})
PLUGIN_INSTALL(sextante ./pymorph/html/morph/morph ${MORPH_FILES})
18 changes: 18 additions & 0 deletions src/app/legend/qgslegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2104,6 +2104,24 @@ void QgsLegend::refreshLayerSymbology( QString key, bool expandItem )
setItemExpanded( theLegendLayer, expandItem );//make sure the symbology items are visible
}

void QgsLegend::refreshLayerSymbology( QString key, QgsLegendItem::Expansion expandItem )
{
bool expand = true;
if ( expandItem == QgsLegendItem::DontChange )
{
QgsLegendLayer* theLegendLayer = findLegendLayer( key );
if ( !theLegendLayer )
{
return;
}
expand = theLegendLayer->isExpanded();
}
else if ( expandItem == QgsLegendItem::Collapse )
{
expand = false;
}
return refreshLayerSymbology( key, expand );
}

void QgsLegend::addPixmapWidthValue( int width )
{
Expand Down
4 changes: 3 additions & 1 deletion src/app/legend/qgslegend.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@
#include <QPair>
#include <set>

#include "qgslegenditem.h"

class QgsLegendGroup;
class QgsLegendLayer;
class QgsLegendItem;
class QgsMapLayer;
class QgsMapCanvas;
class QDomDocument;
Expand Down Expand Up @@ -220,6 +221,7 @@ class QgsLegend : public QTreeWidget

/**Updates symbology items for a layer*/
void refreshLayerSymbology( QString key, bool expandItem = true );
void refreshLayerSymbology( QString key, QgsLegendItem::Expansion expandItem );

/*!
* Slot called to clear the tree of all items
Expand Down
7 changes: 7 additions & 0 deletions src/app/legend/qgslegenditem.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ class QgsLegendItem : public QTreeWidgetItem, public QObject
NO_ACTION //do nothing
};

enum Expansion
{
Expand,
Collapse,
DontChange // keep current state
};

virtual LEGEND_ITEM_TYPE type() const { return mType; }

/**Subclasses which allow insertion of other items may implement this method.
Expand Down
16 changes: 11 additions & 5 deletions src/app/legend/qgslegendlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,15 +598,21 @@ void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLa
p.setWindowModality( Qt::WindowModal );
int featuresCounted = 0;


layer->select( layer->pendingAllAttributesList(), QgsRectangle(), false, false );
QgsFeature f;
QgsSymbolV2* currentSymbol = 0;

// Renderer (rule based) may depend on context scale, with scale is ignored if 0
QgsRenderContext renderContext;
renderContext.setRendererScale( 0 );
renderer->startRender( renderContext, layer );

while ( layer->nextFeature( f ) )
{
currentSymbol = renderer->symbolForFeature( f );
mSymbolCountMap[currentSymbol] += 1;
QgsSymbolV2List symbolList = renderer->symbolsForFeature( f );
for ( QgsSymbolV2List::iterator symbolIt = symbolList.begin(); symbolIt != symbolList.end(); ++symbolIt )
{
mSymbolCountMap[*symbolIt] += 1;
}
++featuresCounted;
if ( featuresCounted % 50 == 0 )
{
Expand All @@ -621,6 +627,7 @@ void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLa
}
}
}
renderer->stopRender( renderContext );
p.setValue( nFeatures );

QMap<QString, QPixmap> itemMap;
Expand All @@ -631,7 +638,6 @@ void QgsLegendLayer::updateItemListCountV2( SymbologyList& itemList, QgsVectorLa
}
itemList.clear();

//
symbolIt = symbolList.constBegin();
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
{
Expand Down
4 changes: 2 additions & 2 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7749,7 +7749,7 @@ void QgisApp::showLayerProperties( QgsMapLayer *ml )
else
{
rlp = new QgsRasterLayerProperties( ml, mMapCanvas, this );
connect( rlp, SIGNAL( refreshLegend( QString, bool ) ), mMapLegend, SLOT( refreshLayerSymbology( QString, bool ) ) );
connect( rlp, SIGNAL( refreshLegend( QString, QgsLegendItem::Expansion ) ), mMapLegend, SLOT( refreshLayerSymbology( QString, QgsLegendItem::Expansion ) ) );
}

rlp->exec();
Expand All @@ -7767,7 +7767,7 @@ void QgisApp::showLayerProperties( QgsMapLayer *ml )
else
{
vlp = new QgsVectorLayerProperties( vlayer, this );
connect( vlp, SIGNAL( refreshLegend( QString, bool ) ), mMapLegend, SLOT( refreshLayerSymbology( QString, bool ) ) );
connect( vlp, SIGNAL( refreshLegend( QString, QgsLegendItem::Expansion ) ), mMapLegend, SLOT( refreshLayerSymbology( QString, QgsLegendItem::Expansion ) ) );
}

if ( vlp->exec() )
Expand Down
30 changes: 28 additions & 2 deletions src/app/qgsmaptoolidentify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "qgsproject.h"
#include "qgsmaplayerregistry.h"
#include "qgisapp.h"
#include "qgsrendererv2.h"

#include <QSettings>
#include <QMessageBox>
Expand Down Expand Up @@ -193,9 +194,19 @@ bool QgsMapToolIdentify::identifyLayer( QgsMapLayer *layer, int x, int y )

bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int y )
{
if ( !layer )
if ( !layer || !layer->rendererV2() )
return false;

if ( layer->hasScaleBasedVisibility() &&
( layer->minimumScale() > mCanvas->mapRenderer()->scale() ||
layer->maximumScale() <= mCanvas->mapRenderer()->scale() ) )
{
QgsDebugMsg( "Out of scale limits" );
return false;
}

QgsFeatureRendererV2* renderer = layer->rendererV2();

QMap< QString, QString > attributes, derivedAttributes;

QgsPoint point = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y );
Expand Down Expand Up @@ -252,11 +263,21 @@ bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int
}
QgsFeatureList::iterator f_it = featureList.begin();

if ( renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
{
// setup scale for scale dependent visibility (rule based)
renderer->startRender( *( mCanvas->mapRenderer()->rendererContext() ), layer );
}
bool filter = renderer->capabilities() & QgsFeatureRendererV2::Filter;

for ( ; f_it != featureList.end(); ++f_it )
{
QgsFeatureId fid = f_it->id();

if ( filter && !renderer->willRenderFeature( *f_it ) ) continue;

featureCount++;

QgsFeatureId fid = f_it->id();
QMap<QString, QString> derivedAttributes;

// Calculate derived attributes and insert:
Expand Down Expand Up @@ -307,6 +328,11 @@ bool QgsMapToolIdentify::identifyVectorLayer( QgsVectorLayer *layer, int x, int
results()->addFeature( layer, *f_it, derivedAttributes );
}

if ( renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
{
renderer->stopRender( *( mCanvas->mapRenderer()->rendererContext() ) );
}

QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );

return featureCount > 0;
Expand Down
133 changes: 74 additions & 59 deletions src/app/qgsprojectproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
mWMSAbstract->setPlainText( QgsProject::instance()->readEntry( "WMSServiceAbstract", "/", "" ) );
mWMSOnlineResourceLineEdit->setText( QgsProject::instance()->readEntry( "WMSOnlineResource", "/", "" ) );
mWMSUrlLineEdit->setText( QgsProject::instance()->readEntry( "WMSUrl", "/", "" ) );
mWMSFees->setText( QgsProject::instance()->readEntry( "WMSFees", "/", "" ) );
mWMSAccessConstraints->setText( QgsProject::instance()->readEntry( "WMSAccessConstraints", "/", "" ) );
mWMSKeywordList->setText( QgsProject::instance()->readListEntry( "WMSKeywordList", "/" ).join( "," ) );

bool ok;
QStringList values;
Expand Down Expand Up @@ -304,14 +307,14 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
QStringList wfstInsertLayerIdList = QgsProject::instance()->readListEntry( "WFSTLayers", "Insert" );
QStringList wfstDeleteLayerIdList = QgsProject::instance()->readListEntry( "WFSTLayers", "Delete" );

QSignalMapper *smPublied = new QSignalMapper(this);
connect(smPublied, SIGNAL(mapped(int)), this, SLOT(on_cbxWFSPublied_stateChanged(int)));
QSignalMapper *smUpdate = new QSignalMapper(this);
connect(smUpdate, SIGNAL(mapped(int)), this, SLOT(on_cbxWFSUpdate_stateChanged(int)));
QSignalMapper *smInsert = new QSignalMapper(this);
connect(smInsert, SIGNAL(mapped(int)), this, SLOT(on_cbxWFSInsert_stateChanged(int)));
QSignalMapper *smDelete = new QSignalMapper(this);
connect(smDelete, SIGNAL(mapped(int)), this, SLOT(on_cbxWFSDelete_stateChanged(int)));
QSignalMapper *smPublied = new QSignalMapper( this );
connect( smPublied, SIGNAL( mapped( int ) ), this, SLOT( on_cbxWFSPublied_stateChanged( int ) ) );
QSignalMapper *smUpdate = new QSignalMapper( this );
connect( smUpdate, SIGNAL( mapped( int ) ), this, SLOT( on_cbxWFSUpdate_stateChanged( int ) ) );
QSignalMapper *smInsert = new QSignalMapper( this );
connect( smInsert, SIGNAL( mapped( int ) ), this, SLOT( on_cbxWFSInsert_stateChanged( int ) ) );
QSignalMapper *smDelete = new QSignalMapper( this );
connect( smDelete, SIGNAL( mapped( int ) ), this, SLOT( on_cbxWFSDelete_stateChanged( int ) ) );

twWFSLayers->setColumnCount( 5 );
twWFSLayers->horizontalHeader()->setVisible( true );
Expand All @@ -337,37 +340,37 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
cbp->setChecked( wfsLayerIdList.contains( currentLayer->id() ) );
twWFSLayers->setCellWidget( j, 1, cbp );

smPublied->setMapping(cbp, j);
connect(cbp, SIGNAL(stateChanged(int)), smPublied, SLOT(map()));
smPublied->setMapping( cbp, j );
connect( cbp, SIGNAL( stateChanged( int ) ), smPublied, SLOT( map() ) );

QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( currentLayer );
QgsVectorDataProvider* provider = vlayer->dataProvider();
if ( (provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) && (provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) )
if (( provider->capabilities() & QgsVectorDataProvider::ChangeAttributeValues ) && ( provider->capabilities() & QgsVectorDataProvider::ChangeGeometries ) )
{
QCheckBox* cbu = new QCheckBox();
cbu->setChecked( wfstUpdateLayerIdList.contains( currentLayer->id() ) );
twWFSLayers->setCellWidget( j, 2, cbu );

smUpdate->setMapping(cbu, j);
connect(cbu, SIGNAL(stateChanged(int)), smUpdate, SLOT(map()));
smUpdate->setMapping( cbu, j );
connect( cbu, SIGNAL( stateChanged( int ) ), smUpdate, SLOT( map() ) );
}
if ( ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) )
if (( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) )
{
QCheckBox* cbi = new QCheckBox();
cbi->setChecked( wfstInsertLayerIdList.contains( currentLayer->id() ) );
twWFSLayers->setCellWidget( j, 3, cbi );

smInsert->setMapping(cbi, j);
connect(cbi, SIGNAL(stateChanged(int)), smInsert, SLOT(map()));
smInsert->setMapping( cbi, j );
connect( cbi, SIGNAL( stateChanged( int ) ), smInsert, SLOT( map() ) );
}
if ( ( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
if (( provider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
{
QCheckBox* cbd = new QCheckBox();
cbd->setChecked( wfstDeleteLayerIdList.contains( currentLayer->id() ) );
twWFSLayers->setCellWidget( j, 4, cbd );

smDelete->setMapping(cbd, j);
connect(cbd, SIGNAL(stateChanged(int)), smDelete, SLOT(map()));
smDelete->setMapping( cbd, j );
connect( cbd, SIGNAL( stateChanged( int ) ), smDelete, SLOT( map() ) );
}

j++;
Expand Down Expand Up @@ -567,6 +570,18 @@ void QgsProjectProperties::apply()
QgsProject::instance()->writeEntry( "WMSServiceAbstract", "/", mWMSAbstract->toPlainText() );
QgsProject::instance()->writeEntry( "WMSOnlineResource", "/", mWMSOnlineResourceLineEdit->text() );
QgsProject::instance()->writeEntry( "WMSUrl", "/", mWMSUrlLineEdit->text() );
QgsProject::instance()->writeEntry( "WMSFees", "/", mWMSFees->text() );
QgsProject::instance()->writeEntry( "WMSAccessConstraints", "/", mWMSAccessConstraints->text() );
//WMS keyword list
QStringList keywordStringList = mWMSKeywordList->text().split( "," );
if ( keywordStringList.size() > 0 )
{
QgsProject::instance()->writeEntry( "WMSKeywordList", "/", mWMSKeywordList->text().split( "," ) );
}
else
{
QgsProject::instance()->removeEntry( "WMSKeywordList", "/" );
}

if ( grpWMSExt->isChecked() )
{
Expand Down Expand Up @@ -762,58 +777,58 @@ void QgsProjectProperties::on_cbxProjectionEnabled_stateChanged( int state )

void QgsProjectProperties::on_cbxWFSPublied_stateChanged( int aIdx )
{
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 1 ) );
if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cbn )
cbn->setChecked(false);
}
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 1 ) );
if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cbn )
cbn->setChecked( false );
}
}

void QgsProjectProperties::on_cbxWFSUpdate_stateChanged( int aIdx )
{
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 1 ) );
if ( cbn )
cbn->setChecked(true);
}
else if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cbn )
cbn->setChecked(false);
}
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 1 ) );
if ( cbn )
cbn->setChecked( true );
}
else if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cbn )
cbn->setChecked( false );
}
}

void QgsProjectProperties::on_cbxWFSInsert_stateChanged( int aIdx )
{
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cbn )
cbn->setChecked(true);
}
else if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 4 ) );
if ( cbn )
cbn->setChecked(false);
}
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 2 ) );
if ( cbn )
cbn->setChecked( true );
}
else if ( cb && !cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 4 ) );
if ( cbn )
cbn->setChecked( false );
}
}

void QgsProjectProperties::on_cbxWFSDelete_stateChanged( int aIdx )
{
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 4 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cbn )
cbn->setChecked(true);
}
QCheckBox* cb = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 4 ) );
if ( cb && cb->isChecked() )
{
QCheckBox* cbn = qobject_cast<QCheckBox *>( twWFSLayers->cellWidget( aIdx, 3 ) );
if ( cbn )
cbn->setChecked( true );
}
}

void QgsProjectProperties::setMapUnitsToCurrentProjection()
Expand Down
11 changes: 11 additions & 0 deletions src/app/qgsrasterlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1723,3 +1723,14 @@ void QgsRasterLayerProperties::updatePipeItems()
#endif
}
}

void QgsRasterLayerProperties::on_mMinimumScaleSetCurrentPushButton_clicked()
{
cbMinimumScale->setScale( 1.0 / QgisApp::instance()->mapCanvas()->mapRenderer()->scale() );
}

void QgsRasterLayerProperties::on_mMaximumScaleSetCurrentPushButton_clicked()
{
cbMaximumScale->setScale( 1.0 / QgisApp::instance()->mapCanvas()->mapRenderer()->scale() );
}

3 changes: 3 additions & 0 deletions src/app/qgsrasterlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class QgsRasterLayerProperties : public QDialog, private Ui::QgsRasterLayerPrope
void on_pbnSaveStyleAs_clicked();
/** Help button */
void on_buttonBox_helpRequested() { QgsContextHelp::run( metaObject()->className() ); }
void on_mMinimumScaleSetCurrentPushButton_clicked();
void on_mMaximumScaleSetCurrentPushButton_clicked();

/**Enable or disable Build pyramids button depending on selection in pyramids list*/
void toggleBuildPyramidsButton();

Expand Down
12 changes: 10 additions & 2 deletions src/app/qgsvectorlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "qgslabeldialog.h"
#include "qgslabelinggui.h"
#include "qgslabel.h"
#include "qgslegenditem.h"
#include "qgsgenericprojectionselector.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
Expand Down Expand Up @@ -881,15 +882,14 @@ void QgsVectorLayerProperties::apply()
layer->setAbstract( mLayerAbstractTextEdit->toPlainText() );

// update symbology
emit refreshLegend( layer->id(), false );
emit refreshLegend( layer->id(), QgsLegendItem::DontChange );

//no need to delete the old one, maplayer will do it if needed
layer->setCacheImage( 0 );

layer->triggerRepaint();
// notify the project we've made a change
QgsProject::instance()->dirty( true );

}

void QgsVectorLayerProperties::on_pbnQueryBuilder_clicked()
Expand Down Expand Up @@ -1378,4 +1378,12 @@ void QgsVectorLayerProperties::enableLabelOptions( bool theFlag )
labelOptionsFrame->setEnabled( theFlag );
}

void QgsVectorLayerProperties::on_mMinimumScaleSetCurrentPushButton_clicked()
{
cbMinimumScale->setScale( 1.0 / QgisApp::instance()->mapCanvas()->mapRenderer()->scale() );
}

void QgsVectorLayerProperties::on_mMaximumScaleSetCurrentPushButton_clicked()
{
cbMaximumScale->setScale( 1.0 / QgisApp::instance()->mapCanvas()->mapRenderer()->scale() );
}
5 changes: 5 additions & 0 deletions src/app/qgsvectorlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "qgsdelattrdialog.h"
#include "qgsattributetypedialog.h"
#include "qgsfield.h"
#include "qgslegenditem.h"
#include "qgsmapcanvas.h"
#include "qgscontexthelp.h"
#include "qgsexpressionbuilderdialog.h"
Expand Down Expand Up @@ -135,10 +136,14 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
void on_mButtonAddJoin_clicked();
void on_mButtonRemoveJoin_clicked();

void on_mMinimumScaleSetCurrentPushButton_clicked();
void on_mMaximumScaleSetCurrentPushButton_clicked();

signals:

/** emitted when changes to layer were saved to update legend */
void refreshLegend( QString layerID, bool expandItem );
void refreshLegend( QString layerID, QgsLegendItem::Expansion expandItem );

void toggleEditing( QgsMapLayer * );

Expand Down
22 changes: 16 additions & 6 deletions src/core/qgsgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,24 @@ QgsGeometry* QgsGeometry::fromRect( const QgsRectangle& rect )
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode )
{
QDomNode geometryChild = geometryNode.firstChild();
if ( geometryChild.isNull() )
{
return 0;
}
QgsGeometry* g = new QgsGeometry();
QDomElement geometryTypeElement = geometryChild.toElement();
QDomElement geometryTypeElement = geometryNode.toElement();
QString geomType = geometryTypeElement.tagName();

if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon") )
{
QDomNode geometryChild = geometryNode.firstChild();
if ( geometryChild.isNull() )
{
return 0;
}
geometryTypeElement = geometryChild.toElement();
geomType = geometryTypeElement.tagName();
}

if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon") )
return 0;

if ( geomType == "Point" )
{
g->setFromGML2Point( geometryTypeElement );
Expand Down
8 changes: 4 additions & 4 deletions src/core/qgsmaplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,11 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** Event handler for when a coordinate transform fails due to bad vertex error */
virtual void invalidTransformInput();

/** Accessor and mutator for the minimum scale member */
/** Accessor and mutator for the minimum scale denominator member */
void setMinimumScale( float theMinScale );
float minimumScale();

/** Accessor and mutator for the maximum scale member */
/** Accessor and mutator for the maximum scale denominator member */
void setMaximumScale( float theMaxScale );
float maximumScale();

Expand Down Expand Up @@ -474,9 +474,9 @@ class CORE_EXPORT QgsMapLayer : public QObject
/** Tag for embedding additional information */
QString mTag;

/** Minimum scale at which this layer should be displayed */
/** Minimum scale denominator at which this layer should be displayed */
float mMinScale;
/** Maximum scale at which this layer should be displayed */
/** Maximum scale denominator at which this layer should be displayed */
float mMaxScale;
/** A flag that tells us whether to use the above vars to restrict layer visibility */
bool mScaleBasedVisibility;
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsmaprenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class CORE_EXPORT QgsMapRenderer : public QObject

const QgsMapToPixel* coordinateTransform() { return &( mRenderContext.mapToPixel() ); }

//! Scale denominator
double scale() const { return mScale; }
/**Sets scale for scale based visibility. Normally, the scale is calculated automatically. This
function is only used to force a preview scale (e.g. for print composer)*/
Expand Down Expand Up @@ -288,7 +289,7 @@ class CORE_EXPORT QgsMapRenderer : public QObject
//! map units per pixel
double mMapUnitsPerPixel;

//! Map scale at its current zoom level
//! Map scale denominator at its current zoom level
double mScale;

//! scale calculator
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsscalecalculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ double QgsScaleCalculator::calculate( const QgsRectangle &mapExtent, int canvasW
delta = calculateGeographicDistance( mapExtent );
break;
}
QgsDebugMsg( "Using conversionFactor of " + QString::number( conversionFactor ) );
if ( canvasWidth == 0 || mDpi == 0 )
{
QgsDebugMsg( "Can't calculate scale from the input values" );
return 0;
}
double scale = ( delta * conversionFactor ) / (( double )canvasWidth / mDpi );
QgsDebugMsg( QString( "scale = %1 conversionFactor = %2" ).arg( scale ).arg( conversionFactor ) );
return scale;
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/qgsscalecalculator.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ class CORE_EXPORT QgsScaleCalculator
QGis::UnitType mapUnits() const;

/**
* Calculate the scale
* Calculate the scale denominator
* @param mapExtent QgsRectangle containing the current map extent
* @param canvasWidth Width of the map canvas in pixel (physical) units
* @return scale of current map view
* @return scale denominator of current map view
*/
double calculate( const QgsRectangle &mapExtent, int canvasWidth );

Expand Down
12 changes: 8 additions & 4 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ void QgsCategorizedSymbolRendererV2::rebuildHash()
QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
{
// TODO: special case for int, double

QHash<QString, QgsSymbolV2*>::iterator it = mSymbolHash.find( value.toString() );
if ( it == mSymbolHash.end() )
{
Expand All @@ -169,7 +168,7 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForValue( QVariant value )
}
else
{
//QgsDebugMsg( "attribute value not found: " + value.toString() );
QgsDebugMsg( "attribute value not found: " + value.toString() );
}
return NULL;
}
Expand All @@ -192,7 +191,12 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
if ( symbol == NULL )
{
// if no symbol found use default one
return symbolForValue( QVariant( "" ) );
//return symbolForValue( QVariant( "" ) );
// What is default? Empty string may be a legal value, and features not found
// should not be rendered using empty string value category symbology.
// We also need to get NULL in that case so that willRenderFeature()
// may be used to count features.
return 0;
}

if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 )
Expand Down Expand Up @@ -600,7 +604,7 @@ void QgsCategorizedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* r
void QgsCategorizedSymbolRendererV2::updateSymbols( QgsSymbolV2 * sym )
{
int i = 0;
foreach( QgsRendererCategoryV2 cat, mCategories )
foreach ( QgsRendererCategoryV2 cat, mCategories )
{
QgsSymbolV2* symbol = sym->clone();
symbol->setColor( cat.symbol()->color() );
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgscategorizedsymbolrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2

//! returns bitwise OR-ed capabilities of the renderer
//! \note added in 2.0
virtual int capabilities() { return SymbolLevels | RotationField; }
virtual int capabilities() { return SymbolLevels | RotationField | Filter; }

virtual QgsSymbolV2List symbols();
//! @note added in 2.0
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgsgraduatedsymbolrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2

//! returns bitwise OR-ed capabilities of the renderer
//! \note added in 2.0
virtual int capabilities() { return SymbolLevels | RotationField; }
virtual int capabilities() { return SymbolLevels | RotationField | Filter; }

virtual QgsSymbolV2List symbols();

Expand Down
9 changes: 7 additions & 2 deletions src/core/symbology-ng/qgsrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ class CORE_EXPORT QgsFeatureRendererV2

QString type() const { return mType; }

// to be overridden
/** to be overridden
* @param feature feature
* @return returns pointer to symbol or 0 if symbol was not found
*/
virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature ) = 0;

virtual void startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer ) = 0;
Expand All @@ -97,7 +100,9 @@ class CORE_EXPORT QgsFeatureRendererV2
{
SymbolLevels = 1, // rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
RotationField = 1 << 1, // rotate symbols by attribute value
MoreSymbolsPerFeature = 1 << 2 // may use more than one symbol to render a feature: symbolsForFeature() will return them
MoreSymbolsPerFeature = 1 << 2, // may use more than one symbol to render a feature: symbolsForFeature() will return them
Filter = 1 << 3, // features may be filtered, i.e. some features may not be rendered (categorized, rule based ...)
ScaleDependent = 1 << 4 // dependends on scale if feature will be rendered (rule based )
};

//! returns bitwise OR-ed capabilities of the renderer
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgsrulebasedrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ bool QgsRuleBasedRendererV2::Rule::isFilterOK( QgsFeature& f ) const

bool QgsRuleBasedRendererV2::Rule::isScaleOK( double scale ) const
{
if ( scale == 0 ) // so that we can count features in classes without scale context
return true;
if ( mScaleMinDenom == 0 && mScaleMaxDenom == 0 )
return true;
if ( mScaleMinDenom != 0 && mScaleMinDenom > scale )
Expand Down
2 changes: 1 addition & 1 deletion src/core/symbology-ng/qgsrulebasedrendererv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2

//! returns bitwise OR-ed capabilities of the renderer
//! \note added in 2.0
virtual int capabilities() { return MoreSymbolsPerFeature; }
virtual int capabilities() { return MoreSymbolsPerFeature | Filter | ScaleDependent; }

/////

Expand Down
92 changes: 81 additions & 11 deletions src/gui/attributetable/qgsattributetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "qgslogger.h"
#include "qgsattributeaction.h"
#include "qgsmapcanvas.h"
#include "qgsrendererv2.h"

#include <QtGui>
#include <QVariant>
Expand All @@ -44,7 +45,9 @@ QgsAttributeTableModel::QgsAttributeTableModel( QgsMapCanvas *canvas, QgsVectorL
connect( mLayer, SIGNAL( attributeAdded( int ) ), this, SLOT( attributeAdded( int ) ) );
connect( mLayer, SIGNAL( attributeDeleted( int ) ), this, SLOT( attributeDeleted( int ) ) );

connect( mLayer, SIGNAL( repaintRequested() ), this, SLOT( layerRepaintRequested() ) );
connect( mCanvas, SIGNAL( extentsChanged() ), this, SLOT( extentsChanged() ) );

extentsChanged();
}

Expand Down Expand Up @@ -289,21 +292,66 @@ void QgsAttributeTableModel::loadLayer()
rect = mCurrentExtent;
}

mLayer->select( QgsAttributeList(), rect, false );

QgsFeature f;
for ( i = 0; mLayer->nextFeature( f ); ++i )
QgsFeatureRendererV2* renderer = mLayer->rendererV2();
if ( !renderer )
{
QgsDebugMsg( "Cannot get renderer" );
}
else if ( mLayer->hasScaleBasedVisibility() &&
( mLayer->minimumScale() > mCanvas->mapRenderer()->scale() ||
mLayer->maximumScale() <= mCanvas->mapRenderer()->scale() ) )
{
featureAdded( f.id() );
QgsDebugMsg( "Out of scale limits" );
}
else
{
QgsRenderContext renderContext;
if ( renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
{
// setup scale
// mapRenderer()->renderContext()->scale is not automaticaly updated when
// render extent changes (because it's scale is used to identify if changed
// since last render) -> use local context
renderContext.setExtent( mCanvas->mapRenderer()->rendererContext()->extent() );
renderContext.setMapToPixel( mCanvas->mapRenderer()->rendererContext()->mapToPixel() );
renderContext.setRendererScale( mCanvas->mapRenderer()->scale() );
renderer->startRender( renderContext, mLayer );
}

if ( t.elapsed() > 5000 )
bool filter = renderer->capabilities() & QgsFeatureRendererV2::Filter;

QgsAttributeList attributeList = QgsAttributeList();
if ( filter )
{
bool cancel = false;
emit progress( i, cancel );
if ( cancel )
break;
QList<QString> attributeNameList = renderer->usedAttributes();
foreach ( QString attributeName, attributeNameList )
{
attributeList.append( mLayer->fieldNameIndex( attributeName ) );
}
}
mLayer->select( attributeList, rect, false );

t.restart();
QgsFeature f;
for ( i = 0; mLayer->nextFeature( f ); ++i )
{
if ( !filter || renderer->willRenderFeature( f ) )
{
featureAdded( f.id() );
}

if ( t.elapsed() > 5000 )
{
bool cancel = false;
emit progress( i, cancel );
if ( cancel )
break;

t.restart();
}
}
if ( renderer->capabilities() & QgsFeatureRendererV2::ScaleDependent )
{
renderer->stopRender( renderContext );
}
}
emit finished();
Expand Down Expand Up @@ -612,5 +660,27 @@ QgsFeature QgsAttributeTableModel::feature( const QModelIndex &idx ) const

void QgsAttributeTableModel::extentsChanged()
{
QgsDebugMsg( "Entered" );
mCurrentExtent = mCanvas->mapRenderer()->mapToLayerCoordinates( mLayer, mCanvas->extent() );

QSettings settings;
int behaviour = settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt();
if ( behaviour == 2 ) // features in current canvas
{
loadLayer();
}
}

void QgsAttributeTableModel::layerRepaintRequested()
{
QgsDebugMsg( "Entered" );
// Added to reload table if properties changed and so some features could become invisible
// TODO: in theory we need to reload table only if previous or new renderer
// capabilities are ScaleDependent or Filter
QSettings settings;
int behaviour = settings.value( "/qgis/attributeTableBehaviour", 0 ).toInt();
if ( behaviour == 2 ) // features in current canvas
{
loadLayer();
}
}
2 changes: 2 additions & 0 deletions src/gui/attributetable/qgsattributetablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
public slots:
void extentsChanged();

void layerRepaintRequested();

private slots:
/**
* Launched when attribute has been added
Expand Down
1 change: 1 addition & 0 deletions src/mapserver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ SET ( qgis_mapserv_SRCS
qgsbetweenfilter.cpp
qgscomparisonfilter.cpp
qgslogicalfilter.cpp
qgsspatialfilter.cpp
qgsftptransaction.cpp
qgsmslayerbuilder.cpp
qgshostedvdsbuilder.cpp
Expand Down
8 changes: 0 additions & 8 deletions src/mapserver/qgis_map_serv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,15 +523,7 @@ int main( int argc, char * argv[] )
continue;
}

//info format for GetFeatureInfo

//additionally support text/xml; format=sia2045
QString infoFormat = parameterMap.value( "INFO_FORMAT" );
if ( infoFormat.compare( "text/xml", Qt::CaseInsensitive ) == 0 && adminConfigParser->featureInfoFormatSIA2045() )
{
infoFormat = "text/xml; format=sia2045";
}

theRequestHandler->sendGetFeatureInfoResponse( featureInfoDoc, infoFormat );
delete theRequestHandler;
delete theServer;
Expand Down
124 changes: 116 additions & 8 deletions src/mapserver/qgsfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "qgsbetweenfilter.h"
#include "qgscomparisonfilter.h"
#include "qgslogicalfilter.h"
#include "qgsspatialfilter.h"
#include "qgsvectordataprovider.h"
#include <QDomElement>
#include <QStringList>
Expand Down Expand Up @@ -56,7 +57,8 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
}

//Name of the element indicates the type of filter
QString filterName = filterElem.localName();
//using tagName and to upper for interoperability
QString filterName = filterElem.tagName().toUpper();

if ( filterName == "AND" || filterName == "OR" || filterName == "NOT" )
{
Expand Down Expand Up @@ -91,6 +93,112 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
}
delete subFilter1; delete subFilter2; return 0;
}
// if the filter is spatial
if ( filterName == "BBOX" || filterName == "CONTAINS" || filterName == "CROSSES" || filterName == "DISJOINT" || filterName == "EQUALS" || filterName == "INTERSECTS" || filterName == "OVERLAPS" || filterName == "TOUCHES" || filterName == "WITHIN" )
{
QgsGeometry* geom;

QDomNodeList bNodes = filterElem.elementsByTagName( "Box" );
if ( bNodes.size() > 0 ) {
QDomElement bElem = bNodes.at( 0 ).toElement().firstChild().toElement();
QString coordSeparator = ",";
QString tupelSeparator = " ";
if ( bElem.hasAttribute( "cs" ) )
{
coordSeparator = bElem.attribute( "cs" );
}
if ( bElem.hasAttribute( "ts" ) )
{
tupelSeparator = bElem.attribute( "ts" );
}

QString bString = bElem.text();
bool conversionSuccess;
double minx = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &conversionSuccess );
double miny = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &conversionSuccess );
double maxx = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &conversionSuccess );
double maxy = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &conversionSuccess );
QgsRectangle* rect = new QgsRectangle( minx, miny, maxx, maxy );
geom = QgsGeometry::fromRect( *rect );
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "Point" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "LineString" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "Polygon" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "MultiPoint" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "MultiLineString" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
{
QDomNodeList gNodes = filterElem.elementsByTagName( "MultiPolygon" );
if ( gNodes.size() > 0 ) {
QDomElement gElem = gNodes.at( 0 ).toElement();
geom = QgsGeometry::fromGML2( gElem );
}
}

if ( !geom )
return 0;

if ( filterName == "BBOX" )
return new QgsSpatialFilter( QgsSpatialFilter::BBOX, geom );
if ( filterName == "CONTAINS" )
return new QgsSpatialFilter( QgsSpatialFilter::CONTAINS, geom );
if ( filterName == "CROSSES" )
return new QgsSpatialFilter( QgsSpatialFilter::CROSSES, geom );
if ( filterName == "DISJOINT" )
return new QgsSpatialFilter( QgsSpatialFilter::DISJOINT, geom );
if ( filterName == "EQUALS" )
return new QgsSpatialFilter( QgsSpatialFilter::EQUALS, geom );
if ( filterName == "INTERSECTS" )
return new QgsSpatialFilter( QgsSpatialFilter::INTERSECTS, geom );
if ( filterName == "OVERLAPS" )
return new QgsSpatialFilter( QgsSpatialFilter::OVERLAPS, geom );
if ( filterName == "TOUCHES" )
return new QgsSpatialFilter( QgsSpatialFilter::TOUCHES, geom );
if ( filterName == "WITHIN" )
return new QgsSpatialFilter( QgsSpatialFilter::WITHIN, geom );
return 0;
}

//assume it must be a comparison filter

Expand Down Expand Up @@ -153,33 +261,33 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
//now create the filter

//comparison filter?
if ( filterName == "PropertyIsEqualTo" )
if ( filterName == "PROPERTYISEQUALTO" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::EQUAL, literalList.at( 0 ) );
}
else if ( filterName == "PropertyIsNotEqualTo" )
else if ( filterName == "PROPERTYISNOTEQUALTO" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::NOT_EQUAL, literalList.at( 0 ) );
}
else if ( filterName == "PropertyIsLessThan" )
else if ( filterName == "PROPERTYISLESSTHAN" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::LESSER, literalList.at( 0 ) );
}
else if ( filterName == "PropertyIsGreaterThan" )
else if ( filterName == "PROPERTYISGREATERTHAN" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::GREATER, literalList.at( 0 ) );
}
else if ( filterName == "PropertyIsLessThanOrEqualTo" )
else if ( filterName == "PROPERTYISLESSTHANOREQUALTO" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::LESSER_OR_EQUAL, literalList.at( 0 ) );
}
else if ( filterName == "PropertyIsGreaterThanOrEqualTo" )
else if ( filterName == "PROPERTYISGREATERTHANOREQUALTO" )
{
return new QgsComparisonFilter( attributeIndex, QgsComparisonFilter::GREATER_OR_EQUAL, literalList.at( 0 ) );
}

//between filter?
else if ( filterName == "PropertyIsBetween" )
else if ( filterName == "PROPERTYISBETWEEN" )
{
return new QgsBetweenFilter( attributeIndex, literalList.at( 0 ), literalList.at( 1 ) );
}
Expand Down
67 changes: 0 additions & 67 deletions src/mapserver/qgshttprequesthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,73 +147,6 @@ void QgsHttpRequestHandler::sendGetFeatureInfoResponse( const QDomDocument& info
{
ba = infoDoc.toByteArray();
}
else if ( infoFormat == "text/xml; format=sia2045" )
{
QDomDocument outFeatureInfoDoc;
QDomElement infoDocElement = infoDoc.documentElement();
QDomElement outInfoDocElement = outFeatureInfoDoc.importNode( infoDocElement, false ).toElement();
outFeatureInfoDoc.appendChild( outInfoDocElement );

QString currentAttributeName;
QString currentAttributeValue;
QDomElement currentAttributeElem;
QString currentLayerName;
QDomElement currentLayerElem;
QDomNodeList layerNodeList = infoDocElement.elementsByTagName( "Layer" );
for ( int i = 0; i < layerNodeList.size(); ++i )
{
currentLayerElem = layerNodeList.at( i ).toElement();
currentLayerName = currentLayerElem.attribute( "name" );
QDomElement currentFeatureElem;

QDomNodeList featureList = currentLayerElem.elementsByTagName( "Feature" );
if ( featureList.size() < 1 )
{
//raster?
QDomNodeList attributeList = currentLayerElem.elementsByTagName( "Attribute" );
QDomElement rasterLayerElem;
if ( attributeList.size() > 0 )
{
rasterLayerElem = outFeatureInfoDoc.createElement( currentLayerName );
}
for ( int j = 0; j < attributeList.size(); ++j )
{
currentAttributeElem = attributeList.at( j ).toElement();
currentAttributeName = currentAttributeElem.attribute( "name" );
currentAttributeValue = currentAttributeElem.attribute( "value" );
QDomElement outAttributeElem = outFeatureInfoDoc.createElement( currentAttributeName );
QDomText outAttributeText = outFeatureInfoDoc.createTextNode( currentAttributeValue );
outAttributeElem.appendChild( outAttributeText );
rasterLayerElem.appendChild( outAttributeElem );
}
if ( attributeList.size() > 0 )
{
outInfoDocElement.appendChild( rasterLayerElem );
}
}
else //vector
{
for ( int j = 0; j < featureList.size(); ++j )
{
QDomElement outFeatureElem = outFeatureInfoDoc.createElement( currentLayerName );
currentFeatureElem = featureList.at( j ).toElement();
QDomNodeList attributeList = currentFeatureElem.elementsByTagName( "Attribute" );
for ( int k = 0; k < attributeList.size(); ++k )
{
currentAttributeElem = attributeList.at( k ).toElement();
currentAttributeName = currentAttributeElem.attribute( "name" );
currentAttributeValue = currentAttributeElem.attribute( "value" );
QDomElement outAttributeElem = outFeatureInfoDoc.createElement( currentAttributeName );
QDomText outAttributeText = outFeatureInfoDoc.createTextNode( currentAttributeValue );
outAttributeElem.appendChild( outAttributeText );
outFeatureElem.appendChild( outAttributeElem );
}
outInfoDocElement.appendChild( outFeatureElem );
}
}
}
ba = outFeatureInfoDoc.toByteArray();
}
else if ( infoFormat == "text/plain" || infoFormat == "text/html" )
{
//create string
Expand Down
2 changes: 1 addition & 1 deletion src/mapserver/qgspostrequesthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ QMap<QString, QString> QgsPostRequestHandler::parseInput()
QDomElement docElem = doc.documentElement();
parameters.insert( "VERSION", docElem.attribute( "version" ) );
parameters.insert( "SERVICE", docElem.attribute( "service" ) );
parameters.insert( "REQUEST", docElem.localName() );
parameters.insert( "REQUEST", docElem.tagName() );
parameters.insert( "REQUEST_BODY", inputString );
}

Expand Down
40 changes: 40 additions & 0 deletions src/mapserver/qgsprojectparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,26 @@ void QgsProjectParser::serviceCapabilities( QDomElement& parentElement, QDomDocu
serviceElem.appendChild( wmsAbstractElem );
}

//keyword list
QDomElement keywordListElem = propertiesElem.firstChildElement( "WMSKeywordList" );
if ( !keywordListElem.isNull() )
{
QDomElement wmsKeywordElem = doc.createElement( "KeywordList" );
QDomNodeList keywordList = keywordListElem.elementsByTagName( "value" );
for ( int i = 0; i < keywordList.size(); ++i )
{
QDomElement keywordElem = doc.createElement( "Keyword" );
QDomText keywordText = doc.createTextNode( keywordList.at( i ).toElement().text() );
keywordElem.appendChild( keywordText );
wmsKeywordElem.appendChild( keywordElem );
}

if ( keywordList.size() > 0 )
{
serviceElem.appendChild( wmsKeywordElem );
}
}

//OnlineResource element is mandatory according to the WMS specification
QDomElement wmsOnlineResourceElem = propertiesElem.firstChildElement( "WMSOnlineResource" );
QDomElement onlineResourceElem = doc.createElement( "OnlineResource" );
Expand Down Expand Up @@ -1785,6 +1805,26 @@ void QgsProjectParser::serviceCapabilities( QDomElement& parentElement, QDomDocu

serviceElem.appendChild( contactInfoElem );

//Fees
QDomElement feesElem = propertiesElem.firstChildElement( "WMSFees" );
if ( !feesElem.isNull() )
{
QDomElement wmsFeesElem = doc.createElement( "Fees" );
QDomText wmsFeesText = doc.createTextNode( feesElem.text() );
wmsFeesElem.appendChild( wmsFeesText );
serviceElem.appendChild( wmsFeesElem );
}

//AccessConstraints
QDomElement accessConstraintsElem = propertiesElem.firstChildElement( "WMSAccessConstraints" );
if ( !accessConstraintsElem.isNull() )
{
QDomElement wmsAccessConstraintsElem = doc.createElement( "AccessConstraints" );
QDomText wmsAccessConstraintsText = doc.createTextNode( accessConstraintsElem.text() );
wmsAccessConstraintsElem.appendChild( wmsAccessConstraintsText );
serviceElem.appendChild( wmsAccessConstraintsElem );
}

//MaxWidth / MaxHeight for WMS 1.3
QString version = doc.documentElement().attribute( "version" );
if ( version != "1.1.1" )
Expand Down
77 changes: 77 additions & 0 deletions src/mapserver/qgsspatialfilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/***************************************************************************
qgsspatialfilter.cpp
-----------------------
begin : Oct 19, 2012
copyright : (C) 2012 by René-Luc D'Hont
email : rldhont at 3liz dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsspatialfilter.h"
#include "qgsgeometry.h"
#include <QDomElement>

QgsSpatialFilter::QgsSpatialFilter(): QgsFilter(), mSpatialType( QgsSpatialFilter::UNKNOWN ), mGeom( 0 )
{
}

QgsSpatialFilter::QgsSpatialFilter( SPATIAL_TYPE st, QgsGeometry* geom ): QgsFilter(), mSpatialType( st ), mGeom( geom )
{
}

QgsSpatialFilter::~QgsSpatialFilter()
{
delete mGeom;
}

bool QgsSpatialFilter::evaluate( const QgsFeature& f ) const
{
if ( !mGeom )
{
return true;
}

QgsGeometry* geom = ( new QgsFeature( f ) )->geometry();
switch ( mSpatialType )
{
case BBOX:
return geom->intersects( mGeom->boundingBox() );
break;
case CONTAINS:
return geom->contains( mGeom );
break;
case CROSSES:
return geom->crosses( mGeom );
break;
case DISJOINT:
return geom->disjoint( mGeom );
break;
case EQUALS:
return geom->equals( mGeom );
break;
case INTERSECTS:
return geom->intersects( mGeom );
break;
case OVERLAPS:
return geom->overlaps( mGeom );
break;
case TOUCHES:
return geom->touches( mGeom );
break;
case WITHIN:
return geom->within( mGeom );
break;
case UNKNOWN:
default:
break;
}
return false;
}
73 changes: 73 additions & 0 deletions src/mapserver/qgsspatialfilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/***************************************************************************
qgsspatialfilter.h
---------------------
begin : Oct 19, 2012
copyright : (C) 2012 by René-Luc D'Hont
email : rldhont at 3liz dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSSPATIALFILTER_H
#define QGSSPATIALFILTER_H

#include <qgsfilter.h>
#include <qgsgeometry.h>
#include <QDomElement>

/**A filter for spatial filter (bbox, intersects, within, disjoint)
Sample xml fragment:
<Filter xmlns="http://www.opengis.net/ogc">
<BBOX>
<gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326">
<gml:coordinates decimal="." cs="," ts=" ">135.45,-47.425 157.95,-36.175</gml:coordinates>
</gml:Box>
</BBOX>
</Filter>
*/
class QgsSpatialFilter: public QgsFilter
{
public:
enum SPATIAL_TYPE
{
BBOX,
CONTAINS,
CROSSES,
EQUALS,
DISJOINT,
INTERSECTS,
OVERLAPS,
TOUCHES,
WITHIN,
UNKNOWN
};

QgsSpatialFilter();
QgsSpatialFilter( SPATIAL_TYPE st, QgsGeometry* geom );
~QgsSpatialFilter();

/**Evaluates a feature against the filter.
@return true if the filter applies for the feature*/
bool evaluate( const QgsFeature& f ) const;

//setters and getters
SPATIAL_TYPE spatialType() const {return mSpatialType;}
void setSpatialType( SPATIAL_TYPE t ) {mSpatialType = t;}

//setters and getters
QgsGeometry* geometry() const {return mGeom;}
void setGeometry( QgsGeometry* g ) {mGeom = g;}

private:
SPATIAL_TYPE mSpatialType;
QgsGeometry* mGeom;
};

#endif //QGSSPATIALFILTER_H
208 changes: 194 additions & 14 deletions src/mapserver/qgswfsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,11 @@ QDomDocument QgsWFSServer::getCapabilities()
getFeatureFormatElement.appendChild( gmlFormatElement );
QDomElement geojsonFormatElement = doc.createElement( "GeoJSON" );/*wfs:GeoJSON*/
getFeatureFormatElement.appendChild( geojsonFormatElement );
QDomElement getFeatureDhcTypeElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
getFeatureElement.appendChild( getFeatureDhcTypeElement );
QDomElement getFeatureDhcTypeGetElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
getFeatureElement.appendChild( getFeatureDhcTypeGetElement );
QDomElement getFeatureDhcTypePostElement = dcpTypeElement.cloneNode().toElement();//this is the same as for 'GetCapabilities'
getFeatureDhcTypePostElement.firstChild().firstChild().toElement().setTagName( "Post" );
getFeatureElement.appendChild( getFeatureDhcTypePostElement );

//wfs:Transaction
QDomElement transactionElement = doc.createElement( "Transaction"/*wfs:Transaction*/ );
Expand Down Expand Up @@ -240,14 +243,19 @@ QDomDocument QgsWFSServer::getCapabilities()
filterCapabilitiesElement.appendChild( spatialCapabilitiesElement );
QDomElement spatialOperatorsElement = doc.createElement( "ogc:Spatial_Operators"/*ogc:Spatial_Operators*/ );
spatialCapabilitiesElement.appendChild( spatialOperatorsElement );
QDomElement ogcBboxElement = doc.createElement( "ogc:BBOX"/*ogc:BBOX*/ );
spatialOperatorsElement.appendChild( ogcBboxElement );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:BBOX"/*ogc:BBOX*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Disjoint"/*ogc:Disjoint*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Intersects"/*ogc:Intersects*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Touches"/*ogc:Touches*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Crosses"/*ogc:Crosses*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Contains"/*ogc:Contains*/ ) );
spatialOperatorsElement.appendChild( doc.createElement( "ogc:Overlaps"/*ogc:Overlaps*/ ) );
QDomElement scalarCapabilitiesElement = doc.createElement( "ogc:Scalar_Capabilities"/*ogc:Scalar_Capabilities*/ );
filterCapabilitiesElement.appendChild( scalarCapabilitiesElement );
QDomElement comparisonOperatorsElement = doc.createElement( "ogc:Comparison_Operators"/*ogc:Comparison_Operators*/ );
scalarCapabilitiesElement.appendChild( comparisonOperatorsElement );
QDomElement simpleComparisonsElement = doc.createElement( "ogc:Simple_Comparisons"/*ogc:Simple_Comparisons*/ );
comparisonOperatorsElement.appendChild( simpleComparisonsElement );
comparisonOperatorsElement.appendChild( doc.createElement( "ogc:Simple_Comparisons"/*ogc:Simple_Comparisons*/ ) );
comparisonOperatorsElement.appendChild( doc.createElement( "ogc:Between"/*ogc:Simple_Comparisons*/ ) );
return doc;
}

Expand Down Expand Up @@ -292,6 +300,178 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
QgsDebugMsg( "Info format is:" + format );

QStringList wfsLayersId = mConfigParser->wfsLayers();

QList<QgsMapLayer*> layerList;
QgsMapLayer* currentLayer = 0;

QDomDocument doc;
QString errorMsg;
if ( doc.setContent( mParameterMap.value( "REQUEST_BODY" ), true, &errorMsg ) )
{
QDomElement docElem = doc.documentElement();

long maxFeat = 0;
long featureCounter = 0;
long maxFeatures = 0;
if ( docElem.hasAttribute( "maxFeatures" ) )
maxFeatures = docElem.attribute( "maxFeatures" ).toLong();

QDomNodeList queryNodes = docElem.elementsByTagName( "Query" );
for ( int i = 0; i < queryNodes.size(); i++ )
{
QDomElement queryElem = queryNodes.at( 0 ).toElement();
mTypeName = queryElem.attribute( "typeName", "" );
if ( mTypeName.contains( ":" ) )
{
mTypeName = mTypeName.section( ":", 1, 1 );
}

layerList = mConfigParser->mapLayerFromStyle( mTypeName, "" );
currentLayer = layerList.at( 0 );
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>( currentLayer );
if ( layer && wfsLayersId.contains( layer->id() ) )
{
//is there alias info for this vector layer?
QMap< int, QString > layerAliasInfo;
const QMap< QString, QString >& aliasMap = layer->attributeAliases();
QMap< QString, QString >::const_iterator aliasIt = aliasMap.constBegin();
for ( ; aliasIt != aliasMap.constEnd(); ++aliasIt )
{
int attrIndex = layer->fieldNameIndex( aliasIt.key() );
if ( attrIndex != -1 )
{
layerAliasInfo.insert( attrIndex, aliasIt.value() );
}
}

//excluded attributes for this layer
const QSet<QString>& layerExcludedAttributes = layer->excludeAttributesWFS();

//do a select with searchRect and go through all the features
QgsVectorDataProvider* provider = layer->dataProvider();
if ( !provider )
{
return 2;
}

QgsFeature feature;
QgsAttributeMap featureAttributes;
const QgsFieldMap& fields = provider->fields();

mWithGeom = true;
QgsAttributeList attrIndexes = provider->attributeIndexes();

QDomNodeList queryChildNodes = queryElem.childNodes();
if ( queryChildNodes.size() )
{
mWithGeom = false;
QStringList::const_iterator alstIt;
QList<int> idxList;
QMap<QString, int> fieldMap = provider->fieldNameMap();
QMap<QString, int>::const_iterator fieldIt;
QString fieldName;
QDomElement propertyElem;
for ( int q = 0; q < queryChildNodes.size(); q++ )
{
QDomElement queryChildElem = queryChildNodes.at( q ).toElement();
if ( queryChildElem.tagName() == "PropertyName" )
{
fieldName = queryChildElem.text();
if ( fieldName.contains( ":" ) )
{
fieldName = fieldName.section( ":", 1, 1 );
}
fieldIt = fieldMap.find( fieldName );
if ( fieldIt != fieldMap.end() )
{
idxList.append( fieldIt.value() );
}
else if ( fieldName == "geometry" )
{
mWithGeom = true;
}
}
}
if ( idxList.size() > 0 || mWithGeom )
{
attrIndexes = idxList;
}
else
{
mWithGeom = true;
}
}

//map extent
QgsRectangle searchRect = layer->extent();
searchRect.set( searchRect.xMinimum() - 0.000001
, searchRect.yMinimum() - 0.000001
, searchRect.xMaximum() + 0.000001
, searchRect.yMaximum() + 0.000001 );
QgsCoordinateReferenceSystem layerCrs = layer->crs();

if ( maxFeatures == 0 )
maxFeat += layer->featureCount();

provider->select( attrIndexes, searchRect, mWithGeom, true );

if ( i == 0 )
startGetFeature( request, format, layerCrs, &searchRect );

long featCounter = 0;
QDomNodeList filterNodes = queryElem.elementsByTagName( "Filter" );
if (filterNodes.size() > 0 )
{
QDomElement filterElem = filterNodes.at( 0 ).toElement();
QDomNodeList fidNodes = filterElem.elementsByTagName( "FeatureId" );
if ( fidNodes.size() > 0 )
{
QDomElement fidElem;
for ( int f = 0; f < fidNodes.size(); f++ )
{
fidElem = fidNodes.at( f ).toElement();
provider->featureAtId( fidElem.attribute( "fid" ).toInt(), feature, mWithGeom, attrIndexes );
sendGetFeature( request, format, &feature, featCounter, layerCrs, fields, layerExcludedAttributes );
++featCounter;
++featureCounter;
}
}
else
{
QgsFilter* mFilter = QgsFilter::createFilterFromXml( filterElem.firstChild().toElement(), layer );
if ( mFilter )
{
while ( provider->nextFeature( feature ) && featureCounter < maxFeat )
{
if ( mFilter->evaluate( feature ) )
{
sendGetFeature( request, format, &feature, featCounter, layerCrs, fields, layerExcludedAttributes );
++featCounter;
++featureCounter;
}
}
}
}
}
else
{
while ( provider->nextFeature( feature ) && featureCounter < maxFeat )
{
sendGetFeature( request, format, &feature, featCounter, layerCrs, fields, layerExcludedAttributes );
++featCounter;
++featureCounter;
}
}
}

}

endGetFeature( request, format );
return 0;

}

//read TYPENAME
QMap<QString, QString>::const_iterator type_name_it = mParameterMap.find( "TYPENAME" );
if ( type_name_it != mParameterMap.end() )
Expand All @@ -303,11 +483,6 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
return 1;
}

QStringList wfsLayersId = mConfigParser->wfsLayers();

QList<QgsMapLayer*> layerList;
QgsMapLayer* currentLayer = 0;

layerList = mConfigParser->mapLayerFromStyle( mTypeName, "" );
currentLayer = layerList.at( 0 );

Expand Down Expand Up @@ -1069,12 +1244,17 @@ QgsFeatureIds QgsWFSServer::getFeatureIdsFromFilter( QDomElement filter, QgsVect
QgsFeatureIds fids;

QgsVectorDataProvider* provider = layer->dataProvider();
QDomElement filterFirstElem = filter.firstChild().toElement();
QDomNodeList fidNodes = filter.elementsByTagName( "FeatureId" );

if ( filterFirstElem.localName() == "FeatureId" )
if ( fidNodes.size() != 0 )
{
QDomElement fidElem;
bool conversionSuccess;
fids.insert( filterFirstElem.attribute( "fid" ).toInt( &conversionSuccess ) );
for ( int i = 0; i < fidNodes.size(); ++i )
{
fidElem = fidNodes.at( i ).toElement();
fids.insert( fidElem.attribute( "fid" ).toInt( &conversionSuccess ) );
}
}
else
{
Expand Down
127 changes: 127 additions & 0 deletions src/mapserver/qgswmsserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,8 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
renderContext.setPainter( 0 );
}

bool sia2045 = mConfigParser->featureInfoFormatSIA2045();

//layers can have assigned a different name for GetCapabilities
QHash<QString, QString> layerAliasMap = mConfigParser->featureInfoLayerAliasMap();

Expand Down Expand Up @@ -805,6 +807,10 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
}
layerElement.setAttribute( "name", layerName );
getFeatureInfoElement.appendChild( layerElement );
if ( sia2045 ) //the name might not be unique after alias replacement
{
layerElement.setAttribute( "id", currentLayer->id() );
}

//switch depending on vector or raster
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
Expand Down Expand Up @@ -845,6 +851,11 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
}

if ( sia2045 && mParameterMap.value( "INFO_FORMAT" ).compare( "text/xml", Qt::CaseInsensitive ) == 0 )
{
convertFeatureInfoToSIA2045( result );
}

restoreLayerFilters( originalLayerFilters );
delete featuresRect;
delete infoPoint;
Expand Down Expand Up @@ -2058,3 +2069,119 @@ void QgsWMSServer::addXMLDeclaration( QDomDocument& doc ) const
QDomProcessingInstruction xmlDeclaration = doc.createProcessingInstruction( "xml", "version=\"1.0\"" );
doc.appendChild( xmlDeclaration );
}

void QgsWMSServer::convertFeatureInfoToSIA2045( QDomDocument& doc )
{
QDomDocument SIAInfoDoc;
QDomElement infoDocElement = doc.documentElement();
QDomElement SIAInfoDocElement = SIAInfoDoc.importNode( infoDocElement, false ).toElement();
SIAInfoDoc.appendChild( SIAInfoDocElement );

QString currentAttributeName;
QString currentAttributeValue;
QDomElement currentAttributeElem;
QString currentLayerName;
QDomElement currentLayerElem;
QDomNodeList layerNodeList = infoDocElement.elementsByTagName( "Layer" );
for ( int i = 0; i < layerNodeList.size(); ++i )
{
currentLayerElem = layerNodeList.at( i ).toElement();
currentLayerName = currentLayerElem.attribute( "name" );

QDomElement currentFeatureElem;

QDomNodeList featureList = currentLayerElem.elementsByTagName( "Feature" );
if ( featureList.size() < 1 )
{
//raster?
QDomNodeList attributeList = currentLayerElem.elementsByTagName( "Attribute" );
QDomElement rasterLayerElem;
if ( attributeList.size() > 0 )
{
rasterLayerElem = SIAInfoDoc.createElement( currentLayerName );
}
for ( int j = 0; j < attributeList.size(); ++j )
{
currentAttributeElem = attributeList.at( j ).toElement();
currentAttributeName = currentAttributeElem.attribute( "name" );
currentAttributeValue = currentAttributeElem.attribute( "value" );
QDomElement outAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
QDomText outAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
outAttributeElem.appendChild( outAttributeText );
rasterLayerElem.appendChild( outAttributeElem );
}
if ( attributeList.size() > 0 )
{
SIAInfoDocElement.appendChild( rasterLayerElem );
}
}
else //vector
{
//property attributes
QSet<QString> layerPropertyAttributes;
QString currentLayerId = currentLayerElem.attribute( "id" );
if ( !currentLayerId.isEmpty() )
{
QgsMapLayer* currentLayer = QgsMapLayerRegistry::instance()->mapLayer( currentLayerId );
if ( currentLayer )
{
QString WMSPropertyAttributesString = currentLayer->customProperty( "WMSPropertyAttributes" ).toString();
if ( !WMSPropertyAttributesString.isEmpty() )
{
QStringList propertyList = WMSPropertyAttributesString.split( "//" );
QStringList::const_iterator propertyIt = propertyList.constBegin();
for ( ; propertyIt != propertyList.constEnd(); ++propertyIt )
{
layerPropertyAttributes.insert( *propertyIt );
}
}
}
}

QDomElement propertyRefChild; //child to insert the next property after (or
for ( int j = 0; j < featureList.size(); ++j )
{
QDomElement SIAFeatureElem = SIAInfoDoc.createElement( currentLayerName );
currentFeatureElem = featureList.at( j ).toElement();
QDomNodeList attributeList = currentFeatureElem.elementsByTagName( "Attribute" );

for ( int k = 0; k < attributeList.size(); ++k )
{
currentAttributeElem = attributeList.at( k ).toElement();
currentAttributeName = currentAttributeElem.attribute( "name" );
currentAttributeValue = currentAttributeElem.attribute( "value" );
if ( layerPropertyAttributes.contains( currentAttributeName ) )
{
QDomElement propertyElem = SIAInfoDoc.createElement( "property" );
QDomElement identifierElem = SIAInfoDoc.createElement( "identifier" );
QDomText identifierText = SIAInfoDoc.createTextNode( currentAttributeName );
identifierElem.appendChild( identifierText );
QDomElement valueElem = SIAInfoDoc.createElement( "value" );
QDomText valueText = SIAInfoDoc.createTextNode( currentAttributeValue );
valueElem.appendChild( valueText );
propertyElem.appendChild( identifierElem );
propertyElem.appendChild( valueElem );
if ( propertyRefChild.isNull() )
{
SIAFeatureElem.insertBefore( propertyElem, QDomNode() );
propertyRefChild = propertyElem;
}
else
{
SIAFeatureElem.insertAfter( propertyElem, propertyRefChild );
}
}
else
{
QDomElement SIAAttributeElem = SIAInfoDoc.createElement( currentAttributeName );
QDomText SIAAttributeText = SIAInfoDoc.createTextNode( currentAttributeValue );
SIAAttributeElem.appendChild( SIAAttributeText );
SIAFeatureElem.appendChild( SIAAttributeElem );
}
}
SIAInfoDocElement.appendChild( SIAFeatureElem );
}
}
}
doc = SIAInfoDoc;
}
3 changes: 3 additions & 0 deletions src/mapserver/qgswmsserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ class QgsWMSServer
/**Add '<?xml version="1.0" ?>'. Some clients need an xml declaration (though it is not strictly required)*/
void addXMLDeclaration( QDomDocument& doc ) const;

/**Converts a feature info xml document to SIA2045 norm*/
void convertFeatureInfoToSIA2045( QDomDocument& doc );

/**Map containing the WMS parameters*/
QMap<QString, QString> mParameterMap;
QgsConfigParser* mConfigParser;
Expand Down
1 change: 1 addition & 0 deletions src/plugins/globe/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ ADD_LIBRARY (globeplugin MODULE ${globe_plugin_SRCS} ${globe_plugin_MOC_SRCS} ${
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_BINARY_DIR}
${OSGEARTH_INCLUDE_DIR}
${OSG_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
../../core ../../core/raster ../../core/renderer ../../core/symbology
../../gui
Expand Down
54 changes: 42 additions & 12 deletions src/ui/qgsprojectpropertiesbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
<height>489</height>
<height>497</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_13">
Expand Down Expand Up @@ -799,7 +799,7 @@
<x>0</x>
<y>0</y>
<width>600</width>
<height>984</height>
<height>1085</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_15">
Expand All @@ -815,6 +815,16 @@
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Person</string>
</property>
<property name="buddy">
<cstring>mWMSContactPerson</cstring>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
Expand Down Expand Up @@ -851,16 +861,6 @@
<item row="2" column="1">
<widget class="QLineEdit" name="mWMSOnlineResourceLineEdit"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Person</string>
</property>
<property name="buddy">
<cstring>mWMSContactPerson</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="mWMSContactPerson"/>
</item>
Expand Down Expand Up @@ -900,6 +900,36 @@
<item row="6" column="1">
<widget class="QTextEdit" name="mWMSAbstract"/>
</item>
<item row="7" column="1">
<widget class="QLineEdit" name="mWMSFees"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="mWMSFeesLabel">
<property name="text">
<string>Fees</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLineEdit" name="mWMSAccessConstraints"/>
</item>
<item row="8" column="0">
<widget class="QLabel" name="mWMSAccessConstraintsLabel">
<property name="text">
<string>Access constraints</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLineEdit" name="mWMSKeywordList"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="mWMSKeywordListLabel">
<property name="text">
<string>Keyword list</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down
82 changes: 67 additions & 15 deletions src/ui/qgsrasterlayerpropertiesbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>652</width>
<width>797</width>
<height>515</height>
</rect>
</property>
Expand Down Expand Up @@ -34,7 +34,7 @@
<item row="0" column="0" colspan="4">
<widget class="QTabWidget" name="tabBar">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<property name="iconSize">
<size>
Expand Down Expand Up @@ -622,31 +622,83 @@
<property name="margin">
<number>11</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="textLabel1_2_2_2">
<item row="0" column="0">
<widget class="QLabel" name="textLabel1_3">
<property name="toolTip">
<string>MInimum scale denominator.</string>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>Less than:</string>
<string>Maximum scale:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="textLabel1_3">
<item row="0" column="4">
<widget class="QgsScaleComboBox" name="cbMaximumScale" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Minimum scale (maximum scale denominator).</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsScaleComboBox" name="cbMinimumScale" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Maximum scale (minimum scale denominator).</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="textLabel1_2_2_2">
<property name="toolTip">
<string>Maximum scale denominator</string>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
<enum>Qt::LeftToRight</enum>
</property>
<property name="text">
<string>More than or equal to:</string>
<string>Minimum scale</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QgsScaleComboBox" name="cbMaximumScale" native="true"/>
<item row="0" column="2">
<widget class="QPushButton" name="mMinimumScaleSetCurrentPushButton">
<property name="text">
<string>Set current</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsScaleComboBox" name="cbMinimumScale" native="true"/>
<item row="0" column="5">
<widget class="QPushButton" name="mMaximumScaleSetCurrentPushButton">
<property name="text">
<string>Set current</string>
</property>
</widget>
</item>
</layout>
</widget>
Expand Down Expand Up @@ -938,7 +990,7 @@
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'DejaVu Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'Cantarell'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
Expand Down
91 changes: 78 additions & 13 deletions src/ui/qgsvectorlayerpropertiesbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<item row="1" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>4</number>
</property>
<property name="iconSize">
<size>
Expand Down Expand Up @@ -391,8 +391,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>914</width>
<height>746</height>
<width>920</width>
<height>756</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
Expand Down Expand Up @@ -489,25 +489,83 @@
<property name="margin">
<number>11</number>
</property>
<item row="0" column="2">
<item row="0" column="3">
<widget class="QLabel" name="textLabel1_2_2">
<property name="toolTip">
<string>Maximum scale (minimum scale denominator).</string>
</property>
<property name="text">
<string>Less than:</string>
<string>Minimum scale:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="textLabel1">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Minimum scale denominator.</string>
</property>
<property name="text">
<string>More than or equal to:</string>
<string>Maximum scale:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsScaleComboBox" name="cbMinimumScale"/>
<widget class="QgsScaleComboBox" name="cbMinimumScale" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Maximum scale (minimum scale denominator).</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QgsScaleComboBox" name="cbMaximumScale"/>
<item row="0" column="4">
<widget class="QgsScaleComboBox" name="cbMaximumScale" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Minimum scale (maximum scale denominator).</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="mMinimumScaleSetCurrentPushButton">
<property name="text">
<string>Set current</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QPushButton" name="mMaximumScaleSetCurrentPushButton">
<property name="text">
<string>Set current</string>
</property>
</widget>
</item>
</layout>
</widget>
Expand Down Expand Up @@ -760,8 +818,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>896</width>
<height>728</height>
<width>912</width>
<height>748</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
Expand Down Expand Up @@ -872,8 +930,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>896</width>
<height>728</height>
<width>912</width>
<height>748</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_17">
Expand Down Expand Up @@ -966,6 +1024,13 @@
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsScaleComboBox</class>
<extends>QWidget</extends>
<header>qgsscalecombobox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>pbnIndex</tabstop>
<tabstop>cbMinimumScale</tabstop>
Expand Down