Speedup optimization.
Move label data update to a separate thread to not block main GUI thread.
This commit is contained in:
parent
d997f74620
commit
2aea155d61
|
@ -698,7 +698,8 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat
|
|||
det.SetQuantity(data.GetQuantity());
|
||||
if (data.IsVisible())
|
||||
{
|
||||
det.SetPieceText(piece.GetName(), data, settings->GetLabelFont(), settings->GetLabelSVGFont(), pattern);
|
||||
VAbstractPattern *pDoc = VAbstractValApplication::VApp()->getCurrentDocument();
|
||||
det.SetPieceText(pDoc, piece.GetName(), data, settings->GetLabelFont(), settings->GetLabelSVGFont(), pattern);
|
||||
}
|
||||
|
||||
const VPatternLabelData &geom = piece.GetPatternLabelData();
|
||||
|
@ -890,8 +891,8 @@ auto VLayoutPiece::GetPieceText() const -> QStringList
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VLayoutPiece::SetPieceText(const QString &qsName, const VPieceLabelData &data, const QFont &font,
|
||||
const QString &SVGFontFamily, const VContainer *pattern)
|
||||
void VLayoutPiece::SetPieceText(VAbstractPattern *pDoc, const QString &qsName, const VPieceLabelData &data,
|
||||
const QFont &font, const QString &SVGFontFamily, const VContainer *pattern)
|
||||
{
|
||||
QPointF ptPos;
|
||||
qreal labelWidth = 0;
|
||||
|
@ -929,7 +930,10 @@ void VLayoutPiece::SetPieceText(const QString &qsName, const VPieceLabelData &da
|
|||
d->m_tmDetail.SetFontSize(fntSize);
|
||||
d->m_tmDetail.SetSVGFontPointSize(fntSize);
|
||||
|
||||
d->m_tmDetail.Update(qsName, data, pattern);
|
||||
VPieceLabelInfo info = VTextManager::PrepareLabelInfo(pDoc, pattern, true);
|
||||
info.pieceName = qsName;
|
||||
info.labelData = data;
|
||||
d->m_tmDetail.UpdatePieceLabelInfo(info);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1000,7 +1004,8 @@ void VLayoutPiece::SetPatternInfo(VAbstractPattern *pDoc, const VPatternLabelDat
|
|||
d->m_tmPattern.SetFontSize(fntSize);
|
||||
d->m_tmPattern.SetSVGFontPointSize(fntSize);
|
||||
|
||||
d->m_tmPattern.Update(pDoc, pattern);
|
||||
VPieceLabelInfo const info = VTextManager::PrepareLabelInfo(pDoc, pattern, false);
|
||||
d->m_tmPattern.UpdatePatternLabelInfo(info);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -116,7 +116,7 @@ public:
|
|||
void SetInternalPaths(const QVector<VLayoutPiecePath> &internalPaths);
|
||||
|
||||
auto GetPieceText() const -> QStringList;
|
||||
void SetPieceText(const QString &qsName, const VPieceLabelData &data, const QFont &font,
|
||||
void SetPieceText(VAbstractPattern *pDoc, const QString &qsName, const VPieceLabelData &data, const QFont &font,
|
||||
const QString &SVGFontFamily, const VContainer *pattern);
|
||||
|
||||
auto GetPatternText() const -> QStringList;
|
||||
|
|
|
@ -32,13 +32,10 @@
|
|||
#include <QFileInfo>
|
||||
#include <QFlags> // QFlags<Qt::Alignment>
|
||||
#include <QFontMetrics>
|
||||
#include <QGlobalStatic>
|
||||
#include <QLatin1String>
|
||||
#include <QRegularExpression>
|
||||
#include <QtMath>
|
||||
|
||||
#include "../ifc/xml/vabstractpattern.h"
|
||||
#include "../vmisc/compatibility.h"
|
||||
#include "../vmisc/svgfont/vsvgfont.h"
|
||||
#include "../vmisc/svgfont/vsvgfontdatabase.h"
|
||||
#include "../vmisc/svgfont/vsvgfontengine.h"
|
||||
|
@ -46,22 +43,13 @@
|
|||
#include "../vmisc/vcommonsettings.h"
|
||||
#include "../vmisc/vtranslator.h"
|
||||
#include "../vpatterndb/calculator.h"
|
||||
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
|
||||
#include "../vpatterndb/variables/vmeasurement.h"
|
||||
#include "../vpatterndb/vcontainer.h"
|
||||
#include "vtextmanager.h"
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
namespace
|
||||
{
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_CLANG("-Wunused-member-function")
|
||||
|
||||
Q_GLOBAL_STATIC(QVector<TextLine>, m_patternLabelLinesCache) // NOLINT
|
||||
|
||||
QT_WARNING_POP
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto FileBaseName(const QString &filePath) -> QString
|
||||
{
|
||||
|
@ -296,11 +284,9 @@ auto operator>>(QDataStream &dataStream, VTextManager &data) -> QDataStream &
|
|||
namespace
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void PrepareMeasurementsPlaceholders(const VContainer *data, QMap<QString, QString> &placeholders)
|
||||
void PrepareMeasurementsPlaceholders(const VPieceLabelInfo &info, QMap<QString, QString> &placeholders)
|
||||
{
|
||||
SCASSERT(data != nullptr)
|
||||
|
||||
const QMap<QString, QSharedPointer<VMeasurement>> measurements = data->DataMeasurements();
|
||||
const QMap<QString, QSharedPointer<VMeasurement>> measurements = info.measurements;
|
||||
auto i = measurements.constBegin();
|
||||
while (i != measurements.constEnd())
|
||||
{
|
||||
|
@ -310,77 +296,40 @@ void PrepareMeasurementsPlaceholders(const VContainer *data, QMap<QString, QStri
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void PrepareCustomerPlaceholders(const VAbstractPattern *doc, QMap<QString, QString> &placeholders)
|
||||
void PrepareDimensionPlaceholders(const VPieceLabelInfo &info, QMap<QString, QString> &placeholders)
|
||||
{
|
||||
QLocale const locale(VAbstractApplication::VApp()->Settings()->GetLocale());
|
||||
placeholders.insert(pl_height, info.dimensionHeight);
|
||||
placeholders.insert(pl_dimensionX, info.dimensionHeight);
|
||||
|
||||
if (VAbstractValApplication::VApp()->GetMeasurementsType() == MeasurementsType::Individual)
|
||||
{
|
||||
placeholders.insert(pl_customer, VAbstractValApplication::VApp()->GetCustomerName());
|
||||
placeholders.insert(pl_size, info.dimensionSize);
|
||||
placeholders.insert(pl_dimensionY, info.dimensionSize);
|
||||
|
||||
const QString birthDate =
|
||||
locale.toString(VAbstractValApplication::VApp()->GetCustomerBirthDate(), doc->GetLabelDateFormat());
|
||||
placeholders.insert(pl_birthDate, birthDate);
|
||||
placeholders.insert(pl_hip, info.dimensionHip);
|
||||
placeholders.insert(pl_dimensionZ, info.dimensionHip);
|
||||
|
||||
placeholders.insert(pl_email, VAbstractValApplication::VApp()->CustomerEmail());
|
||||
}
|
||||
else
|
||||
{
|
||||
placeholders.insert(pl_customer, doc->GetCustomerName());
|
||||
placeholders.insert(pl_waist, info.dimensionWaist);
|
||||
placeholders.insert(pl_dimensionW, info.dimensionWaist);
|
||||
|
||||
const QString birthDate = locale.toString(doc->GetCustomerBirthDate(), doc->GetLabelDateFormat());
|
||||
placeholders.insert(pl_birthDate, birthDate);
|
||||
|
||||
placeholders.insert(pl_email, doc->GetCustomerEmail());
|
||||
}
|
||||
placeholders.insert(pl_heightLabel,
|
||||
not info.dimensionHeightLabel.isEmpty() ? info.dimensionHeightLabel : info.dimensionHeight);
|
||||
placeholders.insert(pl_sizeLabel,
|
||||
not info.dimensionSizeLabel.isEmpty() ? info.dimensionSizeLabel : info.dimensionSize);
|
||||
placeholders.insert(pl_hipLabel, not info.dimensionHipLabel.isEmpty() ? info.dimensionHipLabel : info.dimensionHip);
|
||||
placeholders.insert(pl_waistLabel,
|
||||
not info.dimensionWaistLabel.isEmpty() ? info.dimensionWaistLabel : info.dimensionWaist);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void PrepareDimensionPlaceholders(QMap<QString, QString> &placeholders)
|
||||
void PrepareUserMaterialsPlaceholders(const VPieceLabelInfo &info, QMap<QString, QString> &placeholders)
|
||||
{
|
||||
QString const heightValue = QString::number(VAbstractValApplication::VApp()->GetDimensionHeight());
|
||||
placeholders.insert(pl_height, heightValue);
|
||||
placeholders.insert(pl_dimensionX, heightValue);
|
||||
|
||||
QString const sizeValue = QString::number(VAbstractValApplication::VApp()->GetDimensionSize());
|
||||
placeholders.insert(pl_size, sizeValue);
|
||||
placeholders.insert(pl_dimensionY, sizeValue);
|
||||
|
||||
QString const hipValue = QString::number(VAbstractValApplication::VApp()->GetDimensionHip());
|
||||
placeholders.insert(pl_hip, hipValue);
|
||||
placeholders.insert(pl_dimensionZ, hipValue);
|
||||
|
||||
QString const waistValue = QString::number(VAbstractValApplication::VApp()->GetDimensionWaist());
|
||||
placeholders.insert(pl_waist, waistValue);
|
||||
placeholders.insert(pl_dimensionW, waistValue);
|
||||
|
||||
{
|
||||
QString label = VAbstractValApplication::VApp()->GetDimensionHeightLabel();
|
||||
placeholders.insert(pl_heightLabel, not label.isEmpty() ? label : heightValue);
|
||||
|
||||
label = VAbstractValApplication::VApp()->GetDimensionSizeLabel();
|
||||
placeholders.insert(pl_sizeLabel, not label.isEmpty() ? label : sizeValue);
|
||||
|
||||
label = VAbstractValApplication::VApp()->GetDimensionHipLabel();
|
||||
placeholders.insert(pl_hipLabel, not label.isEmpty() ? label : hipValue);
|
||||
|
||||
label = VAbstractValApplication::VApp()->GetDimensionWaistLabel();
|
||||
placeholders.insert(pl_waistLabel, not label.isEmpty() ? label : waistValue);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void PrepareUserMaterialsPlaceholders(const VAbstractPattern *doc, QMap<QString, QString> &placeholders)
|
||||
{
|
||||
const QMap<int, QString> materials = doc->GetPatternMaterials();
|
||||
for (int i = 0; i < userMaterialPlaceholdersQuantity; ++i)
|
||||
{
|
||||
const QString number = QString::number(i + 1);
|
||||
|
||||
QString value;
|
||||
if (materials.contains(i + 1))
|
||||
if (info.patternMaterials.contains(i + 1))
|
||||
{
|
||||
value = materials.value(i + 1);
|
||||
value = info.patternMaterials.value(i + 1);
|
||||
}
|
||||
|
||||
placeholders.insert(pl_userMaterial + number, value);
|
||||
|
@ -388,10 +337,10 @@ void PrepareUserMaterialsPlaceholders(const VAbstractPattern *doc, QMap<QString,
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void PrepareFinalMeasurementsPlaceholders(const VAbstractPattern *doc, bool pieceLabel,
|
||||
const QString &pieceAreaShortName, QMap<QString, QString> &placeholders)
|
||||
void PrepareFinalMeasurementsPlaceholders(bool pieceLabel, const VPieceLabelInfo &info,
|
||||
QMap<QString, QString> &placeholders)
|
||||
{
|
||||
VContainer completeData = doc->GetCompleteData();
|
||||
VContainer completeData = info.completeData;
|
||||
completeData.FillPiecesAreas(VAbstractValApplication::VApp()->patternUnits());
|
||||
|
||||
if (pieceLabel)
|
||||
|
@ -400,7 +349,7 @@ void PrepareFinalMeasurementsPlaceholders(const VAbstractPattern *doc, bool piec
|
|||
|
||||
try
|
||||
{
|
||||
const QString formula = pieceArea_ + pieceAreaShortName;
|
||||
const QString formula = pieceArea_ + info.labelData.GetAreaShortName();
|
||||
const qreal result = cal->EvalFormula(completeData.DataVariables(), formula);
|
||||
placeholders[pl_currentArea] = QString::number(result);
|
||||
}
|
||||
|
@ -414,7 +363,7 @@ void PrepareFinalMeasurementsPlaceholders(const VAbstractPattern *doc, bool piec
|
|||
|
||||
try
|
||||
{
|
||||
const QString formula = pieceSeamLineArea_ + pieceAreaShortName;
|
||||
const QString formula = pieceSeamLineArea_ + info.labelData.GetAreaShortName();
|
||||
const qreal result = cal->EvalFormula(completeData.DataVariables(), formula);
|
||||
placeholders[pl_currentSeamLineArea] = QString::number(result);
|
||||
}
|
||||
|
@ -433,7 +382,7 @@ void PrepareFinalMeasurementsPlaceholders(const VAbstractPattern *doc, bool piec
|
|||
placeholders.insert(pl_currentSeamLineArea, QString());
|
||||
}
|
||||
|
||||
const QVector<VFinalMeasurement> measurements = doc->GetFinalMeasurements();
|
||||
const QVector<VFinalMeasurement> measurements = info.finalMeasurements;
|
||||
for (int i = 0; i < measurements.size(); ++i)
|
||||
{
|
||||
const VFinalMeasurement &m = measurements.at(i);
|
||||
|
@ -459,48 +408,43 @@ void PrepareFinalMeasurementsPlaceholders(const VAbstractPattern *doc, bool piec
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto PreparePlaceholders(const VAbstractPattern *doc, const VContainer *data, bool pieceLabel = false,
|
||||
const QString &pieceAreaShortName = QString()) -> QMap<QString, QString>
|
||||
auto PreparePlaceholders(const VPieceLabelInfo &info, bool pieceLabel = false) -> QMap<QString, QString>
|
||||
{
|
||||
SCASSERT(doc != nullptr)
|
||||
SCASSERT(data != nullptr)
|
||||
|
||||
QMap<QString, QString> placeholders;
|
||||
|
||||
// Pattern tags
|
||||
QLocale const locale(VAbstractApplication::VApp()->Settings()->GetLocale());
|
||||
|
||||
const QString date = locale.toString(QDate::currentDate(), doc->GetLabelDateFormat());
|
||||
const QString date = info.locale.toString(QDate::currentDate(), info.labelDateFormat);
|
||||
placeholders.insert(pl_date, date);
|
||||
|
||||
const QString time = locale.toString(QTime::currentTime(), doc->GetLabelTimeFormat());
|
||||
const QString time = info.locale.toString(QTime::currentTime(), info.LabelTimeFormat);
|
||||
placeholders.insert(pl_time, time);
|
||||
|
||||
placeholders.insert(pl_patternName, doc->GetPatternName());
|
||||
placeholders.insert(pl_patternNumber, doc->GetPatternNumber());
|
||||
placeholders.insert(pl_author, doc->GetCompanyName());
|
||||
placeholders.insert(pl_patternName, info.patternName);
|
||||
placeholders.insert(pl_patternNumber, info.patternNumber);
|
||||
placeholders.insert(pl_author, info.companyName);
|
||||
|
||||
placeholders.insert(pl_mUnits, UnitsToStr(VAbstractValApplication::VApp()->MeasurementsUnits(), true));
|
||||
placeholders.insert(pl_mUnits, UnitsToStr(info.measurementsUnits, true));
|
||||
const QString pUnits = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true);
|
||||
placeholders.insert(pl_pUnits, pUnits);
|
||||
placeholders.insert(pl_mSizeUnits, UnitsToStr(VAbstractValApplication::VApp()->DimensionSizeUnits(), true));
|
||||
placeholders.insert(pl_mSizeUnits, UnitsToStr(info.dimensionSizeUnits, true));
|
||||
placeholders.insert(pl_areaUnits, pUnits + QStringLiteral("²"));
|
||||
|
||||
PrepareCustomerPlaceholders(doc, placeholders);
|
||||
placeholders.insert(pl_customer, info.customerName);
|
||||
placeholders.insert(pl_birthDate, info.locale.toString(info.customerBirthDate, info.labelDateFormat));
|
||||
placeholders.insert(pl_email, info.customerEmail);
|
||||
|
||||
placeholders.insert(pl_pExt, QStringLiteral("val"));
|
||||
placeholders.insert(pl_pFileName, FileBaseName(VAbstractValApplication::VApp()->GetPatternPath()));
|
||||
placeholders.insert(pl_mFileName, FileBaseName(doc->MPath()));
|
||||
placeholders.insert(pl_mFileName, FileBaseName(info.measurementsPath));
|
||||
|
||||
PrepareDimensionPlaceholders(placeholders);
|
||||
PrepareDimensionPlaceholders(info, placeholders);
|
||||
|
||||
placeholders.insert(pl_mExt, VAbstractValApplication::VApp()->GetMeasurementsType() == MeasurementsType::Multisize
|
||||
? QStringLiteral("vst")
|
||||
placeholders.insert(pl_mExt, info.measurementsType == MeasurementsType::Multisize ? QStringLiteral("vst")
|
||||
: QStringLiteral("vit"));
|
||||
|
||||
PrepareUserMaterialsPlaceholders(doc, placeholders);
|
||||
PrepareMeasurementsPlaceholders(data, placeholders);
|
||||
PrepareFinalMeasurementsPlaceholders(doc, pieceLabel, pieceAreaShortName, placeholders);
|
||||
PrepareUserMaterialsPlaceholders(info, placeholders);
|
||||
PrepareMeasurementsPlaceholders(info, placeholders);
|
||||
PrepareFinalMeasurementsPlaceholders(pieceLabel, info, placeholders);
|
||||
|
||||
// Piece tags
|
||||
placeholders.insert(pl_pLetter, QString());
|
||||
|
@ -513,35 +457,40 @@ auto PreparePlaceholders(const VAbstractPattern *doc, const VContainer *data, bo
|
|||
placeholders.insert(pl_pQuantity, QString());
|
||||
placeholders.insert(pl_wOnFold, QString());
|
||||
|
||||
QSharedPointer<VTranslator> const phTr = VAbstractApplication::VApp()->GetPlaceholderTranslator();
|
||||
|
||||
if (QSharedPointer<VTranslator> const phTr = info.placeholderTranslator; !phTr.isNull())
|
||||
{
|
||||
placeholders.insert(pl_mFabric, phTr->translate("Placeholder", "Fabric"));
|
||||
placeholders.insert(pl_mLining, phTr->translate("Placeholder", "Lining"));
|
||||
placeholders.insert(pl_mInterfacing, phTr->translate("Placeholder", "Interfacing"));
|
||||
placeholders.insert(pl_mInterlining, phTr->translate("Placeholder", "Interlining"));
|
||||
placeholders.insert(pl_wCut, phTr->translate("Placeholder", "Cut"));
|
||||
}
|
||||
|
||||
return placeholders;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void InitPiecePlaceholders(QMap<QString, QString> &placeholders, const QString &name, const VPieceLabelData &data)
|
||||
void InitPiecePlaceholders(QMap<QString, QString> &placeholders, const VPieceLabelInfo &info)
|
||||
{
|
||||
const VPieceLabelData data = info.labelData;
|
||||
|
||||
placeholders[pl_pLetter] = data.GetLetter();
|
||||
placeholders[pl_pAnnotation] = data.GetAnnotation();
|
||||
placeholders[pl_pOrientation] = data.GetOrientation();
|
||||
placeholders[pl_pRotation] = data.GetRotationWay();
|
||||
placeholders[pl_pTilt] = data.GetTilt();
|
||||
placeholders[pl_pFoldPosition] = data.GetFoldPosition();
|
||||
placeholders[pl_pName] = name;
|
||||
placeholders[pl_pName] = info.pieceName;
|
||||
placeholders[pl_pQuantity] = QString::number(data.GetQuantity());
|
||||
|
||||
if (data.IsOnFold())
|
||||
{
|
||||
QSharedPointer<VTranslator> const phTr = VAbstractApplication::VApp()->GetPlaceholderTranslator();
|
||||
if (QSharedPointer<VTranslator> const phTr = info.placeholderTranslator; !phTr.isNull())
|
||||
{
|
||||
placeholders[pl_wOnFold] = phTr->translate("Placeholder", "on fold");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto ReplacePlaceholders(const QMap<QString, QString> &placeholders, QString line) -> QString
|
||||
|
@ -789,18 +738,15 @@ auto VTextManager::GetLabelSourceLines(int width, const VSvgFont &font, qreal pe
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief VTextManager::Update updates the text lines with detail data
|
||||
* @param qsName detail name
|
||||
* @param data reference to the detail data
|
||||
*/
|
||||
void VTextManager::Update(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern)
|
||||
void VTextManager::UpdatePieceLabelInfo(const VPieceLabelInfo &info)
|
||||
{
|
||||
m_liLines.clear();
|
||||
|
||||
QMap<QString, QString> placeholders = PreparePlaceholders(VAbstractValApplication::VApp()->getCurrentDocument(),
|
||||
pattern, true, data.GetAreaShortName());
|
||||
InitPiecePlaceholders(placeholders, qsName, data);
|
||||
QMap<QString, QString> placeholders = PreparePlaceholders(info, true);
|
||||
InitPiecePlaceholders(placeholders, info);
|
||||
|
||||
QVector<VLabelTemplateLine> lines = data.GetLabelTemplate();
|
||||
QVector<VLabelTemplateLine> lines = info.labelData.GetLabelTemplate();
|
||||
|
||||
for (auto &line : lines)
|
||||
{
|
||||
|
@ -813,32 +759,25 @@ void VTextManager::Update(const QString &qsName, const VPieceLabelData &data, co
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief VTextManager::Update updates the text lines with pattern info
|
||||
* @param pDoc pointer to the abstract pattern object
|
||||
*/
|
||||
void VTextManager::Update(VAbstractPattern *pDoc, const VContainer *pattern)
|
||||
void VTextManager::UpdatePatternLabelInfo(const VPieceLabelInfo &info)
|
||||
{
|
||||
m_liLines.clear();
|
||||
|
||||
if (m_patternLabelLinesCache->isEmpty() || pDoc->GetPatternWasChanged())
|
||||
{
|
||||
QVector<VLabelTemplateLine> lines = pDoc->GetPatternLabelTemplate();
|
||||
if (lines.isEmpty() && m_patternLabelLinesCache->isEmpty())
|
||||
QVector<VLabelTemplateLine> lines = info.patternLabelTemplate;
|
||||
if (lines.isEmpty())
|
||||
{
|
||||
return; // Nothing to parse
|
||||
}
|
||||
|
||||
const QMap<QString, QString> placeholders = PreparePlaceholders(pDoc, pattern);
|
||||
const QMap<QString, QString> placeholders = PreparePlaceholders(info);
|
||||
|
||||
for (auto &line : lines)
|
||||
{
|
||||
line.line = ReplacePlaceholders(placeholders, line.line);
|
||||
}
|
||||
|
||||
pDoc->SetPatternWasChanged(false);
|
||||
*m_patternLabelLinesCache = PrepareLines(lines);
|
||||
}
|
||||
|
||||
m_liLines = *m_patternLabelLinesCache;
|
||||
m_liLines = PrepareLines(lines);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1030,3 +969,52 @@ auto VTextManager::BreakTextIntoLines(const QString &text, const VSvgFont &font,
|
|||
|
||||
return lines;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VTextManager::PrepareLabelInfo(VAbstractPattern *doc, const VContainer *pattern, bool pieceLabel)
|
||||
-> VPieceLabelInfo
|
||||
{
|
||||
VPieceLabelInfo info(doc->GetCompleteData());
|
||||
info.measurements = pattern->DataMeasurements();
|
||||
info.finalMeasurements = doc->GetFinalMeasurements();
|
||||
info.locale = QLocale(VAbstractApplication::VApp()->Settings()->GetLocale());
|
||||
info.labelDateFormat = doc->GetLabelDateFormat();
|
||||
info.LabelTimeFormat = doc->GetLabelTimeFormat();
|
||||
info.patternName = doc->GetPatternName();
|
||||
info.patternNumber = doc->GetPatternNumber();
|
||||
info.companyName = doc->GetCompanyName();
|
||||
info.measurementsUnits = VAbstractValApplication::VApp()->MeasurementsUnits();
|
||||
info.dimensionSizeUnits = VAbstractValApplication::VApp()->DimensionSizeUnits();
|
||||
info.measurementsPath = doc->MPath();
|
||||
info.placeholderTranslator = VAbstractApplication::VApp()->GetPlaceholderTranslator();
|
||||
info.measurementsType = VAbstractValApplication::VApp()->GetMeasurementsType();
|
||||
|
||||
if (info.measurementsType == MeasurementsType::Individual)
|
||||
{
|
||||
info.customerName = VAbstractValApplication::VApp()->GetCustomerName();
|
||||
info.customerBirthDate = VAbstractValApplication::VApp()->GetCustomerBirthDate();
|
||||
info.customerEmail = VAbstractValApplication::VApp()->CustomerEmail();
|
||||
}
|
||||
else
|
||||
{
|
||||
info.customerName = doc->GetCustomerName();
|
||||
info.customerBirthDate = doc->GetCustomerBirthDate();
|
||||
info.customerEmail = doc->GetCustomerEmail();
|
||||
}
|
||||
|
||||
info.dimensionHeight = QString::number(VAbstractValApplication::VApp()->GetDimensionHeight());
|
||||
info.dimensionSize = QString::number(VAbstractValApplication::VApp()->GetDimensionSize());
|
||||
info.dimensionHip = QString::number(VAbstractValApplication::VApp()->GetDimensionHip());
|
||||
info.dimensionWaist = QString::number(VAbstractValApplication::VApp()->GetDimensionWaist());
|
||||
info.dimensionHeightLabel = VAbstractValApplication::VApp()->GetDimensionHeightLabel();
|
||||
info.dimensionSizeLabel = VAbstractValApplication::VApp()->GetDimensionSizeLabel();
|
||||
info.dimensionHipLabel = VAbstractValApplication::VApp()->GetDimensionHipLabel();
|
||||
info.dimensionWaistLabel = VAbstractValApplication::VApp()->GetDimensionWaistLabel();
|
||||
info.patternMaterials = doc->GetPatternMaterials();
|
||||
if (!pieceLabel)
|
||||
{
|
||||
info.patternLabelTemplate = doc->GetPatternLabelTemplate();
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -38,13 +38,16 @@
|
|||
#include <QVector>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "../ifc/xml/vabstractpattern.h"
|
||||
#include "../vmisc/def.h"
|
||||
#include "../vmisc/defglobal.h"
|
||||
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
|
||||
#include "../vpatterndb/vcontainer.h"
|
||||
|
||||
class VPieceLabelData;
|
||||
class VAbstractPattern;
|
||||
class VContainer;
|
||||
class VSvgFont;
|
||||
class VMeasurement;
|
||||
class VTranslator;
|
||||
|
||||
/**
|
||||
* @brief The TextLine struct holds the information about one text line
|
||||
|
@ -65,6 +68,45 @@ private:
|
|||
static const quint16 classVersion;
|
||||
};
|
||||
|
||||
struct VPieceLabelInfo
|
||||
{
|
||||
explicit VPieceLabelInfo(const VContainer &data)
|
||||
: completeData(data)
|
||||
{
|
||||
}
|
||||
|
||||
QString pieceName{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
VPieceLabelData labelData{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QMap<QString, QSharedPointer<VMeasurement>> measurements{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
VContainer completeData; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QVector<VFinalMeasurement> finalMeasurements{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QLocale locale{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString labelDateFormat{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString LabelTimeFormat{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString patternName{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString patternNumber{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString companyName{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString customerName{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString customerEmail{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
Unit measurementsUnits{Unit::Cm}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
Unit dimensionSizeUnits{Unit::Cm}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString measurementsPath{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
MeasurementsType measurementsType{
|
||||
MeasurementsType::Individual}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QSharedPointer<VTranslator> placeholderTranslator{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QDate customerBirthDate{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionHeight{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionSize{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionHip{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionWaist{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionHeightLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionSizeLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionHipLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QString dimensionWaistLabel{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QMap<int, QString> patternMaterials{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
QVector<VLabelTemplateLine> patternLabelTemplate{}; // NOLINT(misc-non-private-member-variables-in-classes)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The VTextManager class this class is used to determine whether a collection of
|
||||
* text lines can fit into specified bounding box and with what font size
|
||||
|
@ -104,12 +146,14 @@ public:
|
|||
auto GetLabelSourceLines(int width, const QFont &font) const -> QVector<TextLine>;
|
||||
auto GetLabelSourceLines(int width, const VSvgFont &font, qreal penWidth) const -> QVector<TextLine>;
|
||||
|
||||
void Update(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern);
|
||||
void Update(VAbstractPattern *pDoc, const VContainer *pattern);
|
||||
void UpdatePieceLabelInfo(const VPieceLabelInfo &info);
|
||||
void UpdatePatternLabelInfo(const VPieceLabelInfo &info);
|
||||
|
||||
friend auto operator<<(QDataStream &dataStream, const VTextManager &data) -> QDataStream &;
|
||||
friend auto operator>>(QDataStream &dataStream, VTextManager &data) -> QDataStream &;
|
||||
|
||||
static auto PrepareLabelInfo(VAbstractPattern *doc, const VContainer *pattern, bool pieceLabel) -> VPieceLabelInfo;
|
||||
|
||||
private:
|
||||
QFont m_font{};
|
||||
QString m_svgFontFamily{};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
VLib {
|
||||
Depends { name: "Qt"; submodules: ["concurrent"] }
|
||||
Depends { name: "VMiscLib" }
|
||||
Depends { name: "IFCLib" }
|
||||
Depends { name: "VGeometryLib" }
|
||||
|
|
|
@ -115,8 +115,10 @@ DialogEditLabel::DialogEditLabel(const VAbstractPattern *doc, const VContainer *
|
|||
connect(ui->toolButtonBottom, &QToolButton::clicked, this,
|
||||
[this]() { DialogTool::MoveListRowBottom(ui->listWidgetEdit); });
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
InitPlaceholders();
|
||||
InitPlaceholdersMenu();
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
m_placeholdersMenu->setStyleSheet(QStringLiteral("QMenu { menu-scrollable: 1; }"));
|
||||
m_placeholdersMenu->setToolTipsVisible(true);
|
||||
|
@ -763,7 +765,7 @@ auto DialogEditLabel::GetTemplate() const -> QVector<VLabelTemplateLine>
|
|||
for (int i = 0; i < ui->listWidgetEdit->count(); ++i)
|
||||
{
|
||||
const QListWidgetItem *lineItem = ui->listWidgetEdit->item(i);
|
||||
if (lineItem)
|
||||
if (lineItem != nullptr)
|
||||
{
|
||||
VLabelTemplateLine line;
|
||||
line.line = lineItem->text();
|
||||
|
@ -815,6 +817,8 @@ void DialogEditLabel::SetTemplate(const QVector<VLabelTemplateLine> &lines)
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void DialogEditLabel::SetPiece(const VPiece &piece)
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
const VPieceLabelData &pieceData = piece.GetPieceLabelData();
|
||||
m_placeholders[pl_pLetter].second = pieceData.GetLetter();
|
||||
m_placeholders[pl_pAnnotation].second = pieceData.GetAnnotation();
|
||||
|
@ -862,6 +866,8 @@ void DialogEditLabel::SetPiece(const VPiece &piece)
|
|||
? throw VException(errorMsg)
|
||||
: qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
#include "toolsdef.h"
|
||||
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsView>
|
||||
#include <QKeyEvent>
|
||||
|
@ -1008,6 +1009,8 @@ void VToolSeamAllowance::Highlight(quint32 id)
|
|||
* @brief UpdateLabel updates the text label, making it just big enough for the text to fit it
|
||||
*/
|
||||
void VToolSeamAllowance::UpdateDetailLabel()
|
||||
{
|
||||
if (m_pieceUpdateInfoWatcher->isFinished())
|
||||
{
|
||||
VPiece detail = VAbstractTool::data.GetPiece(m_id);
|
||||
detail.SetPieceLabelData(detail.GetPieceLabelData()); // Refresh translation
|
||||
|
@ -1016,14 +1019,22 @@ void VToolSeamAllowance::UpdateDetailLabel()
|
|||
|
||||
if (labelData.IsVisible())
|
||||
{
|
||||
QPointF pos;
|
||||
qreal labelAngle = 0;
|
||||
m_pieceLabelPos = QPointF();
|
||||
m_pieceLabelAngle = 0;
|
||||
if (PrepareLabelData(labelData, pins, m_dataLabel, m_pieceLabelPos, m_pieceLabelAngle))
|
||||
{
|
||||
|
||||
if (PrepareLabelData(labelData, pins, m_dataLabel, pos, labelAngle))
|
||||
VPieceLabelInfo info = VTextManager::PrepareLabelInfo(doc, getData(), true);
|
||||
info.pieceName = detail.GetName();
|
||||
info.labelData = detail.GetPieceLabelData();
|
||||
|
||||
m_pieceLabelInfoStale = false;
|
||||
m_pieceUpdateInfoWatcher->setFuture(QtConcurrent::run(
|
||||
[this, info, detail]()
|
||||
{
|
||||
m_dataLabel->SetPieceName(detail.GetName());
|
||||
m_dataLabel->UpdateData(detail.GetName(), labelData, getData());
|
||||
UpdateLabelItem(m_dataLabel, pos, labelAngle);
|
||||
m_dataLabel->UpdatePieceLabelData(info);
|
||||
}));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1031,12 +1042,19 @@ void VToolSeamAllowance::UpdateDetailLabel()
|
|||
m_dataLabel->hide();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pieceLabelInfoStale = true;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief UpdatePatternInfo updates the pattern info label
|
||||
*/
|
||||
void VToolSeamAllowance::UpdatePatternInfo()
|
||||
{
|
||||
if (m_patternUpdateInfoWatcher->isFinished())
|
||||
{
|
||||
const VPiece detail = VAbstractTool::data.GetPiece(m_id);
|
||||
const VPatternLabelData &geom = detail.GetPatternLabelData();
|
||||
|
@ -1044,14 +1062,19 @@ void VToolSeamAllowance::UpdatePatternInfo()
|
|||
|
||||
if (geom.IsVisible())
|
||||
{
|
||||
QPointF pos;
|
||||
qreal labelAngle = 0;
|
||||
m_patternLabelPos = QPointF();
|
||||
m_patternLabelAngle = 0;
|
||||
if (PrepareLabelData(geom, pins, m_patternInfo, m_patternLabelPos, m_patternLabelAngle))
|
||||
{
|
||||
VPieceLabelInfo const info = VTextManager::PrepareLabelInfo(doc, getData(), false);
|
||||
|
||||
if (PrepareLabelData(geom, pins, m_patternInfo, pos, labelAngle))
|
||||
m_patternLabelInfoStale = false;
|
||||
m_patternUpdateInfoWatcher->setFuture(QtConcurrent::run(
|
||||
[this, info, detail]()
|
||||
{
|
||||
m_patternInfo->SetPieceName(detail.GetName());
|
||||
m_patternInfo->UpdateData(doc, getData());
|
||||
UpdateLabelItem(m_patternInfo, pos, labelAngle);
|
||||
m_patternInfo->UpdatePatternLabelData(info);
|
||||
}));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1059,6 +1082,11 @@ void VToolSeamAllowance::UpdatePatternInfo()
|
|||
m_patternInfo->hide();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_patternLabelInfoStale = true;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VToolSeamAllowance::UpdatePassmarks()
|
||||
|
@ -1672,8 +1700,13 @@ VToolSeamAllowance::VToolSeamAllowance(const VToolSeamAllowanceInitData &initDat
|
|||
m_mirrorLine(new QGraphicsPathItem(this)),
|
||||
m_foldLineMark(new QGraphicsPathItem(this)),
|
||||
m_foldLineLabel(new QGraphicsPathItem(this)),
|
||||
m_foldLineLabelText(new QGraphicsSimpleTextItem(this))
|
||||
m_foldLineLabelText(new QGraphicsSimpleTextItem(this)),
|
||||
m_patternUpdateInfoWatcher(new QFutureWatcher<void>(this)),
|
||||
m_pieceUpdateInfoWatcher(new QFutureWatcher<void>(this))
|
||||
{
|
||||
m_dataLabel->setVisible(false);
|
||||
m_patternInfo->setVisible(false);
|
||||
|
||||
VPiece const detail = initData.data->GetPiece(initData.id);
|
||||
ReinitInternals(detail, m_sceneDetails);
|
||||
VToolSeamAllowance::AllowSelecting(true);
|
||||
|
@ -1694,6 +1727,33 @@ VToolSeamAllowance::VToolSeamAllowance(const VToolSeamAllowanceInitData &initDat
|
|||
ConnectOutsideSignals();
|
||||
|
||||
m_foldLineMark->setBrush(Qt::SolidPattern);
|
||||
|
||||
connect(m_patternUpdateInfoWatcher, &QFutureWatcher<void>::finished, this,
|
||||
[this]()
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
|
||||
m_patternInfo->show();
|
||||
UpdateLabelItem(m_patternInfo, m_patternLabelPos, m_patternLabelAngle);
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||
if (m_patternLabelInfoStale)
|
||||
{
|
||||
m_patternLabelInfoStale = false;
|
||||
UpdatePatternInfo();
|
||||
}
|
||||
});
|
||||
connect(m_pieceUpdateInfoWatcher, &QFutureWatcher<void>::finished, this,
|
||||
[this]()
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
|
||||
m_dataLabel->show();
|
||||
UpdateLabelItem(m_dataLabel, m_pieceLabelPos, m_pieceLabelAngle);
|
||||
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||
if (m_pieceLabelInfoStale)
|
||||
{
|
||||
m_pieceLabelInfoStale = false;
|
||||
UpdateDetailLabel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -204,6 +204,18 @@ private:
|
|||
/** @brief m_geometryIsReady is true when a piece's geometry is ready and checks for validity can be enabled. */
|
||||
bool m_geometryIsReady{false};
|
||||
|
||||
QPointF m_patternLabelPos{};
|
||||
qreal m_patternLabelAngle{0};
|
||||
|
||||
QPointF m_pieceLabelPos{};
|
||||
qreal m_pieceLabelAngle{0};
|
||||
|
||||
QFutureWatcher<void> *m_patternUpdateInfoWatcher;
|
||||
QFutureWatcher<void> *m_pieceUpdateInfoWatcher;
|
||||
|
||||
bool m_patternLabelInfoStale{false};
|
||||
bool m_pieceLabelInfoStale{false};
|
||||
|
||||
explicit VToolSeamAllowance(const VToolSeamAllowanceInitData &initData, QGraphicsItem *parent = nullptr);
|
||||
|
||||
void UpdateExcludeState();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# File with common stuff for whole project
|
||||
include(../../../common.pri)
|
||||
|
||||
QT += core widgets xml printsupport svg
|
||||
QT += core widgets xml printsupport svg concurrent
|
||||
|
||||
# Name of the library
|
||||
TARGET = vtools
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
VLib {
|
||||
Depends { name: "Qt"; submodules: ["widgets", "xml", "svg"] }
|
||||
Depends { name: "Qt"; submodules: ["widgets", "xml", "svg", "concurrent"] }
|
||||
Depends { name: "IFCLib"; }
|
||||
Depends { name: "VLayoutLib"; }
|
||||
Depends { name: "VFormatLib"; }
|
||||
|
|
|
@ -293,22 +293,19 @@ auto VTextGraphicsItem::IsContained(QRectF rectBB, qreal dRot, qreal &dX, qreal
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief VTextGraphicsItem::UpdateData Updates the detail label
|
||||
* @param qsName name of detail
|
||||
* @param data reference to VPatternPieceData
|
||||
*/
|
||||
void VTextGraphicsItem::UpdateData(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern)
|
||||
void VTextGraphicsItem::UpdatePieceLabelData(const VPieceLabelInfo &info)
|
||||
{
|
||||
m_tm.Update(qsName, data, pattern);
|
||||
m_tm.UpdatePieceLabelInfo(info);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
/**
|
||||
* @brief VTextGraphicsItem::UpdateData Updates the pattern label
|
||||
* @param pDoc pointer to the pattern object
|
||||
*/
|
||||
void VTextGraphicsItem::UpdateData(VAbstractPattern *pDoc, const VContainer *pattern)
|
||||
void VTextGraphicsItem::UpdatePatternLabelData(const VPieceLabelInfo &info)
|
||||
{
|
||||
m_tm.Update(pDoc, pattern);
|
||||
m_tm.UpdatePatternLabelInfo(info);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -80,8 +80,8 @@ public:
|
|||
auto GetFontSize() const -> int;
|
||||
void SetSize(qreal fW, qreal fH);
|
||||
auto IsContained(QRectF rectBB, qreal dRot, qreal &dX, qreal &dY) const -> bool;
|
||||
void UpdateData(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern);
|
||||
void UpdateData(VAbstractPattern *pDoc, const VContainer *pattern);
|
||||
void UpdatePieceLabelData(const VPieceLabelInfo &info);
|
||||
void UpdatePatternLabelData(const VPieceLabelInfo &info);
|
||||
auto GetTextLines() const -> vsizetype;
|
||||
void SetPieceName(const QString &name);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# File with common stuff for whole project
|
||||
include(../../../common.pri)
|
||||
|
||||
QT += widgets printsupport
|
||||
QT += widgets printsupport xml
|
||||
|
||||
# Name of the library
|
||||
TARGET = vwidgets
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import qbs.Utilities
|
||||
|
||||
VLib {
|
||||
Depends { name: "Qt"; submodules: ["core", "widgets"] }
|
||||
Depends { name: "Qt"; submodules: ["core", "widgets", "xml"] }
|
||||
Depends { name: "VMiscLib" }
|
||||
Depends { name: "VPropertyExplorerLib" }
|
||||
Depends { name: "VPatternDBLib" }
|
||||
|
|
Loading…
Reference in New Issue
Block a user