116 changes: 116 additions & 0 deletions src/app/qgsprojectproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "qgsprojectproperties.h"

//qgis includes
#include "qgisapp.h"
#include "qgscomposer.h"
#include "qgscontexthelp.h"
#include "qgscoordinatetransform.h"
#include "qgslogger.h"
Expand All @@ -27,6 +29,7 @@
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsproject.h"
#include "qgsprojectlayergroupdialog.h"
#include "qgsrenderer.h"
#include "qgssnappingdialog.h"
#include "qgsrasterlayer.h"
Expand Down Expand Up @@ -261,6 +264,22 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa

grpWMSList->setChecked( mWMSList->count() > 0 );

//composer restriction for WMS
values = QgsProject::instance()->readListEntry( "WMSComposerList", "/", &ok );
mWMSComposerGroupBox->setChecked( ok );
if ( ok )
{
mComposerListWidget->addItems( values );
}

//layer restriction for WMS
values = QgsProject::instance()->readListEntry( "WMSRestrictedLayers", "/", &ok );
mLayerRestrictionsGroupBox->setChecked( ok );
if ( ok )
{
mLayerRestrictionsListWidget->addItems( values );
}

bool addWktGeometry = QgsProject::instance()->readBoolEntry( "WMSAddWktGeometry", "/" );
mAddWktGeometryCheckBox->setChecked( addWktGeometry );

Expand Down Expand Up @@ -539,6 +558,36 @@ void QgsProjectProperties::apply()
QgsProject::instance()->removeEntry( "WMSCrsList", "/" );
}

//WMS composer restrictions
if ( mWMSComposerGroupBox->isChecked() )
{
QStringList composerTitles;
for ( int i = 0; i < mComposerListWidget->count(); ++i )
{
composerTitles << mComposerListWidget->item( i )->text();
}
QgsProject::instance()->writeEntry( "WMSComposerList", "/", composerTitles );
}
else
{
QgsProject::instance()->removeEntry( "WMSComposerList", "/" );
}

//WMS layer restrictions
if ( mLayerRestrictionsGroupBox->isChecked() )
{
QStringList layerNames;
for ( int i = 0; i < mLayerRestrictionsListWidget->count(); ++i )
{
layerNames << mLayerRestrictionsListWidget->item( i )->text();
}
QgsProject::instance()->writeEntry( "WMSRestrictedLayers", "/", layerNames );
}
else
{
QgsProject::instance()->removeEntry( "WMSRestrictedLayers", "/" );
}

QgsProject::instance()->writeEntry( "WMSAddWktGeometry", "/", mAddWktGeometryCheckBox->isChecked() );

QString maxWidthText = mMaxWidthLineEdit->text();
Expand Down Expand Up @@ -747,6 +796,73 @@ void QgsProjectProperties::on_pbnWMSSetUsedSRS_clicked()
mWMSList->addItems( crsList.values() );
}

void QgsProjectProperties::on_mAddWMSComposerButton_clicked()
{
QSet<QgsComposer*> projectComposers = QgisApp::instance()->printComposers();
QStringList composerTitles;
QSet<QgsComposer*>::const_iterator cIt = projectComposers.constBegin();
for ( ; cIt != projectComposers.constEnd(); ++cIt )
{
composerTitles << ( *cIt )->title();
}

bool ok;
QString name = QInputDialog::getItem( this, tr( "Select print composer" ), tr( "Composer Title" ), composerTitles, 0, false, &ok );
if ( ok )
{
if ( mComposerListWidget->findItems( name, Qt::MatchExactly ).size() < 1 )
{
mComposerListWidget->addItem( name );
}
}
}

void QgsProjectProperties::on_mRemoveWMSComposerButton_clicked()
{
QListWidgetItem* currentItem = mComposerListWidget->currentItem();
if ( currentItem )
{
delete mComposerListWidget->takeItem( mComposerListWidget->row( currentItem ) );
}
}

void QgsProjectProperties::on_mAddLayerRestrictionButton_clicked()
{
QgsProjectLayerGroupDialog d( this, QgsProject::instance()->fileName() );
d.setWindowTitle( tr( "Select restricted layers and groups" ) );
if ( d.exec() == QDialog::Accepted )
{
QStringList layerNames = d.selectedLayerNames();
QStringList::const_iterator layerIt = layerNames.constBegin();
for ( ; layerIt != layerNames.constEnd(); ++layerIt )
{
if ( mLayerRestrictionsListWidget->findItems( *layerIt, Qt::MatchExactly ).size() < 1 )
{
mLayerRestrictionsListWidget->addItem( *layerIt );
}
}

QStringList groups = d.selectedGroups();
QStringList::const_iterator groupIt = groups.constBegin();
for ( ; groupIt != groups.constEnd(); ++groupIt )
{
if ( mLayerRestrictionsListWidget->findItems( *groupIt, Qt::MatchExactly ).size() < 1 )
{
mLayerRestrictionsListWidget->addItem( *groupIt );
}
}
}
}

void QgsProjectProperties::on_mRemoveLayerRestrictionButton_clicked()
{
QListWidgetItem* currentItem = mLayerRestrictionsListWidget->currentItem();
if ( currentItem )
{
delete mLayerRestrictionsListWidget->takeItem( mLayerRestrictionsListWidget->row( currentItem ) );
}
}

void QgsProjectProperties::on_pbnWFSLayersSelectAll_clicked()
{
for ( int i = 0; i < twWFSLayers->rowCount(); i++ )
Expand Down
4 changes: 4 additions & 0 deletions src/app/qgsprojectproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ class QgsProjectProperties : public QDialog, private Ui::QgsProjectPropertiesBas
void on_pbnWMSAddSRS_clicked();
void on_pbnWMSRemoveSRS_clicked();
void on_pbnWMSSetUsedSRS_clicked();
void on_mAddWMSComposerButton_clicked();
void on_mRemoveWMSComposerButton_clicked();
void on_mAddLayerRestrictionButton_clicked();
void on_mRemoveLayerRestrictionButton_clicked();

/*!
* Slots to select/unselect all the WFS layers
Expand Down
192 changes: 185 additions & 7 deletions src/mapserver/qgsprojectparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ QgsProjectParser::QgsProjectParser( QDomDocument* xmlDoc, const QString& filePat
mLegendGroupElements.push_back( groupNodeList.at( i ).toElement() );
}
}

mRestrictedLayers = restrictedLayers();
}
}

Expand Down Expand Up @@ -367,6 +369,10 @@ void QgsProjectParser::addLayers( QDomDocument &doc,
{
layerElem.setAttribute( "queryable", "1" );
QString name = currentChildElem.attribute( "name" );
if ( mRestrictedLayers.contains( name ) ) //unpublished group
{
continue;
}
QDomElement nameElem = doc.createElement( "Name" );
QDomText nameText = doc.createTextNode( name );
nameElem.appendChild( nameText );
Expand Down Expand Up @@ -434,6 +440,10 @@ void QgsProjectParser::addLayers( QDomDocument &doc,
continue;
}

if ( mRestrictedLayers.contains( currentLayer->name() ) ) //unpublished layer
{
continue;
}
if ( nonIdentifiableLayers.contains( currentLayer->id() ) )
{
layerElem.setAttribute( "queryable", "0" );
Expand Down Expand Up @@ -665,6 +675,12 @@ QList<QgsMapLayer*> QgsProjectParser::mapLayerFromStyle( const QString& lName, c
Q_UNUSED( styleName );
QList<QgsMapLayer*> layerList;

//first check if the layer name refers an unpublished layer / group
if ( mRestrictedLayers.contains( lName ) )
{
return layerList;
}

if ( !mXMLDoc )
{
return layerList;
Expand Down Expand Up @@ -1440,18 +1456,19 @@ void QgsProjectParser::printCapabilities( QDomElement& parentElement, QDomDocume
return;
}

QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );
if ( composerNodeList.size() < 1 )
QList<QDomElement> composerElemList = publishedComposerElements();
if ( composerElemList.size() < 1 )
{
return;
}

QDomElement composerTemplatesElem = doc.createElement( "ComposerTemplates" );

for ( int i = 0; i < composerNodeList.size(); ++i )
QList<QDomElement>::const_iterator composerElemIt = composerElemList.constBegin();
for ( ; composerElemIt != composerElemList.constEnd(); ++composerElemIt )
{
QDomElement composerTemplateElem = doc.createElement( "ComposerTemplate" );
QDomElement currentComposerElem = composerNodeList.at( i ).toElement();
QDomElement currentComposerElem = *composerElemIt;
if ( currentComposerElem.isNull() )
{
continue;
Expand Down Expand Up @@ -1515,10 +1532,11 @@ QDomElement QgsProjectParser::composerByName( const QString& composerName ) cons
return composerElem;
}

QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );
for ( int i = 0; i < composerNodeList.size(); ++i )
QList<QDomElement> composerElemList = publishedComposerElements();
QList<QDomElement>::const_iterator composerIt = composerElemList.constBegin();
for ( ; composerIt != composerElemList.constEnd(); ++composerIt )
{
QDomElement currentComposerElem = composerNodeList.at( i ).toElement();
QDomElement currentComposerElem = *composerIt;
if ( currentComposerElem.attribute( "title" ) == composerName )
{
return currentComposerElem;
Expand All @@ -1528,6 +1546,50 @@ QDomElement QgsProjectParser::composerByName( const QString& composerName ) cons
return composerElem;
}

QList<QDomElement> QgsProjectParser::publishedComposerElements() const
{
QList<QDomElement> composerElemList;
if ( !mXMLDoc )
{
return composerElemList;
}

QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );

QDomElement propertiesElem = mXMLDoc->documentElement().firstChildElement( "properties" );
QDomElement wmsComposerListElem = propertiesElem.firstChildElement( "WMSComposerList" );
if ( wmsComposerListElem.isNull() )
{
for ( unsigned int i = 0; i < composerNodeList.length(); ++i )
{
composerElemList.push_back( composerNodeList.at( i ).toElement() );
}
return composerElemList;
}

QSet<QString> publishedComposerNames;
QDomNodeList valueList = wmsComposerListElem.elementsByTagName( "value" );
for ( int i = 0; i < valueList.size(); ++i )
{
publishedComposerNames.insert( valueList.at( i ).toElement().text() );
}

//remove unpublished composers from list
QString currentComposerName;
QDomElement currentElem;
for ( int i = 0; i < composerNodeList.size(); ++i )
{
currentElem = composerNodeList.at( i ).toElement();
currentComposerName = currentElem.attribute( "title" );
if ( publishedComposerNames.contains( currentComposerName ) )
{
composerElemList.push_back( currentElem );
}
}

return composerElemList;
}

void QgsProjectParser::serviceCapabilities( QDomElement& parentElement, QDomDocument& doc ) const
{
QDomElement serviceElem = doc.createElement( "Service" );
Expand Down Expand Up @@ -1971,3 +2033,119 @@ void QgsProjectParser::projectLayerMap( QMap<QString, QgsMapLayer*>& layerMap )
}
}
}

QSet<QString> QgsProjectParser::restrictedLayers() const
{
QSet<QString> restrictedLayerSet;

if ( !mXMLDoc )
{
return restrictedLayerSet;
}

//names of unpublished layers / groups
QDomElement propertiesElem = mXMLDoc->documentElement().firstChildElement( "properties" );
if ( !propertiesElem.isNull() )
{
QDomElement wmsLayerRestrictionElem = propertiesElem.firstChildElement( "WMSRestrictedLayers" );
if ( !wmsLayerRestrictionElem.isNull() )
{
QStringList restrictedLayersAndGroups;
QDomNodeList wmsLayerRestrictionValues = wmsLayerRestrictionElem.elementsByTagName( "value" );
for ( int i = 0; i < wmsLayerRestrictionValues.size(); ++i )
{
restrictedLayerSet.insert( wmsLayerRestrictionValues.at( i ).toElement().text() );
}
}
}

//get legend dom element
if ( restrictedLayerSet.size() < 1 || !mXMLDoc )
{
return restrictedLayerSet;
}

QDomElement legendElem = mXMLDoc->documentElement().firstChildElement( "legend" );
if ( legendElem.isNull() )
{
return restrictedLayerSet;
}

//go through all legend groups and insert names of subgroups / sublayers if there is a match
QDomNodeList legendGroupList = legendElem.elementsByTagName( "legendgroup" );
for ( int i = 0; i < legendGroupList.size(); ++i )
{
//get name
QDomElement groupElem = legendGroupList.at( i ).toElement();
QString groupName = groupElem.attribute( "name" );
if ( restrictedLayerSet.contains( groupName ) ) //match: add names of subgroups and sublayers to set
{
//embedded group? -> also get names of subgroups and sublayers from embedded projects
if ( groupElem.attribute( "embedded" ) == "1" )
{
sublayersOfEmbeddedGroup( convertToAbsolutePath( groupElem.attribute( "project" ) ), groupName, restrictedLayerSet );
}
else //local group
{
QDomNodeList subgroupList = groupElem.elementsByTagName( "legendgroup" );
for ( int j = 0; j < subgroupList.size(); ++j )
{
restrictedLayerSet.insert( subgroupList.at( j ).toElement().attribute( "name" ) );
}
QDomNodeList sublayerList = groupElem.elementsByTagName( "legendlayer" );
for ( int k = 0; k < sublayerList.size(); ++k )
{
restrictedLayerSet.insert( sublayerList.at( k ).toElement().attribute( "name" ) );
}
}
}
}
return restrictedLayerSet;
}

void QgsProjectParser::sublayersOfEmbeddedGroup( const QString& projectFilePath, const QString& groupName, QSet<QString>& layerSet )
{
QFile projectFile( projectFilePath );
if ( !projectFile.open( QIODevice::ReadOnly ) )
{
return;
}

QDomDocument xmlDoc;
if ( !xmlDoc.setContent( &projectFile ) )
{
return;
}

//go to legend node
QDomElement legendElem = xmlDoc.documentElement().firstChildElement( "legend" );
if ( legendElem.isNull() )
{
return;
}

//get group node list of embedded project
QDomNodeList groupNodes = legendElem.elementsByTagName( "legendgroup" );
QDomElement groupElem;
for ( int i = 0; i < groupNodes.size(); ++i )
{
groupElem = groupNodes.at( i ).toElement();
if ( groupElem.attribute( "name" ) == groupName )
{
//get all subgroups and sublayers and add to layerSet
QDomElement subElem;
QDomNodeList subGroupList = groupElem.elementsByTagName( "legendgroup" );
for ( int j = 0; j < subGroupList.size(); ++j )
{
subElem = subGroupList.at( j ).toElement();
layerSet.insert( subElem.attribute( "name" ) );
}
QDomNodeList subLayerList = groupElem.elementsByTagName( "legendlayer" );
for ( int j = 0; j < subLayerList.size(); ++j )
{
subElem = subLayerList.at( j ).toElement();
layerSet.insert( subElem.attribute( "name" ) );
}
}
}
}
10 changes: 10 additions & 0 deletions src/mapserver/qgsprojectparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class QgsProjectParser: public QgsConfigParser
QHash< QString, QDomElement > mProjectLayerElementsById;
/**Project layer elements, accessible by layer name*/
QHash< QString, QDomElement > mProjectLayerElementsByName;
/**Names of layers and groups which should not be published*/
QSet<QString> mRestrictedLayers;

/**Creates a maplayer object from <maplayer> element. The layer cash owns the maplayer, so don't delete it
@return the maplayer or 0 in case of error*/
Expand Down Expand Up @@ -169,6 +171,9 @@ class QgsProjectParser: public QgsConfigParser
/**Returns dom element of composer (identified by composer title) or a null element in case of error*/
QDomElement composerByName( const QString& composerName ) const;

/**Returns the composer elements published by this WMS. It is possible to hide composers from the WMS*/
QList<QDomElement> publishedComposerElements() const;

/**Converts a (possibly relative) path to absolute*/
QString convertToAbsolutePath( const QString& file ) const;

Expand All @@ -188,6 +193,11 @@ class QgsProjectParser: public QgsConfigParser
void projectLayerMap( QMap<QString, QgsMapLayer*>& layerMap ) const;

static QString editTypeString( QgsVectorLayer::EditType type );

/**Returns a complete string set with all the restricted layer names (layers/groups that are not to be published)*/
QSet<QString> restrictedLayers() const;
/**Adds sublayers of an embedded group to layer set*/
static void sublayersOfEmbeddedGroup( const QString& projectFilePath, const QString& groupName, QSet<QString>& layerSet );
};

#endif // QGSPROJECTPARSER_H
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsEmbedLayerDialogBase</class>
<widget class="QDialog" name="QgsEmbedLayerDialogBase">
<class>QgsProjectLayerGroupDialogBase</class>
<widget class="QDialog" name="QgsProjectLayerGroupDialogBase">
<property name="geometry">
<rect>
<x>0</x>
Expand Down
388 changes: 256 additions & 132 deletions src/ui/qgsprojectpropertiesbase.ui

Large diffs are not rendered by default.