Skip to content

Commit

Permalink
Merge pull request #9437 from 3nids/maplayertype_enum
Browse files Browse the repository at this point in the history
 create scope based enum for QgsMapLayer::LayerType >> QgsMapLayerType
  • Loading branch information
3nids authored Mar 26, 2019
2 parents 74e8207 + e232817 commit f000956
Show file tree
Hide file tree
Showing 100 changed files with 384 additions and 332 deletions.
4 changes: 3 additions & 1 deletion cmake_templates/Doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,9 @@ EXPAND_AS_DEFINED = "SIP_ABSTRACT" \
"SIP_TRANSFERTHIS" \
"SIP_VIRTUAL_CATCHER_CODE" \
"SIP_VIRTUALERRORHANDLER" \
"SIP_WHEN_FEATURE"
"SIP_WHEN_FEATURE" \
"SIP_MONKEYPATCH_SCOPEENUM" \
"SIP_MONKEYPATCH_SCOPEENUM_UNNEST"

# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
Expand Down
12 changes: 12 additions & 0 deletions python/core/auto_additions/qgsmaplayer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# The following has been generated automatically from src/core/qgsmaplayer.h
QgsMapLayer.LayerType = QgsMapLayerType
# monkey patching scoped based enum
QgsMapLayer.VectorLayer = QgsMapLayerType.VectorLayer
QgsMapLayer.VectorLayer.__doc__ = ""
QgsMapLayer.RasterLayer = QgsMapLayerType.RasterLayer
QgsMapLayer.RasterLayer.__doc__ = ""
QgsMapLayer.PluginLayer = QgsMapLayerType.PluginLayer
QgsMapLayer.PluginLayer.__doc__ = ""
QgsMapLayer.MeshLayer = QgsMapLayerType.MeshLayer
QgsMapLayer.MeshLayer.__doc__ = "Added in 3.2"
QgsMapLayerType.__doc__ = 'Types of layers that can be added to a map\n\n.. versionadded:: 3.8\n\n' + '* VectorLayer: ' + QgsMapLayerType.VectorLayer.__doc__ + '\n' + '* RasterLayer: ' + QgsMapLayerType.RasterLayer.__doc__ + '\n' + '* PluginLayer: ' + QgsMapLayerType.PluginLayer.__doc__ + '\n' + '* MeshLayer: ' + QgsMapLayerType.MeshLayer.__doc__
# --
QgsMapLayer.LayerFlag.baseClass = QgsMapLayer
QgsMapLayer.LayerFlags.baseClass = QgsMapLayer
LayerFlags = QgsMapLayer # dirty hack since SIP seems to introduce the flags in module
Expand Down
4 changes: 2 additions & 2 deletions python/core/auto_generated/qgsbrowserproxymodel.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Sets whether the model is filtered by map layer type.
.. seealso:: :py:func:`setLayerType`
%End

QgsMapLayer::LayerType layerType() const;
QgsMapLayerType layerType() const;
%Docstring
Returns the layer type to filter the model by. This is only used if
filterByLayerType() is ``True``.
Expand All @@ -123,7 +123,7 @@ filterByLayerType() is ``True``.
.. seealso:: :py:func:`filterByLayerType`
%End

void setLayerType( QgsMapLayer::LayerType type );
void setLayerType( QgsMapLayerType type );
%Docstring
Sets the layer ``type`` to filter the model by. This is only used if
filterByLayerType() is ``True``.
Expand Down
4 changes: 2 additions & 2 deletions python/core/auto_generated/qgsdataitem.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -433,9 +433,9 @@ Item that represents a layer that can be opened with one of the providers



QgsMapLayer::LayerType mapLayerType() const;
QgsMapLayerType mapLayerType() const;
%Docstring
Returns QgsMapLayer.LayerType
Returns :py:class:`QgsMapLayerType`
%End

static LayerType typeFromMapLayer( QgsMapLayer *layer );
Expand Down
31 changes: 16 additions & 15 deletions python/core/auto_generated/qgsmaplayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@




enum class QgsMapLayerType
{
VectorLayer,
RasterLayer,
PluginLayer,
MeshLayer
};

class QgsMapLayer : QObject
{
%Docstring
Expand All @@ -24,24 +33,24 @@ This is the base class for all map layer types (vector, raster).
#include "qgsmaplayer.h"
%End
%ConvertToSubClassCode
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sipCpp );
QgsMapLayer * layer = qobject_cast<QgsMapLayer *>( sipCpp );

sipType = 0;

if ( layer )
{
switch ( layer->type() )
{
case QgsMapLayer::VectorLayer:
case QgsMapLayerType::VectorLayer:
sipType = sipType_QgsVectorLayer;
break;
case QgsMapLayer::RasterLayer:
case QgsMapLayerType::RasterLayer:
sipType = sipType_QgsRasterLayer;
break;
case QgsMapLayer::PluginLayer:
case QgsMapLayerType::PluginLayer:
sipType = sipType_QgsPluginLayer;
break;
case QgsMapLayer::MeshLayer:
case QgsMapLayerType::MeshLayer:
sipType = sipType_QgsMeshLayer;
break;
default:
Expand All @@ -52,14 +61,6 @@ This is the base class for all map layer types (vector, raster).
%End
public:

enum LayerType
{
VectorLayer,
RasterLayer,
PluginLayer,
MeshLayer
};

enum PropertyType
{
Style,
Expand Down Expand Up @@ -95,7 +96,7 @@ This is the base class for all map layer types (vector, raster).
typedef QFlags<QgsMapLayer::StyleCategory> StyleCategories;


QgsMapLayer( QgsMapLayer::LayerType type = VectorLayer, const QString &name = QString(), const QString &source = QString() );
QgsMapLayer( QgsMapLayerType type = QgsMapLayerType::VectorLayer, const QString &name = QString(), const QString &source = QString() );
%Docstring
Constructor for QgsMapLayer

Expand All @@ -117,7 +118,7 @@ is still unique.
.. versionadded:: 3.0
%End

QgsMapLayer::LayerType type() const;
QgsMapLayerType type() const;
%Docstring
Returns the type of the layer.
%End
Expand Down
6 changes: 3 additions & 3 deletions python/gui/auto_additions/qgsadvanceddigitizingdockwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
QgsAdvancedDigitizingDockWidget.CadCapacities.baseClass = QgsAdvancedDigitizingDockWidget
CadCapacities = QgsAdvancedDigitizingDockWidget # dirty hack since SIP seems to introduce the flags in module
# monkey patching scoped based enum
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.NoConstraint.__doc__ = "No additional constraint"
QgsAdvancedDigitizingDockWidget.NoConstraint = QgsAdvancedDigitizingDockWidget.AdditionalConstraint.NoConstraint
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Perpendicular.__doc__ = "Perpendicular"
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.NoConstraint.__doc__ = "No additional constraint"
QgsAdvancedDigitizingDockWidget.Perpendicular = QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Perpendicular
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Parallel.__doc__ = "Parallel"
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Perpendicular.__doc__ = "Perpendicular"
QgsAdvancedDigitizingDockWidget.Parallel = QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Parallel
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Parallel.__doc__ = "Parallel"
QgsAdvancedDigitizingDockWidget.AdditionalConstraint.__doc__ = 'Additional constraints which can be enabled\n\n' + '* NoConstraint: ' + QgsAdvancedDigitizingDockWidget.AdditionalConstraint.NoConstraint.__doc__ + '\n' + '* Perpendicular: ' + QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Perpendicular.__doc__ + '\n' + '* Parallel: ' + QgsAdvancedDigitizingDockWidget.AdditionalConstraint.Parallel.__doc__
# --
2 changes: 1 addition & 1 deletion python/gui/auto_generated/qgisinterface.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Constructor
virtual QgsLayerTreeView *layerTreeView() = 0;

virtual void addCustomActionForLayerType( QAction *action, QString menu,
QgsMapLayer::LayerType type, bool allLayers ) = 0;
QgsMapLayerType type, bool allLayers ) = 0;
%Docstring
Add action to context menu for layers in the layer tree.
If allLayers is ``True``, then the action will be available for all layers of given type,
Expand Down
4 changes: 2 additions & 2 deletions python/gui/auto_generated/qgsdatasourceselectdialog.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ will return a (possibly invalid) QgsMimeDataUtils.Uri.

QgsDataSourceSelectDialog( QgsBrowserModel *browserModel = 0,
bool setFilterByLayerType = false,
const QgsMapLayer::LayerType &layerType = QgsMapLayer::LayerType::VectorLayer,
const QgsMapLayerType &layerType = QgsMapLayerType::VectorLayer,
QWidget *parent = 0 );
%Docstring
Constructs a QgsDataSourceSelectDialog, optionally filtering by layer type
Expand All @@ -47,7 +47,7 @@ Constructs a QgsDataSourceSelectDialog, optionally filtering by layer type

~QgsDataSourceSelectDialog();

void setLayerTypeFilter( QgsMapLayer::LayerType layerType );
void setLayerTypeFilter( QgsMapLayerType layerType );
%Docstring
Sets layer type filter to ``layerType`` and activates the filtering
%End
Expand Down
2 changes: 1 addition & 1 deletion python/gui/auto_generated/qgsmaplayeractionregistry.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Creates a map layer action which can run on any layer
Creates a map layer action which can run only on a specific layer
%End

QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayer::LayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = 0 );
QgsMapLayerAction( const QString &name, QObject *parent /TransferThis/, QgsMapLayerType layerType, Targets targets = AllActions, const QIcon &icon = QIcon(), QgsMapLayerAction::Flags flags = 0 );
%Docstring
Creates a map layer action which can run on a specific type of layer
%End
Expand Down
37 changes: 30 additions & 7 deletions scripts/sipify.pl
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ sub detect_non_method_member{
}

# Skip forward declarations
if ($LINE =~ m/^\s*(class|struct) \w+(?<external> *SIP_EXTERNAL)?;\s*(\/\/.*)?$/){
if ($LINE =~ m/^\s*(enum\s+)?(class|struct) \w+(?<external> *SIP_EXTERNAL)?;\s*(\/\/.*)?$/){
if ($+{external}){
dbg_info('do not skip external forward declaration');
$COMMENT = '';
Expand Down Expand Up @@ -959,10 +959,15 @@ sub detect_non_method_member{
my $is_scope_based = "0";
$is_scope_based = "1" if defined $2;
my $monkeypatch = "0";
$monkeypatch = "1" if defined $is_scope_based eq "1" and $LINE =~ m/SIP_MONKEYPATCH_SCOPEENUM/;
$monkeypatch = "1" if defined $is_scope_based eq "1" and $LINE =~ m/SIP_MONKEYPATCH_SCOPEENUM(_UNNEST)?(:?\(\s*(?<emkb>\w+)\s*,\s*(?<emkf>\w+)\s*\))?/;
my $enum_mk_base = "";
$enum_mk_base = $+{emkb} if defined $+{emkb};
if (defined $+{emkf} and $monkeypatch eq "1"){
push @OUTPUT_PYTHON, "$enum_mk_base.$+{emkf} = $enum_qualname\n";
}
if ($LINE =~ m/\{((\s*\w+)(\s*=\s*[\w\s\d<|]+.*?)?(,?))+\s*\}/){
# one line declaration
$LINE !~ m/=/ or exit_with_error("spify.pl does not handle enum one liners with value assignment. Use multiple lines instead.");
$LINE !~ m/=/ or exit_with_error("Sipify does not handle enum one liners with value assignment. Use multiple lines instead. Or jusr write a new parser.");
next;
}
else
Expand All @@ -983,17 +988,35 @@ sub detect_non_method_member{
do {no warnings 'uninitialized';
my $enum_decl = $LINE =~ s/^(\s*(?<em>\w+))(\s+SIP_\w+(?:\([^()]+\))?)?(?:\s*=\s*(?:[\w\s\d|+-]|::|<<)+)?(,?)(:?\s*\/\/!<\s*(?<co>.*)|.*)$/$1$3$4/r;
my $enum_member = $+{em};
push @enum_members_doc, "'* $enum_member: ' + $ACTUAL_CLASS.$enum_qualname.$2.__doc__";
my $comment = $+{co};
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_qualname.$enum_member.__doc__ = \"$comment\"\n" if $is_scope_based eq "1";
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_member = $ACTUAL_CLASS.$enum_qualname.$enum_member\n" if $monkeypatch eq "1";
dbg_info("is_scope_based:$is_scope_based enum_mk_base:$enum_mk_base monkeypatch:$monkeypatch");
if ($is_scope_based eq "1") {
if ( $monkeypatch eq 1 ){
if ($enum_mk_base ne "") {
push @OUTPUT_PYTHON, "$enum_mk_base.$enum_member = $enum_qualname.$enum_member\n";
push @OUTPUT_PYTHON, "$enum_mk_base.$enum_member.__doc__ = \"$comment\"\n" ;
push @enum_members_doc, "'* $enum_member: ' + $enum_qualname.$enum_member.__doc__";
} else {
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_member = $ACTUAL_CLASS.$enum_qualname.$enum_member\n";
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_qualname.$enum_member.__doc__ = \"$comment\"\n";
push @enum_members_doc, "'* $enum_member: ' + $ACTUAL_CLASS.$enum_qualname.$enum_member.__doc__";
}
}
}
$enum_decl = fix_annotations($enum_decl);
write_output("ENU3", "$enum_decl\n");
};
detect_comment_block(strict_mode => UNSTRICT);
}
write_output("ENU4", "$LINE\n");
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_qualname.__doc__ = '$COMMENT\\n\\n' + " . join(" + '\\n' + ", @enum_members_doc) . "\n# --\n" if $is_scope_based eq "1";
if ($is_scope_based eq "1") {
$COMMENT =~ s/\n/\\n/g;
if ( $ACTUAL_CLASS ne "" ){
push @OUTPUT_PYTHON, "$ACTUAL_CLASS.$enum_qualname.__doc__ = '$COMMENT\\n\\n' + " . join(" + '\\n' + ", @enum_members_doc) . "\n# --\n";
} else {
push @OUTPUT_PYTHON, "$enum_qualname.__doc__ = '$COMMENT\\n\\n' + " . join(" + '\\n' + ", @enum_members_doc) . "\n# --\n";
}
}
# enums don't have Docstring apparently
$COMMENT = '';
next;
Expand Down
10 changes: 5 additions & 5 deletions src/3d/qgs3dmapscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,15 +545,15 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )
// This is a bit of a hack and it should be handled in QgsMapLayer::setRenderer3D() but in qgis_core
// the vector layer 3D renderer class is not available. Maybe we need an intermediate map layer 3D renderer
// class in qgis_core that can be used to handle this case nicely.
if ( layer->type() == QgsMapLayer::VectorLayer && renderer->type() == QLatin1String( "vector" ) )
if ( layer->type() == QgsMapLayerType::VectorLayer && renderer->type() == QLatin1String( "vector" ) )
{
static_cast<QgsVectorLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsVectorLayer *>( layer ) );
}
else if ( layer->type() == QgsMapLayer::VectorLayer && renderer->type() == QLatin1String( "rulebased" ) )
else if ( layer->type() == QgsMapLayerType::VectorLayer && renderer->type() == QLatin1String( "rulebased" ) )
{
static_cast<QgsRuleBased3DRenderer *>( renderer )->setLayer( static_cast<QgsVectorLayer *>( layer ) );
}
else if ( layer->type() == QgsMapLayer::MeshLayer && renderer->type() == QLatin1String( "mesh" ) )
else if ( layer->type() == QgsMapLayerType::MeshLayer && renderer->type() == QLatin1String( "mesh" ) )
{
static_cast<QgsMeshLayer3DRenderer *>( renderer )->setLayer( static_cast<QgsMeshLayer *>( layer ) );
}
Expand All @@ -575,7 +575,7 @@ void Qgs3DMapScene::addLayerEntity( QgsMapLayer *layer )

connect( layer, &QgsMapLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );

if ( layer->type() == QgsMapLayer::VectorLayer )
if ( layer->type() == QgsMapLayerType::VectorLayer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
connect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
Expand All @@ -590,7 +590,7 @@ void Qgs3DMapScene::removeLayerEntity( QgsMapLayer *layer )

disconnect( layer, &QgsMapLayer::renderer3DChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );

if ( layer->type() == QgsMapLayer::VectorLayer )
if ( layer->type() == QgsMapLayerType::VectorLayer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
disconnect( vlayer, &QgsVectorLayer::selectionChanged, this, &Qgs3DMapScene::onLayerRenderer3DChanged );
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmmergevector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ QVariantMap QgsMergeVectorAlgorithm::processAlgorithm( const QVariantMap &parame
continue;
}

if ( layer->type() != QgsMapLayer::VectorLayer )
if ( layer->type() != QgsMapLayerType::VectorLayer )
throw QgsProcessingException( QObject::tr( "All layers must be vector layers!" ) );

QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer );
Expand Down
8 changes: 4 additions & 4 deletions src/analysis/processing/qgsalgorithmpackage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters

switch ( layer->type() )
{
case QgsMapLayer::VectorLayer:
case QgsMapLayerType::VectorLayer:
{
if ( !packageVectorLayer( qobject_cast< QgsVectorLayer * >( layer ), packagePath,
context, &multiStepFeedback ) )
Expand All @@ -130,21 +130,21 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters
break;
}

case QgsMapLayer::RasterLayer:
case QgsMapLayerType::RasterLayer:
{
//not supported
feedback->pushDebugInfo( QObject::tr( "Raster layers are not currently supported." ) );
errored = true;
break;
}

case QgsMapLayer::PluginLayer:
case QgsMapLayerType::PluginLayer:
//not supported
feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
errored = true;
break;

case QgsMapLayer::MeshLayer:
case QgsMapLayerType::MeshLayer:
//not supported
feedback->pushDebugInfo( QObject::tr( "Packaging mesh layers is not supported." ) );
errored = true;
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmrasterlogicalop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ bool QgsRasterBooleanLogicAlgorithmBase::prepareAlgorithm( const QVariantMap &pa
rasterLayers.reserve( layers.count() );
for ( QgsMapLayer *l : layers )
{
if ( l->type() == QgsMapLayer::RasterLayer )
if ( l->type() == QgsMapLayerType::RasterLayer )
{
QgsRasterLayer *layer = qobject_cast< QgsRasterLayer * >( l );
QgsRasterAnalysisUtils::RasterLogicInput input;
Expand Down
12 changes: 6 additions & 6 deletions src/app/browser/qgsinbuiltdataitemproviders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,8 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
return;

QgsLayerItem *layerItem = qobject_cast<QgsLayerItem *>( item );
if ( layerItem && ( layerItem->mapLayerType() == QgsMapLayer::VectorLayer ||
layerItem->mapLayerType() == QgsMapLayer::RasterLayer ) )
if ( layerItem && ( layerItem->mapLayerType() == QgsMapLayerType::VectorLayer ||
layerItem->mapLayerType() == QgsMapLayerType::RasterLayer ) )
{
QMenu *exportMenu = new QMenu( tr( "Export Layer" ), menu );
menu->addMenu( exportMenu );
Expand All @@ -361,7 +361,7 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
{
switch ( layerItem->mapLayerType() )
{
case QgsMapLayer::VectorLayer:
case QgsMapLayerType::VectorLayer:
{
std::unique_ptr<QgsVectorLayer> layer( new QgsVectorLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() ) );
if ( layer && layer->isValid() )
Expand All @@ -371,7 +371,7 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
break;
}

case QgsMapLayer::RasterLayer:
case QgsMapLayerType::RasterLayer:
{
std::unique_ptr<QgsRasterLayer> layer( new QgsRasterLayer( layerItem->uri(), layerItem->name(), layerItem->providerKey() ) );
if ( layer && layer->isValid() )
Expand All @@ -381,8 +381,8 @@ void QgsLayerItemGuiProvider::populateContextMenu( QgsDataItem *item, QMenu *men
break;
}

case QgsMapLayer::PluginLayer:
case QgsMapLayer::MeshLayer:
case QgsMapLayerType::PluginLayer:
case QgsMapLayerType::MeshLayer:
break;
}
} );
Expand Down
2 changes: 1 addition & 1 deletion src/app/decorations/qgsdecorationgrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@ bool QgsDecorationGrid::getIntervalFromCurrentLayer( double *values )
QMessageBox::warning( nullptr, tr( "Get Interval from Layer" ), tr( "No active layer" ) );
return false;
}
if ( layer->type() != QgsMapLayer::RasterLayer )
if ( layer->type() != QgsMapLayerType::RasterLayer )
{
QMessageBox::warning( nullptr, tr( "Get Interval from Layer" ), tr( "Please select a raster layer." ) );
return false;
Expand Down
Loading

0 comments on commit f000956

Please sign in to comment.