Save pin inside a piece.
--HG-- branch : feature
This commit is contained in:
parent
a58a479db5
commit
ad403850bc
|
@ -717,7 +717,8 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
|
||||||
<< TagPatternInfo
|
<< TagPatternInfo
|
||||||
<< TagGrainline
|
<< TagGrainline
|
||||||
<< VToolSeamAllowance::TagCSA
|
<< VToolSeamAllowance::TagCSA
|
||||||
<< VToolSeamAllowance::TagIPaths;
|
<< VToolSeamAllowance::TagIPaths
|
||||||
|
<< VToolSeamAllowance::TagPins;
|
||||||
|
|
||||||
const QDomNodeList nodeList = domElement.childNodes();
|
const QDomNodeList nodeList = domElement.childNodes();
|
||||||
for (qint32 i = 0; i < nodeList.size(); ++i)
|
for (qint32 i = 0; i < nodeList.size(); ++i)
|
||||||
|
@ -757,6 +758,9 @@ void VPattern::ParseDetailElement(QDomElement &domElement, const Document &parse
|
||||||
case 5:// VToolSeamAllowance::TagIPaths
|
case 5:// VToolSeamAllowance::TagIPaths
|
||||||
detail.SetInternalPaths(ParsePieceInternalPaths(element));
|
detail.SetInternalPaths(ParsePieceInternalPaths(element));
|
||||||
break;
|
break;
|
||||||
|
case 6:// VToolSeamAllowance::TagPins
|
||||||
|
detail.SetPins(ParsePiecePins(element));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,6 +631,26 @@ QVector<quint32> VAbstractPattern::ParsePieceInternalPaths(const QDomElement &do
|
||||||
return records;
|
return records;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
QVector<quint32> VAbstractPattern::ParsePiecePins(const QDomElement &domElement)
|
||||||
|
{
|
||||||
|
QVector<quint32> records;
|
||||||
|
const QDomNodeList nodeList = domElement.childNodes();
|
||||||
|
for (qint32 i = 0; i < nodeList.size(); ++i)
|
||||||
|
{
|
||||||
|
const QDomElement element = nodeList.at(i).toElement();
|
||||||
|
if (not element.isNull())
|
||||||
|
{
|
||||||
|
const quint32 path = element.text().toUInt();
|
||||||
|
if (path > NULL_ID)
|
||||||
|
{
|
||||||
|
records.append(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
|
VPieceNode VAbstractPattern::ParseSANode(const QDomElement &domElement)
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,6 +99,7 @@ public:
|
||||||
static VPiecePath ParsePieceNodes(const QDomElement &domElement);
|
static VPiecePath ParsePieceNodes(const QDomElement &domElement);
|
||||||
static QVector<CustomSARecord> ParsePieceCSARecords(const QDomElement &domElement);
|
static QVector<CustomSARecord> ParsePieceCSARecords(const QDomElement &domElement);
|
||||||
static QVector<quint32> ParsePieceInternalPaths(const QDomElement &domElement);
|
static QVector<quint32> ParsePieceInternalPaths(const QDomElement &domElement);
|
||||||
|
static QVector<quint32> ParsePiecePins(const QDomElement &domElement);
|
||||||
|
|
||||||
void AddToolOnRemove(VDataTool *tool);
|
void AddToolOnRemove(VDataTool *tool);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,38 @@
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
QVector<quint32> PieceMissingNodes(const QVector<quint32> &d1Nodes, const QVector<quint32> &d2Nodes)
|
||||||
|
{
|
||||||
|
if (d1Nodes.size() == d2Nodes.size()) //-V807
|
||||||
|
{
|
||||||
|
return QVector<quint32>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<quint32> set1;
|
||||||
|
for (qint32 i = 0; i < d1Nodes.size(); ++i)
|
||||||
|
{
|
||||||
|
set1.insert(d1Nodes.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<quint32> set2;
|
||||||
|
for (qint32 j = 0; j < d2Nodes.size(); ++j)
|
||||||
|
{
|
||||||
|
set2.insert(d2Nodes.at(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<quint32> set3 = set1.subtract(set2).toList();
|
||||||
|
QVector<quint32> r;
|
||||||
|
for (qint32 i = 0; i < set3.size(); ++i)
|
||||||
|
{
|
||||||
|
r.append(set3.at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
VPiece::VPiece()
|
VPiece::VPiece()
|
||||||
: VAbstractPiece(), d(new VPieceData(PiecePathType::PiecePath))
|
: VAbstractPiece(), d(new VPieceData(PiecePathType::PiecePath))
|
||||||
|
@ -367,63 +399,31 @@ QVector<quint32> VPiece::MissingNodes(const VPiece &det) const
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
|
QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
|
||||||
{
|
{
|
||||||
const QVector<CustomSARecord> detRecords = det.GetCustomSARecords();
|
QVector<quint32> oldCSARecords;
|
||||||
if (d->m_customSARecords.size() == detRecords.size()) //-V807
|
|
||||||
{
|
|
||||||
return QVector<quint32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<quint32> set1;
|
|
||||||
for (qint32 i = 0; i < d->m_customSARecords.size(); ++i)
|
for (qint32 i = 0; i < d->m_customSARecords.size(); ++i)
|
||||||
{
|
{
|
||||||
set1.insert(d->m_customSARecords.at(i).path);
|
oldCSARecords.append(d->m_customSARecords.at(i).path);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<quint32> set2;
|
QVector<quint32> newCSARecords;
|
||||||
for (qint32 j = 0; j < detRecords.size(); ++j)
|
for (qint32 i = 0; i < det.GetCustomSARecords().size(); ++i)
|
||||||
{
|
{
|
||||||
set2.insert(detRecords.at(j).path);
|
newCSARecords.append(det.GetCustomSARecords().at(i).path);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<quint32> set3 = set1.subtract(set2).toList();
|
return PieceMissingNodes(oldCSARecords, newCSARecords);
|
||||||
QVector<quint32> r;
|
|
||||||
for (qint32 i = 0; i < set3.size(); ++i)
|
|
||||||
{
|
|
||||||
r.append(set3.at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
QVector<quint32> VPiece::MissingInternalPaths(const VPiece &det) const
|
QVector<quint32> VPiece::MissingInternalPaths(const VPiece &det) const
|
||||||
{
|
{
|
||||||
const QVector<quint32> detRecords = det.GetInternalPaths();
|
return PieceMissingNodes(d->m_internalPaths, det.GetInternalPaths());
|
||||||
if (d->m_internalPaths.size() == detRecords.size()) //-V807
|
}
|
||||||
{
|
|
||||||
return QVector<quint32>();
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<quint32> set1;
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
for (qint32 i = 0; i < d->m_internalPaths.size(); ++i)
|
QVector<quint32> VPiece::MissingPins(const VPiece &det) const
|
||||||
{
|
{
|
||||||
set1.insert(d->m_internalPaths.at(i));
|
return PieceMissingNodes(d->m_pins, det.GetPins());
|
||||||
}
|
|
||||||
|
|
||||||
QSet<quint32> set2;
|
|
||||||
for (qint32 j = 0; j < detRecords.size(); ++j)
|
|
||||||
{
|
|
||||||
set2.insert(detRecords.at(j));
|
|
||||||
}
|
|
||||||
|
|
||||||
const QList<quint32> set3 = set1.subtract(set2).toList();
|
|
||||||
QVector<quint32> r;
|
|
||||||
for (qint32 i = 0; i < set3.size(); ++i)
|
|
||||||
{
|
|
||||||
r.append(set3.at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -99,6 +99,7 @@ public:
|
||||||
QVector<quint32> MissingNodes(const VPiece &det) const;
|
QVector<quint32> MissingNodes(const VPiece &det) const;
|
||||||
QVector<quint32> MissingCSAPath(const VPiece &det) const;
|
QVector<quint32> MissingCSAPath(const VPiece &det) const;
|
||||||
QVector<quint32> MissingInternalPaths(const VPiece &det) const;
|
QVector<quint32> MissingInternalPaths(const VPiece &det) const;
|
||||||
|
QVector<quint32> MissingPins(const VPiece &det) const;
|
||||||
|
|
||||||
void SetPatternPieceData(const VPatternPieceData &data);
|
void SetPatternPieceData(const VPatternPieceData &data);
|
||||||
VPatternPieceData& GetPatternPieceData();
|
VPatternPieceData& GetPatternPieceData();
|
||||||
|
|
|
@ -140,15 +140,15 @@ void VToolPin::AddToFile()
|
||||||
|
|
||||||
if (m_pieceId > NULL_ID)
|
if (m_pieceId > NULL_ID)
|
||||||
{
|
{
|
||||||
// const VPiece oldDet = VAbstractTool::data.GetPiece(m_pieceId);
|
const VPiece oldDet = VAbstractTool::data.GetPiece(m_pieceId);
|
||||||
// VPiece newDet = oldDet;
|
VPiece newDet = oldDet;
|
||||||
|
|
||||||
// newDet.GetPins().append(id);
|
newDet.GetPins().append(id);
|
||||||
|
|
||||||
// SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
|
SavePieceOptions *saveCommand = new SavePieceOptions(oldDet, newDet, doc, m_pieceId);
|
||||||
// qApp->getUndoStack()->push(saveCommand);// First push then make a connect
|
qApp->getUndoStack()->push(saveCommand);// First push then make a connect
|
||||||
// VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
|
VAbstractTool::data.UpdatePiece(m_pieceId, newDet);// Update piece because first save will not call lite update
|
||||||
// connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
|
connect(saveCommand, &SavePieceOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ const quint8 VToolSeamAllowance::pieceVersion = 2;
|
||||||
const QString VToolSeamAllowance::TagCSA = QStringLiteral("csa");
|
const QString VToolSeamAllowance::TagCSA = QStringLiteral("csa");
|
||||||
const QString VToolSeamAllowance::TagRecord = QStringLiteral("record");
|
const QString VToolSeamAllowance::TagRecord = QStringLiteral("record");
|
||||||
const QString VToolSeamAllowance::TagIPaths = QStringLiteral("iPaths");
|
const QString VToolSeamAllowance::TagIPaths = QStringLiteral("iPaths");
|
||||||
|
const QString VToolSeamAllowance::TagPins = QStringLiteral("pins");
|
||||||
|
|
||||||
const QString VToolSeamAllowance::AttrVersion = QStringLiteral("version");
|
const QString VToolSeamAllowance::AttrVersion = QStringLiteral("version");
|
||||||
const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
|
const QString VToolSeamAllowance::AttrForbidFlipping = QStringLiteral("forbidFlipping");
|
||||||
|
@ -220,6 +221,22 @@ void VToolSeamAllowance::AddInternalPaths(VAbstractPattern *doc, QDomElement &do
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
|
void VToolSeamAllowance::AddPins(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &pins)
|
||||||
|
{
|
||||||
|
if (pins.size() > 0)
|
||||||
|
{
|
||||||
|
QDomElement pinsElement = doc->createElement(VToolSeamAllowance::TagPins);
|
||||||
|
for (int i = 0; i < pins.size(); ++i)
|
||||||
|
{
|
||||||
|
QDomElement recordNode = doc->createElement(VToolSeamAllowance::TagRecord);
|
||||||
|
recordNode.appendChild(doc->createTextNode(QString().setNum(pins.at(i))));
|
||||||
|
pinsElement.appendChild(recordNode);
|
||||||
|
}
|
||||||
|
domElement.appendChild(pinsElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------
|
||||||
void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
|
void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece)
|
||||||
{
|
{
|
||||||
|
@ -728,6 +745,7 @@ void VToolSeamAllowance::AddToFile()
|
||||||
//custom seam allowance
|
//custom seam allowance
|
||||||
AddCSARecords(doc, domElement, piece.GetCustomSARecords());
|
AddCSARecords(doc, domElement, piece.GetCustomSARecords());
|
||||||
AddInternalPaths(doc, domElement, piece.GetInternalPaths());
|
AddInternalPaths(doc, domElement, piece.GetInternalPaths());
|
||||||
|
AddPins(doc, domElement, piece.GetPins());
|
||||||
|
|
||||||
AddPiece *addDet = new AddPiece(domElement, doc, piece, m_drawName);
|
AddPiece *addDet = new AddPiece(domElement, doc, piece, m_drawName);
|
||||||
connect(addDet, &AddPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
|
connect(addDet, &AddPiece::NeedFullParsing, doc, &VAbstractPattern::NeedFullParsing);
|
||||||
|
@ -760,6 +778,7 @@ void VToolSeamAllowance::RefreshDataInFile()
|
||||||
AddNodes(doc, domElement, piece);
|
AddNodes(doc, domElement, piece);
|
||||||
AddCSARecords(doc, domElement, piece.GetCustomSARecords());
|
AddCSARecords(doc, domElement, piece.GetCustomSARecords());
|
||||||
AddInternalPaths(doc, domElement, piece.GetInternalPaths());
|
AddInternalPaths(doc, domElement, piece.GetInternalPaths());
|
||||||
|
AddPins(doc, domElement, piece.GetPins());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
static const QString TagCSA;
|
static const QString TagCSA;
|
||||||
static const QString TagRecord;
|
static const QString TagRecord;
|
||||||
static const QString TagIPaths;
|
static const QString TagIPaths;
|
||||||
|
static const QString TagPins;
|
||||||
|
|
||||||
static const QString AttrVersion;
|
static const QString AttrVersion;
|
||||||
static const QString AttrForbidFlipping;
|
static const QString AttrForbidFlipping;
|
||||||
|
@ -74,6 +75,7 @@ public:
|
||||||
static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record);
|
static void AddCSARecord(VAbstractPattern *doc, QDomElement &domElement, const CustomSARecord &record);
|
||||||
static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector<CustomSARecord> &records);
|
static void AddCSARecords(VAbstractPattern *doc, QDomElement &domElement, const QVector<CustomSARecord> &records);
|
||||||
static void AddInternalPaths(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &paths);
|
static void AddInternalPaths(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &paths);
|
||||||
|
static void AddPins(VAbstractPattern *doc, QDomElement &domElement, const QVector<quint32> &pins);
|
||||||
static void AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
static void AddPatternPieceData(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
||||||
static void AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
static void AddPatternInfo(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
||||||
static void AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
static void AddGrainline(VAbstractPattern *doc, QDomElement &domElement, const VPiece &piece);
|
||||||
|
|
|
@ -1422,6 +1422,7 @@ void VToolUnionDetails::AddDetail(QDomElement &domElement, const VPiece &d) cons
|
||||||
//custom seam allowance
|
//custom seam allowance
|
||||||
VToolSeamAllowance::AddCSARecords(doc, det, d.GetCustomSARecords());
|
VToolSeamAllowance::AddCSARecords(doc, det, d.GetCustomSARecords());
|
||||||
VToolSeamAllowance::AddInternalPaths(doc, det, d.GetInternalPaths());
|
VToolSeamAllowance::AddInternalPaths(doc, det, d.GetInternalPaths());
|
||||||
|
VToolSeamAllowance::AddPins(doc, det, d.GetPins());
|
||||||
|
|
||||||
domElement.appendChild(det);
|
domElement.appendChild(det);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ void AddPiece::undo()
|
||||||
DecrementReferences(m_detail.GetPath().GetNodes());
|
DecrementReferences(m_detail.GetPath().GetNodes());
|
||||||
DecrementReferences(m_detail.GetCustomSARecords());
|
DecrementReferences(m_detail.GetCustomSARecords());
|
||||||
DecrementReferences(m_detail.GetInternalPaths());
|
DecrementReferences(m_detail.GetInternalPaths());
|
||||||
|
DecrementReferences(m_detail.GetPins());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,6 +107,7 @@ void DeletePiece::redo()
|
||||||
DecrementReferences(m_detail.GetPath().GetNodes());
|
DecrementReferences(m_detail.GetPath().GetNodes());
|
||||||
DecrementReferences(m_detail.GetCustomSARecords());
|
DecrementReferences(m_detail.GetCustomSARecords());
|
||||||
DecrementReferences(m_detail.GetInternalPaths());
|
DecrementReferences(m_detail.GetInternalPaths());
|
||||||
|
DecrementReferences(m_detail.GetPins());
|
||||||
emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
|
emit NeedFullParsing(); // Doesn't work when UnionDetail delete detail.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -78,10 +78,12 @@ void SavePieceOptions::undo()
|
||||||
VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
|
VToolSeamAllowance::AddNodes(doc, domElement, m_oldDet);
|
||||||
VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
|
VToolSeamAllowance::AddCSARecords(doc, domElement, m_oldDet.GetCustomSARecords());
|
||||||
VToolSeamAllowance::AddInternalPaths(doc, domElement, m_oldDet.GetInternalPaths());
|
VToolSeamAllowance::AddInternalPaths(doc, domElement, m_oldDet.GetInternalPaths());
|
||||||
|
VToolSeamAllowance::AddPins(doc, domElement, m_oldDet.GetPins());
|
||||||
|
|
||||||
IncrementReferences(m_oldDet.MissingNodes(m_newDet));
|
IncrementReferences(m_oldDet.MissingNodes(m_newDet));
|
||||||
IncrementReferences(m_oldDet.MissingCSAPath(m_newDet));
|
IncrementReferences(m_oldDet.MissingCSAPath(m_newDet));
|
||||||
IncrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
|
IncrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
|
||||||
|
IncrementReferences(m_oldDet.MissingPins(m_newDet));
|
||||||
emit NeedLiteParsing(Document::LiteParse);
|
emit NeedLiteParsing(Document::LiteParse);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -107,10 +109,12 @@ void SavePieceOptions::redo()
|
||||||
VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
|
VToolSeamAllowance::AddNodes(doc, domElement, m_newDet);
|
||||||
VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
|
VToolSeamAllowance::AddCSARecords(doc, domElement, m_newDet.GetCustomSARecords());
|
||||||
VToolSeamAllowance::AddInternalPaths(doc, domElement, m_newDet.GetInternalPaths());
|
VToolSeamAllowance::AddInternalPaths(doc, domElement, m_newDet.GetInternalPaths());
|
||||||
|
VToolSeamAllowance::AddPins(doc, domElement, m_newDet.GetPins());
|
||||||
|
|
||||||
DecrementReferences(m_oldDet.MissingNodes(m_newDet));
|
DecrementReferences(m_oldDet.MissingNodes(m_newDet));
|
||||||
DecrementReferences(m_oldDet.MissingCSAPath(m_newDet));
|
DecrementReferences(m_oldDet.MissingCSAPath(m_newDet));
|
||||||
DecrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
|
DecrementReferences(m_oldDet.MissingInternalPaths(m_newDet));
|
||||||
|
DecrementReferences(m_oldDet.MissingPins(m_newDet));
|
||||||
|
|
||||||
emit NeedLiteParsing(Document::LiteParse);
|
emit NeedLiteParsing(Document::LiteParse);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user