mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-19 00:04:52 -04:00
Add size assistant to simple and svg marker data defined sizes
This commit is contained in:
parent
de3377bca9
commit
a80c3496ac
@ -7,5 +7,9 @@ class QgsSizeScaleWidget : QgsDataDefinedAssistant
|
|||||||
QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol );
|
QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol );
|
||||||
|
|
||||||
QgsDataDefined dataDefined() const;
|
QgsDataDefined dataDefined() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void showEvent( QShowEvent * );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +47,36 @@ class ItemDelegate : public QItemDelegate
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void QgsSizeScaleWidget::setFromSymbol()
|
||||||
|
{
|
||||||
|
if ( !mSymbol )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsDataDefined ddSize = mSymbol->dataDefinedSize();
|
||||||
|
QgsScaleExpression expr( ddSize.expressionString() );
|
||||||
|
if ( expr )
|
||||||
|
{
|
||||||
|
for ( int i = 0; i < scaleMethodComboBox->count(); i++ )
|
||||||
|
{
|
||||||
|
if ( scaleMethodComboBox->itemData( i ).toInt() == int( expr.type() ) )
|
||||||
|
{
|
||||||
|
scaleMethodComboBox->setCurrentIndex( i );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mExpressionWidget->setField( expr.baseExpression() );
|
||||||
|
|
||||||
|
minValueSpinBox->setValue( expr.minValue() );
|
||||||
|
maxValueSpinBox->setValue( expr.maxValue() );
|
||||||
|
minSizeSpinBox->setValue( expr.minSize() );
|
||||||
|
maxSizeSpinBox->setValue( expr.maxSize() );
|
||||||
|
}
|
||||||
|
updatePreview();
|
||||||
|
}
|
||||||
|
|
||||||
QgsSizeScaleWidget::QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol )
|
QgsSizeScaleWidget::QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol )
|
||||||
: mSymbol( symbol )
|
: mSymbol( symbol )
|
||||||
// we just use the minimumValue and maximumValue from the layer, unfortunately they are
|
// we just use the minimumValue and maximumValue from the layer, unfortunately they are
|
||||||
@ -85,27 +115,7 @@ QgsSizeScaleWidget::QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsM
|
|||||||
maxValueSpinBox->setShowClearButton( false );
|
maxValueSpinBox->setShowClearButton( false );
|
||||||
|
|
||||||
// setup ui from expression if any
|
// setup ui from expression if any
|
||||||
QgsDataDefined ddSize = mSymbol->dataDefinedSize();
|
setFromSymbol();
|
||||||
QgsScaleExpression expr( ddSize.expressionString() );
|
|
||||||
if ( expr )
|
|
||||||
{
|
|
||||||
for ( int i = 0; i < scaleMethodComboBox->count(); i++ )
|
|
||||||
{
|
|
||||||
if ( scaleMethodComboBox->itemData( i ).toInt() == int( expr.type() ) )
|
|
||||||
{
|
|
||||||
scaleMethodComboBox->setCurrentIndex( i );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mExpressionWidget->setField( expr.baseExpression() );
|
|
||||||
|
|
||||||
minValueSpinBox->setValue( expr.minValue() );
|
|
||||||
maxValueSpinBox->setValue( expr.maxValue() );
|
|
||||||
minSizeSpinBox->setValue( expr.minSize() );
|
|
||||||
maxSizeSpinBox->setValue( expr.maxSize() );
|
|
||||||
updatePreview();
|
|
||||||
}
|
|
||||||
|
|
||||||
connect( minSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
|
connect( minSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
|
||||||
connect( maxSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
|
connect( maxSizeSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( updatePreview() ) );
|
||||||
@ -122,6 +132,11 @@ QgsDataDefined QgsSizeScaleWidget::dataDefined() const
|
|||||||
return QgsDataDefined( exp.data() );
|
return QgsDataDefined( exp.data() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsSizeScaleWidget::showEvent( QShowEvent* )
|
||||||
|
{
|
||||||
|
setFromSymbol();
|
||||||
|
}
|
||||||
|
|
||||||
QgsScaleExpression *QgsSizeScaleWidget::createExpression() const
|
QgsScaleExpression *QgsSizeScaleWidget::createExpression() const
|
||||||
{
|
{
|
||||||
return new QgsScaleExpression( QgsScaleExpression::Type( scaleMethodComboBox->itemData( scaleMethodComboBox->currentIndex() ).toInt() ),
|
return new QgsScaleExpression( QgsScaleExpression::Type( scaleMethodComboBox->itemData( scaleMethodComboBox->currentIndex() ).toInt() ),
|
||||||
@ -134,6 +149,9 @@ QgsScaleExpression *QgsSizeScaleWidget::createExpression() const
|
|||||||
|
|
||||||
void QgsSizeScaleWidget::updatePreview()
|
void QgsSizeScaleWidget::updatePreview()
|
||||||
{
|
{
|
||||||
|
if ( !mSymbol )
|
||||||
|
return;
|
||||||
|
|
||||||
QScopedPointer<QgsScaleExpression> expr( createExpression() );
|
QScopedPointer<QgsScaleExpression> expr( createExpression() );
|
||||||
QList<double> breaks = QgsSymbolLayerV2Utils::prettyBreaks( expr->minValue(), expr->maxValue(), 4 );
|
QList<double> breaks = QgsSymbolLayerV2Utils::prettyBreaks( expr->minValue(), expr->maxValue(), 4 );
|
||||||
|
|
||||||
|
@ -38,6 +38,10 @@ class GUI_EXPORT QgsSizeScaleWidget : public QgsDataDefinedAssistant, private Ui
|
|||||||
|
|
||||||
QgsDataDefined dataDefined() const override;
|
QgsDataDefined dataDefined() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void showEvent( QShowEvent * ) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void computeFromLayerTriggered();
|
void computeFromLayerTriggered();
|
||||||
void updatePreview();
|
void updatePreview();
|
||||||
@ -51,6 +55,8 @@ class GUI_EXPORT QgsSizeScaleWidget : public QgsDataDefinedAssistant, private Ui
|
|||||||
QStandardItemModel mPreviewList;
|
QStandardItemModel mPreviewList;
|
||||||
|
|
||||||
QgsScaleExpression* createExpression() const;
|
QgsScaleExpression* createExpression() const;
|
||||||
|
void setFromSymbol();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //QGSSIZESCALEWIDGET_H
|
#endif //QGSSIZESCALEWIDGET_H
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
|
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
|
#include "qgssizescalewidget.h"
|
||||||
|
|
||||||
#include <QAbstractButton>
|
#include <QAbstractButton>
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
@ -334,6 +335,11 @@ QgsSimpleMarkerSymbolLayerV2Widget::QgsSimpleMarkerSymbolLayerV2Widget( const Qg
|
|||||||
spinOffsetX->setClearValue( 0.0 );
|
spinOffsetX->setClearValue( 0.0 );
|
||||||
spinOffsetY->setClearValue( 0.0 );
|
spinOffsetY->setClearValue( 0.0 );
|
||||||
|
|
||||||
|
//make a temporary symbol for the size assistant preview
|
||||||
|
mAssistantPreviewSymbol = new QgsMarkerSymbolV2();
|
||||||
|
|
||||||
|
mSizeDDBtn->setAssistant( new QgsSizeScaleWidget( mVectorLayer, mAssistantPreviewSymbol ) );
|
||||||
|
|
||||||
QSize size = lstNames->iconSize();
|
QSize size = lstNames->iconSize();
|
||||||
QStringList names;
|
QStringList names;
|
||||||
names << "circle" << "rectangle" << "diamond" << "pentagon" << "cross" << "cross2" << "triangle"
|
names << "circle" << "rectangle" << "diamond" << "pentagon" << "cross" << "cross2" << "triangle"
|
||||||
@ -355,6 +361,12 @@ QgsSimpleMarkerSymbolLayerV2Widget::QgsSimpleMarkerSymbolLayerV2Widget( const Qg
|
|||||||
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) );
|
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) );
|
||||||
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
||||||
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
||||||
|
connect( this, SIGNAL( changed() ), this, SLOT( updateAssistantSymbol() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsSimpleMarkerSymbolLayerV2Widget::~QgsSimpleMarkerSymbolLayerV2Widget()
|
||||||
|
{
|
||||||
|
delete mAssistantPreviewSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
||||||
@ -437,6 +449,8 @@ void QgsSimpleMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer
|
|||||||
registerDataDefinedButton( mOffsetDDBtn, "offset", QgsDataDefinedButton::String, QgsDataDefinedButton::doubleXYDesc() );
|
registerDataDefinedButton( mOffsetDDBtn, "offset", QgsDataDefinedButton::String, QgsDataDefinedButton::doubleXYDesc() );
|
||||||
registerDataDefinedButton( mHorizontalAnchorDDBtn, "horizontal_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::horizontalAnchorDesc() );
|
registerDataDefinedButton( mHorizontalAnchorDDBtn, "horizontal_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::horizontalAnchorDesc() );
|
||||||
registerDataDefinedButton( mVerticalAnchorDDBtn, "vertical_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::verticalAnchorDesc() );
|
registerDataDefinedButton( mVerticalAnchorDDBtn, "vertical_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::verticalAnchorDesc() );
|
||||||
|
|
||||||
|
updateAssistantSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2Widget::symbolLayer()
|
QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2Widget::symbolLayer()
|
||||||
@ -548,6 +562,18 @@ void QgsSimpleMarkerSymbolLayerV2Widget::on_mVerticalAnchorComboBox_currentIndex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsSimpleMarkerSymbolLayerV2Widget::updateAssistantSymbol()
|
||||||
|
{
|
||||||
|
for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
|
||||||
|
{
|
||||||
|
mAssistantPreviewSymbol->deleteSymbolLayer( i );
|
||||||
|
}
|
||||||
|
mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
|
||||||
|
QgsDataDefined* ddSize = mLayer->getDataDefinedProperty( "size" );
|
||||||
|
if ( ddSize )
|
||||||
|
mAssistantPreviewSymbol->setDataDefinedSize( *ddSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
|
|
||||||
@ -1508,6 +1534,16 @@ QgsSvgMarkerSymbolLayerV2Widget::QgsSvgMarkerSymbolLayerV2Widget( const QgsVecto
|
|||||||
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) );
|
connect( spinAngle, SIGNAL( valueChanged( double ) ), this, SLOT( setAngle() ) );
|
||||||
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
connect( spinOffsetX, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
||||||
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
connect( spinOffsetY, SIGNAL( valueChanged( double ) ), this, SLOT( setOffset() ) );
|
||||||
|
connect( this, SIGNAL( changed() ), this, SLOT( updateAssistantSymbol() ) );
|
||||||
|
|
||||||
|
//make a temporary symbol for the size assistant preview
|
||||||
|
mAssistantPreviewSymbol = new QgsMarkerSymbolV2();
|
||||||
|
mSizeDDBtn->setAssistant( new QgsSizeScaleWidget( mVectorLayer, mAssistantPreviewSymbol ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsSvgMarkerSymbolLayerV2Widget::~QgsSvgMarkerSymbolLayerV2Widget()
|
||||||
|
{
|
||||||
|
delete mAssistantPreviewSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QTime>
|
#include <QTime>
|
||||||
@ -1698,6 +1734,18 @@ void QgsSvgMarkerSymbolLayerV2Widget::setGuiForSvg( const QgsSvgMarkerSymbolLaye
|
|||||||
mBorderWidthSpinBox->blockSignals( false );
|
mBorderWidthSpinBox->blockSignals( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsSvgMarkerSymbolLayerV2Widget::updateAssistantSymbol()
|
||||||
|
{
|
||||||
|
for ( int i = mAssistantPreviewSymbol->symbolLayerCount() - 1 ; i >= 0; --i )
|
||||||
|
{
|
||||||
|
mAssistantPreviewSymbol->deleteSymbolLayer( i );
|
||||||
|
}
|
||||||
|
mAssistantPreviewSymbol->appendSymbolLayer( mLayer->clone() );
|
||||||
|
QgsDataDefined* ddSize = mLayer->getDataDefinedProperty( "size" );
|
||||||
|
if ( ddSize )
|
||||||
|
mAssistantPreviewSymbol->setDataDefinedSize( *ddSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsSvgMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
void QgsSvgMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
||||||
{
|
{
|
||||||
@ -1775,6 +1823,8 @@ void QgsSvgMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
|||||||
registerDataDefinedButton( mBorderColorDDBtn, "outline", QgsDataDefinedButton::String, QgsDataDefinedButton::colorNoAlphaDesc() );
|
registerDataDefinedButton( mBorderColorDDBtn, "outline", QgsDataDefinedButton::String, QgsDataDefinedButton::colorNoAlphaDesc() );
|
||||||
registerDataDefinedButton( mHorizontalAnchorDDBtn, "horizontal_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::horizontalAnchorDesc() );
|
registerDataDefinedButton( mHorizontalAnchorDDBtn, "horizontal_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::horizontalAnchorDesc() );
|
||||||
registerDataDefinedButton( mVerticalAnchorDDBtn, "vertical_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::verticalAnchorDesc() );
|
registerDataDefinedButton( mVerticalAnchorDDBtn, "vertical_anchor_point", QgsDataDefinedButton::String, QgsDataDefinedButton::verticalAnchorDesc() );
|
||||||
|
|
||||||
|
updateAssistantSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2Widget::symbolLayer()
|
QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2Widget::symbolLayer()
|
||||||
@ -2460,7 +2510,6 @@ QgsFontMarkerSymbolLayerV2Widget::QgsFontMarkerSymbolLayerV2Widget( const QgsVec
|
|||||||
connect( widgetChar, SIGNAL( characterSelected( const QChar & ) ), this, SLOT( setCharacter( const QChar & ) ) );
|
connect( widgetChar, SIGNAL( characterSelected( const QChar & ) ), this, SLOT( setCharacter( const QChar & ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsFontMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
void QgsFontMarkerSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
|
||||||
{
|
{
|
||||||
if ( layer->layerType() != "FontMarker" )
|
if ( layer->layerType() != "FontMarker" )
|
||||||
@ -2591,7 +2640,6 @@ void QgsFontMarkerSymbolLayerV2Widget::on_mVerticalAnchorComboBox_currentIndexCh
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
|
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ class GUI_EXPORT QgsSimpleLineSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
|
|||||||
|
|
||||||
//creates a new icon for the 'change pattern' button
|
//creates a new icon for the 'change pattern' button
|
||||||
void updatePatternIcon();
|
void updatePatternIcon();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
@ -104,6 +105,7 @@ class GUI_EXPORT QgsSimpleMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QgsSimpleMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );
|
QgsSimpleMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );
|
||||||
|
~QgsSimpleMarkerSymbolLayerV2Widget();
|
||||||
|
|
||||||
static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsSimpleMarkerSymbolLayerV2Widget( vl ); }
|
static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsSimpleMarkerSymbolLayerV2Widget( vl ); }
|
||||||
|
|
||||||
@ -128,6 +130,14 @@ class GUI_EXPORT QgsSimpleMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
QgsSimpleMarkerSymbolLayerV2* mLayer;
|
QgsSimpleMarkerSymbolLayerV2* mLayer;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void updateAssistantSymbol();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsMarkerSymbolV2* mAssistantPreviewSymbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
@ -286,6 +296,7 @@ class GUI_EXPORT QgsSvgMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Widget
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QgsSvgMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );
|
QgsSvgMarkerSymbolLayerV2Widget( const QgsVectorLayer* vl, QWidget* parent = NULL );
|
||||||
|
~QgsSvgMarkerSymbolLayerV2Widget();
|
||||||
|
|
||||||
static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsSvgMarkerSymbolLayerV2Widget( vl ); }
|
static QgsSymbolLayerV2Widget* create( const QgsVectorLayer* vl ) { return new QgsSvgMarkerSymbolLayerV2Widget( vl ); }
|
||||||
|
|
||||||
@ -319,6 +330,15 @@ class GUI_EXPORT QgsSvgMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Widget
|
|||||||
void setGuiForSvg( const QgsSvgMarkerSymbolLayerV2* layer );
|
void setGuiForSvg( const QgsSvgMarkerSymbolLayerV2* layer );
|
||||||
|
|
||||||
QgsSvgMarkerSymbolLayerV2* mLayer;
|
QgsSvgMarkerSymbolLayerV2* mLayer;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void updateAssistantSymbol();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsMarkerSymbolV2* mAssistantPreviewSymbol;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
@ -497,6 +517,7 @@ class GUI_EXPORT QgsFontMarkerSymbolLayerV2Widget : public QgsSymbolLayerV2Widge
|
|||||||
protected:
|
protected:
|
||||||
QgsFontMarkerSymbolLayerV2* mLayer;
|
QgsFontMarkerSymbolLayerV2* mLayer;
|
||||||
CharacterWidget* widgetChar;
|
CharacterWidget* widgetChar;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////
|
//////////
|
||||||
|
Loading…
x
Reference in New Issue
Block a user