Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project validator #1

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions python/core/auto_generated/qgsprojectservervalidator.sip.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsprojectservervalidator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/





class QgsProjectServerValidator
{
%Docstring
Project server validator.

.. versionadded:: 3.14
%End

%TypeHeaderCode
#include "qgsprojectservervalidator.h"
%End
public:

QgsProjectServerValidator();
%Docstring
Constructor for QgsProjectServerValidator.
%End

enum ValidationError
{
DuplicatedNames,
ShortNames,
Encoding
};

static QString displayValidationError( QgsProjectServerValidator::ValidationError error );

struct ValidationResult
{

ValidationResult( const QgsProjectServerValidator::ValidationError error, const QVariant &identifier );
%Docstring
Constructor for ValidationResult.
%End

QgsProjectServerValidator::ValidationError error;

QVariant identifier;
};

bool validate( QgsLayerTree *layerTree, QList< QgsProjectServerValidator::ValidationResult > &results /Out/ ) const;
%Docstring
Validates a layer tree to avoid some problems on QGIS Server, and returns ``True`` if it's considered valid.
If validation fails, the ``results`` list will be filled with a list of
items describing why the validation failed and what needs to be rectified

:param layerTree: input layer tree

:return: - bool
- results: results of the validation
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsprojectservervalidator.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
%Include auto_generated/qgsprojectdisplaysettings.sip
%Include auto_generated/qgsprojectfiletransform.sip
%Include auto_generated/qgsprojectproperty.sip
%Include auto_generated/qgsprojectservervalidator.sip
%Include auto_generated/qgsprojectstorage.sip
%Include auto_generated/qgsprojectstorageregistry.sip
%Include auto_generated/qgsprojecttimesettings.sip
Expand Down
102 changes: 17 additions & 85 deletions src/app/qgsprojectproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include "qgsmessagelog.h"
#include "qgslayercapabilitiesmodel.h"
#include "qgsexpressioncontextutils.h"
#include "qgsprojectservervalidator.h"
#include "qgsprojectstorage.h"
#include "qgsprojectstorageregistry.h"
#include "qgsprojectviewsettings.h"
Expand Down Expand Up @@ -1905,60 +1906,29 @@ void QgsProjectProperties::pbnWCSLayersDeselectAll_clicked()

void QgsProjectProperties::pbnLaunchOWSChecker_clicked()
{
QString myStyle = QgsApplication::reportStyleSheet();
teOWSChecker->clear();
teOWSChecker->document()->setDefaultStyleSheet( myStyle );
teOWSChecker->setHtml( "<h1>" + tr( "Start checking QGIS Server" ) + "</h1>" );

QStringList owsNames, encodingMessages;
checkOWS( QgisApp::instance()->layerTreeView()->layerTreeModel()->rootGroup(), owsNames, encodingMessages );

QStringList duplicateNames, regExpMessages;
QRegExp snRegExp = QgsApplication::shortNameRegExp();
const auto constOwsNames = owsNames;
for ( const QString &name : constOwsNames )
{
if ( !snRegExp.exactMatch( name ) )
regExpMessages << tr( "Use short name for \"%1\"" ).arg( name );
if ( duplicateNames.contains( name ) )
continue;
if ( owsNames.count( name ) > 1 )
duplicateNames << name;
}
QList<QgsProjectServerValidator::ValidationResult> validationResults;
QgsProjectServerValidator validator;
bool results = validator.validate( QgsProject::instance()->layerTreeRoot(), validationResults );

if ( !duplicateNames.empty() )
{
QString nameMessage = "<h1>" + tr( "Some layers and groups have the same name or short name" ) + "</h1>";
nameMessage += "<h2>" + tr( "Duplicate names:" ) + "</h2>";
nameMessage += duplicateNames.join( QStringLiteral( "</li><li>" ) ) + "</li></ul>";
teOWSChecker->setHtml( teOWSChecker->toHtml() + nameMessage );
}
else
QString errors;
if ( !results )
{
teOWSChecker->setHtml( teOWSChecker->toHtml() + "<h1>" + tr( "All names and short names of layer and group are unique" ) + "</h1>" );
}

if ( !regExpMessages.empty() )
{
QString encodingMessage = "<h1>" + tr( "Some layer short names have to be updated:" ) + "</h1><ul><li>" + regExpMessages.join( QStringLiteral( "</li><li>" ) ) + "</li></ul>";
teOWSChecker->setHtml( teOWSChecker->toHtml() + encodingMessage );
}
else
{
teOWSChecker->setHtml( teOWSChecker->toHtml() + "<h1>" + tr( "All layer short names are well formed" ) + "</h1>" );
}

if ( !encodingMessages.empty() )
{
QString encodingMessage = "<h1>" + tr( "Some layer encodings are not set:" ) + "</h1><ul><li>" + encodingMessages.join( QStringLiteral( "</li><li>" ) ) + "</li></ul>";
teOWSChecker->setHtml( teOWSChecker->toHtml() + encodingMessage );
for ( const QgsProjectServerValidator::ValidationResult &result : qgis::as_const( validationResults ) )
{
errors += QLatin1String( "<b>" ) % QgsProjectServerValidator::displayValidationError( result.error ) % QLatin1String( " :</b> " );
errors += result.identifier.toString();
}
}
else
{
teOWSChecker->setHtml( teOWSChecker->toHtml() + "<h1>" + tr( "All layer encodings are set" ) + "</h1>" );
errors = QString( tr( "Ok, it seems valid." ) );
}

teOWSChecker->setHtml( teOWSChecker->toHtml() + "<h1>" + tr( "Start checking QGIS Server" ) + "</h1>" );
QString myStyle = QgsApplication::reportStyleSheet();
myStyle.append( QStringLiteral( "body { margin: 10px; }\n " ) );
teOWSChecker->clear();
teOWSChecker->document()->setDefaultStyleSheet( myStyle );
teOWSChecker->setHtml( errors );
}

void QgsProjectProperties::pbnAddScale_clicked()
Expand Down Expand Up @@ -2321,44 +2291,6 @@ void QgsProjectProperties::addWmtsGrid( const QString &crsStr )
twWmtsGrids->blockSignals( false );
}

void QgsProjectProperties::checkOWS( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages )
{
QList< QgsLayerTreeNode * > treeGroupChildren = treeGroup->children();
for ( int i = 0; i < treeGroupChildren.size(); ++i )
{
QgsLayerTreeNode *treeNode = treeGroupChildren.at( i );
if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
{
QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode );
QString shortName = treeGroupChild->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
if ( shortName.isEmpty() )
owsNames << treeGroupChild->name();
else
owsNames << shortName;
checkOWS( treeGroupChild, owsNames, encodingMessages );
}
else
{
QgsLayerTreeLayer *treeLayer = static_cast<QgsLayerTreeLayer *>( treeNode );
QgsMapLayer *l = treeLayer->layer();
if ( l )
{
QString shortName = l->shortName();
if ( shortName.isEmpty() )
owsNames << l->name();
else
owsNames << shortName;
if ( l->type() == QgsMapLayerType::VectorLayer )
{
QgsVectorLayer *vl = static_cast<QgsVectorLayer *>( l );
if ( vl->dataProvider()->encoding() == QLatin1String( "System" ) )
encodingMessages << tr( "Update layer \"%1\" encoding" ).arg( l->name() );
}
}
}
}
}

void QgsProjectProperties::populateEllipsoidList()
{
//
Expand Down
2 changes: 0 additions & 2 deletions src/app/qgsprojectproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,6 @@ class APP_EXPORT QgsProjectProperties : public QgsOptionsDialogBase, private Ui:
void populateWmtsTree( const QgsLayerTreeGroup *treeGroup, QgsTreeWidgetItem *treeItem );
//! add WMTS Grid definition based on CRS
void addWmtsGrid( const QString &crsStr );
//! Check OWS configuration
void checkOWS( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages );

//! Populates list with ellipsoids from Sqlite3 db
void populateEllipsoidList();
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ SET(QGIS_CORE_SRCS
qgssnappingconfig.cpp
qgsprojectdisplaysettings.cpp
qgsprojectproperty.cpp
qgsprojectservervalidator.cpp
qgsprojectstorage.cpp
qgsprojectstorageregistry.cpp
qgsprojecttimesettings.cpp
Expand Down Expand Up @@ -868,6 +869,7 @@ SET(QGIS_CORE_HDRS
qgsprojectdisplaysettings.h
qgsprojectfiletransform.h
qgsprojectproperty.h
qgsprojectservervalidator.h
qgsprojectstorage.h
qgsprojectstorageregistry.h
qgsprojecttimesettings.h
Expand Down
129 changes: 129 additions & 0 deletions src/core/qgsprojectservervalidator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/***************************************************************************
qgsprojectservervalidator.cpp
---------------------------
begin : March 2020
copyright : (C) 2020 by Etienne Trimaille
email : etienne dot trimaille at gmail 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 "qgsapplication.h"
#include "qgslayertreelayer.h"
#include "qgsprojectservervalidator.h"
#include "qgsvectorlayer.h"


QString QgsProjectServerValidator::displayValidationError( QgsProjectServerValidator::ValidationError error )
{
switch ( error )
{
case QgsProjectServerValidator::Encoding:
return QObject::tr( "Encoding is not set properly. It shouldn't be 'System'" );
case QgsProjectServerValidator::ShortNames:
return QObject::tr( "Layer short name needs to be updated" );
case QgsProjectServerValidator::DuplicatedNames:
return QObject::tr( "Layers/groups have the same name or short name" );
}
return QString();
}

void QgsProjectServerValidator::browseLayerTree( QgsLayerTreeGroup *treeGroup, QStringList &owsNames, QStringList &encodingMessages )
{
QList< QgsLayerTreeNode * > treeGroupChildren = treeGroup->children();
for ( int i = 0; i < treeGroupChildren.size(); ++i )
{
QgsLayerTreeNode *treeNode = treeGroupChildren.at( i );
if ( treeNode->nodeType() == QgsLayerTreeNode::NodeGroup )
{
QgsLayerTreeGroup *treeGroupChild = static_cast<QgsLayerTreeGroup *>( treeNode );
QString shortName = treeGroupChild->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
if ( shortName.isEmpty() )
owsNames << treeGroupChild->name();
else
owsNames << shortName;
browseLayerTree( treeGroupChild, owsNames, encodingMessages );
}
else
{
QgsLayerTreeLayer *treeLayer = static_cast<QgsLayerTreeLayer *>( treeNode );
QgsMapLayer *layer = treeLayer->layer();
if ( layer )
{
QString shortName = layer->shortName();
if ( shortName.isEmpty() )
owsNames << layer->name();
else
owsNames << shortName;

if ( layer->type() == QgsMapLayerType::VectorLayer )
{
QgsVectorLayer *vl = static_cast<QgsVectorLayer *>( layer );
if ( vl->dataProvider()->encoding() == QLatin1String( "System" ) )
encodingMessages << layer->name();
}
}
}
}
}

bool QgsProjectServerValidator::validate( QgsLayerTree *layerTree, QList<QgsProjectServerValidator::ValidationResult> &results ) const
{
results.clear();
bool result = true;

if ( !layerTree )
return false;

QStringList owsNames, encodingMessages;
browseLayerTree( layerTree, owsNames, encodingMessages );

QStringList duplicateNames, regExpMessages;
QRegExp snRegExp = QgsApplication::shortNameRegExp();
const auto constOwsNames = owsNames;
for ( const QString &name : constOwsNames )
{
if ( !snRegExp.exactMatch( name ) )
{
regExpMessages << name;
}

if ( duplicateNames.contains( name ) )
{
continue;
}

if ( owsNames.count( name ) > 1 )
{
duplicateNames << name;
}
}

if ( !duplicateNames.empty() )
{
result = false;
results << ValidationResult( QgsProjectServerValidator::DuplicatedNames, duplicateNames.join( QStringLiteral( ", " ) ) );
}

if ( !regExpMessages.empty() )
{
result = false;
results << ValidationResult( QgsProjectServerValidator::ShortNames, regExpMessages.join( QStringLiteral( ", " ) ) );
}

if ( !encodingMessages.empty() )
{
result = false;
results << ValidationResult( QgsProjectServerValidator::Encoding, encodingMessages.join( QStringLiteral( ", " ) ) );
}

return result;
}
Loading