Piece labels line break.

This commit is contained in:
Roman Telezhynskyi 2023-05-22 17:30:18 +03:00
parent 1dbd0c7c56
commit 7410d188ce
21 changed files with 516 additions and 179 deletions

View File

@ -28,6 +28,7 @@
- New notch type - Check Notch.
- Control a notch width and angle with formulas.
- Independent translation for piece labels.
- Piece labels line break.
# Valentina 0.7.52 September 12, 2022
- Fix crash when default locale is ru.

View File

@ -104,24 +104,12 @@ inline auto LineMatrix(const VPPiecePtr &piece, const QPointF &topLeft, qreal an
inline auto LineFont(const TextLine &tl, const QFont &base) -> QFont
{
QFont fnt = base;
fnt.setPixelSize(base.pixelSize() + tl.m_iFontSize);
fnt.setPointSize(base.pointSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
return fnt;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto LineText(const TextLine &tl, const QFontMetrics &fm, qreal width) -> QString
{
QString qsText = tl.m_qsText;
if (TextWidth(fm, qsText) > width)
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, static_cast<int>(width));
}
return qsText;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto LineAlign(const TextLine &tl, const QString &text, const QFontMetrics &fm, qreal width) -> qreal
{
@ -404,23 +392,31 @@ void VPGraphicsPiece::InitPieceLabel(const QVector<QPointF> &labelShape, const V
qreal dY = 0;
for (int i = 0; i < tm.GetSourceLinesCount(); ++i)
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont());
for (const auto &tl : labelLines)
{
const TextLine& tl = tm.GetSourceLine(i);
const QFont fnt = LineFont(tl, tm.GetFont());
const QFontMetrics fm(fnt);
if (m_textAsPaths)
{
dY += fm.height();
}
if (dY > dH)
if (dY > dH)
{
break;
}
}
else
{
break;
if (dY + fm.height() > dH)
{
break;
}
}
const QString qsText = LineText(tl, fm, dW);
const QString qsText = tl.m_qsText;
const qreal dX = LineAlign(tl, qsText, fm, dW);
// set up the rotation around top-left corner matrix
const QTransform lineMatrix = LineMatrix(piece, labelShape.at(0), angle, QPointF(dX, dY), maxLineWidth);

View File

@ -900,7 +900,8 @@ auto VPLayoutFileReader::ReadLabelLine() -> TextLine
QXmlStreamAttributes attribs = attributes();
line.m_iFontSize = ReadAttributeInt(attribs, ML::AttrFontSize, QString::number(MIN_FONT_SIZE));
line.m_iFontSize =
ReadAttributeInt(attribs, ML::AttrFontSize, QString::number(VCommonSettings::MinPieceLabelFontPointSize()));
line.m_bold = ReadAttributeBool(attribs, ML::AttrBold, falseStr);
line.m_italic = ReadAttributeBool(attribs, ML::AttrItalic, falseStr);
int alignment = ReadAttributeInt(attribs, ML::AttrAlignment, QString::number(static_cast<int>(Qt::AlignCenter)));

View File

@ -112,7 +112,19 @@ PreferencesPatternPage::PreferencesPatternPage(QWidget *parent)
ui->checkBoxSewLineOnDrawing->setChecked(settings->GetSewLineOnDrawing());
ui->doublePassmarkCheck->setChecked(settings->IsDoublePassmark());
ui->checkBoxHideMainPath->setChecked(settings->IsHideMainPath());
ui->fontComboBoxLabelFont->setCurrentFont(settings->GetLabelFont());
QFont labelFont = settings->GetLabelFont();
int pointSize = settings->GetPieceLabelFontPointSize();
labelFont.setPointSize(pointSize);
ui->fontComboBoxLabelFont->setCurrentFont(labelFont);
InitLabelFontSizes();
const qint32 indexSize = ui->comboBoxLabelFontSize->findData(pointSize);
if (indexSize != -1)
{
ui->comboBoxLabelFontSize->setCurrentIndex(indexSize);
}
ui->checkBoxRemeberPatternMaterials->setChecked(settings->IsRememberPatternMaterials());
m_knownMaterials = settings->GetKnownMaterials();
@ -167,6 +179,7 @@ auto PreferencesPatternPage::Apply() -> QStringList
settings->SetSewLineOnDrawing(ui->checkBoxSewLineOnDrawing->isChecked());
settings->SetHideMainPath(ui->checkBoxHideMainPath->isChecked());
settings->SetLabelFont(ui->fontComboBoxLabelFont->currentFont());
settings->SetPieceLabelFontPointSize(ui->comboBoxLabelFontSize->currentData().toInt());
if (settings->IsDoublePassmark() != ui->doublePassmarkCheck->isChecked())
{
@ -255,6 +268,21 @@ void PreferencesPatternPage::InitLabelDateTimeFormats()
connect(ui->pushButtonEditTimeFormats, &QPushButton::clicked, this, &PreferencesPatternPage::EditDateTimeFormats);
}
//---------------------------------------------------------------------------------------------------------------------
void PreferencesPatternPage::InitLabelFontSizes()
{
ui->comboBoxLabelFontSize->clear();
// Get the available font sizes
for (auto size : QFontDatabase::standardSizes())
{
if (size >= VCommonSettings::MinPieceLabelFontPointSize())
{
ui->comboBoxLabelFontSize->addItem(QString::number(size), size);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void PreferencesPatternPage::InitComboBoxFormats(QComboBox *box, const QStringList &items, const QString &currentFormat)
{

View File

@ -65,6 +65,7 @@ private:
Unit m_oldLineUnit{Unit::Mm};
void InitLabelDateTimeFormats();
void InitLabelFontSizes();
static void InitComboBoxFormats(QComboBox *box, const QStringList &items, const QString &currentFormat);
void InitUnits();
void RetranslateUi();

View File

@ -238,6 +238,29 @@ This option will take an affect after restart.</string>
<item>
<widget class="QFontComboBox" name="fontComboBoxLabelFont"/>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="comboBoxLabelFontSize"/>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>

View File

@ -2975,7 +2975,7 @@ void MainWindow::ToolBarTools()
connect(ui->actionIncreaseLabelFont, &QAction::triggered, this, [this]()
{
VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings();
settings->SetLabelFontSize(settings->GetLabelFontSize() + 1);
settings->SetPatternLabelFontSize(settings->GetPatternLabelFontSize() + 1);
if (m_sceneDraw)
{
m_sceneDraw->update();
@ -2996,7 +2996,7 @@ void MainWindow::ToolBarTools()
connect(ui->actionDecreaseLabelFont, &QAction::triggered, this, [this]()
{
VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings();
settings->SetLabelFontSize(settings->GetLabelFontSize() - 1);
settings->SetPatternLabelFontSize(settings->GetPatternLabelFontSize() - 1);
if (m_sceneDraw)
{
m_sceneDraw->update();
@ -3017,7 +3017,7 @@ void MainWindow::ToolBarTools()
connect(ui->actionOriginalLabelFont, &QAction::triggered, this, [this]()
{
VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings();
settings->SetLabelFontSize(VCommonSettings::GetDefLabelFontSize());
settings->SetPatternLabelFontSize(VCommonSettings::GetDefPatternLabelFontSize());
if (m_sceneDraw)
{
m_sceneDraw->update();

View File

@ -886,11 +886,15 @@ void VLayoutPiece::SetPieceText(const QString &qsName, const VPieceLabelData &da
// generate text
d->m_tmDetail.SetFont(font);
d->m_tmDetail.SetFontSize(data.GetFontSize());
int fntSize = data.GetFontSize();
if (fntSize == 0)
{
fntSize = VAbstractApplication::VApp()->Settings()->GetPieceLabelFontPointSize();
}
d->m_tmDetail.SetFontSize(fntSize);
d->m_tmDetail.Update(qsName, data, pattern);
// this will generate the lines of text
d->m_tmDetail.SetFontSize(data.GetFontSize());
d->m_tmDetail.FitFontSize(labelWidth, labelHeight);
}
//---------------------------------------------------------------------------------------------------------------------
@ -962,13 +966,15 @@ void VLayoutPiece::SetPatternInfo(VAbstractPattern *pDoc, const VPatternLabelDat
// Generate text
d->m_tmPattern.SetFont(font);
d->m_tmPattern.SetFontSize(geom.GetFontSize());
int fntSize = geom.GetFontSize();
if (fntSize == 0)
{
fntSize = VAbstractApplication::VApp()->Settings()->GetPieceLabelFontPointSize();
}
d->m_tmPattern.SetFontSize(fntSize);
d->m_tmPattern.Update(pDoc, pattern);
// generate lines of text
d->m_tmPattern.SetFontSize(geom.GetFontSize());
d->m_tmPattern.FitFontSize(labelWidth, labelHeight);
}
//---------------------------------------------------------------------------------------------------------------------
@ -1568,11 +1574,12 @@ void VLayoutPiece::CreateLabelStrings(QGraphicsItem *parent, const QVector<QPoin
const qreal angle = -QLineF(labelShape.at(0), labelShape.at(1)).angle();
qreal dY = 0;
for (int i = 0; i < tm.GetSourceLinesCount(); ++i)
const QVector<TextLine> labelLines = tm.GetLabelSourceLines(qFloor(dW), tm.GetFont());
for (const auto &tl : labelLines)
{
const TextLine &tl = tm.GetSourceLine(i);
QFont fnt = tm.GetFont();
fnt.setPixelSize(tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setPointSize(tm.GetFont().pointSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
@ -1581,19 +1588,21 @@ void VLayoutPiece::CreateLabelStrings(QGraphicsItem *parent, const QVector<QPoin
if (textAsPaths)
{
dY += fm.height();
}
if (dY > dH)
if (dY > dH)
{
break;
}
}
else
{
break;
if (dY + fm.height() > dH)
{
break;
}
}
QString qsText = tl.m_qsText;
if (TextWidth(fm, qsText) > dW)
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, static_cast<int>(dW));
}
qreal dX = 0;
if (tl.m_eAlign == 0 || (tl.m_eAlign & Qt::AlignLeft) > 0)
{

View File

@ -38,7 +38,9 @@
#include <QtMath>
#include "../ifc/xml/vabstractpattern.h"
#include "../vmisc/compatibility.h"
#include "../vmisc/vabstractvalapplication.h"
#include "../vmisc/vcommonsettings.h"
#include "../vpatterndb/floatItemData/vpiecelabeldata.h"
#if QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
@ -50,6 +52,49 @@
#include "../vpatterndb/vcontainer.h"
#include "vtextmanager.h"
namespace
{
auto SplitTextByWidth(const QString &text, const QFont &font, int maxWidth) -> QStringList
{
QFontMetrics fontMetrics(font);
if (TextWidth(fontMetrics, text) <= maxWidth)
{
return {text};
}
QStringList substrings;
substrings.reserve(2);
const int textLength = static_cast<int>(text.length());
int lineWidth = 0;
for (int endIndex = 0; endIndex < textLength; ++endIndex)
{
QChar currentChar = text.at(endIndex);
const int charWidth = TextWidth(fontMetrics, currentChar);
if (lineWidth + charWidth > maxWidth)
{
if (endIndex > 0)
{
substrings.append(text.mid(0, endIndex));
}
if (endIndex < textLength)
{
substrings.append(text.mid(endIndex));
}
break;
}
lineWidth += charWidth;
}
return substrings;
}
} // namespace
const quint32 TextLine::streamHeader = 0xA3881E49; // CRC-32Q string "TextLine"
const quint16 TextLine::classVersion = 1;
@ -487,7 +532,9 @@ auto VTextManager::GetFont() const -> const QFont &
*/
void VTextManager::SetFontSize(int iFS)
{
iFS < MIN_FONT_SIZE ? m_font.setPixelSize(MIN_FONT_SIZE) : m_font.setPixelSize(iFS);
iFS < VCommonSettings::MinPieceLabelFontPointSize()
? m_font.setPointSize(VCommonSettings::MinPieceLabelFontPointSize())
: m_font.setPointSize(iFS);
}
//---------------------------------------------------------------------------------------------------------------------
@ -525,6 +572,40 @@ auto VTextManager::GetSourceLine(vsizetype i) const -> const TextLine &
return m_liLines.at(i);
}
//---------------------------------------------------------------------------------------------------------------------
auto VTextManager::GetLabelSourceLines(int width, const QFont &font) const -> QVector<TextLine>
{
QVector<TextLine> lines;
lines.reserve(m_liLines.size());
QFont fnt = font;
int fSize = m_font.pointSize();
for (const auto &tl : m_liLines)
{
fnt.setPointSize(fSize + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QString qsText = tl.m_qsText;
QFontMetrics fm(fnt);
if (TextWidth(fm, qsText) > width)
{
const QStringList brokeLines = BreakTextIntoLines(qsText, fnt, width);
for (const auto &lineText : brokeLines)
{
TextLine line = tl;
line.m_qsText = lineText;
lines.append(line);
}
}
else
{
lines.append(tl);
}
}
return lines;
}
//---------------------------------------------------------------------------------------------------------------------
auto VTextManager::MaxLineWidth(int width) const -> int
{
@ -534,7 +615,7 @@ auto VTextManager::MaxLineWidth(int width) const -> int
const TextLine &tl = m_liLines.at(i);
QFont fnt = m_font;
fnt.setPixelSize(fnt.pixelSize() + tl.m_iFontSize);
fnt.setPointSize(fnt.pointSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
@ -553,64 +634,6 @@ auto VTextManager::MaxLineWidth(int width) const -> int
return maxWidth;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::FitFontSize sets the font size just big enough, so that the text fits into rectangle of
* size (fW, fH)
* @param fW rectangle width
* @param fH rectangle height
*/
void VTextManager::FitFontSize(qreal fW, qreal fH)
{
int iFS = 0;
if (GetSourceLinesCount() > 0)
{ // division by zero
iFS = 3 * qFloor(fH / static_cast<int>(GetSourceLinesCount())) / 4;
}
if (iFS < MIN_FONT_SIZE)
{
iFS = MIN_FONT_SIZE;
}
// get ratio between char width and height
int iMaxLen = 0;
TextLine maxLine;
QFont fnt;
for (vsizetype i = 0; i < GetSourceLinesCount(); ++i)
{
const TextLine &tl = GetSourceLine(i);
fnt = m_font;
fnt.setPixelSize(iFS + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QFontMetrics fm(fnt);
const int iTW = TextWidth(fm, tl.m_qsText);
if (iTW > iMaxLen)
{
iMaxLen = iTW;
maxLine = tl;
}
}
if (iMaxLen > fW)
{
QFont fnt = m_font;
fnt.setBold(maxLine.m_bold);
fnt.setItalic(maxLine.m_italic);
int lineLength = 0;
do
{
--iFS;
fnt.setPixelSize(iFS + maxLine.m_iFontSize);
QFontMetrics fm(fnt);
lineLength = TextWidth(fm, maxLine.m_qsText);
} while (lineLength > fW && iFS > MIN_FONT_SIZE);
}
SetFontSize(iFS);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextManager::Update updates the text lines with detail data
@ -665,3 +688,93 @@ void VTextManager::Update(VAbstractPattern *pDoc, const VContainer *pattern)
m_liLines = *m_patternLabelLinesCache;
}
//---------------------------------------------------------------------------------------------------------------------
auto VTextManager::BreakTextIntoLines(const QString &text, const QFont &font, int maxWidth) const -> QStringList
{
QFontMetrics fontMetrics(font);
QStringList words = text.split(' ');
QString currentLine;
int currentLineWidth = 0;
const int spaceWidth = TextWidth(fontMetrics, QChar(' '));
const float tolerance = 0.3F;
QStringList lines;
lines.reserve(words.size());
QMutableListIterator<QString> iterator(words);
auto AppendWord = [&currentLine, &currentLineWidth](const QString &word, int totalWidth)
{
if (!currentLine.isEmpty())
{
currentLine += QChar(' ');
}
currentLine += word;
currentLineWidth = totalWidth;
};
while (iterator.hasNext())
{
const QString &word = iterator.next();
int wordWidth = TextWidth(fontMetrics, word);
int totalWidth = !currentLine.isEmpty() ? currentLineWidth + spaceWidth + wordWidth : wordWidth;
if (totalWidth <= maxWidth)
{
// Append the word to the current line
AppendWord(word, totalWidth);
}
else if ((maxWidth - currentLineWidth) <= qRound(static_cast<float>(maxWidth) * tolerance) &&
maxWidth >= wordWidth)
{
// Start a new line with the word if it doesn't exceed the tolerance
lines.append(currentLine);
currentLine = word;
currentLineWidth = wordWidth;
}
else
{
// Word is too long, force line break
if (currentLineWidth + spaceWidth + TextWidth(fontMetrics, word.at(0)) > maxWidth)
{
lines.append(currentLine);
currentLine.clear();
currentLineWidth = 0;
}
const int subWordWidth = !currentLine.isEmpty() ? maxWidth - (currentLineWidth + spaceWidth) : maxWidth;
const QStringList subWords = SplitTextByWidth(word, font, subWordWidth);
if (subWords.isEmpty() || subWords.size() > 2)
{
AppendWord(word, totalWidth);
}
else
{
const int width = TextWidth(fontMetrics, ConstFirst(subWords));
const int tWidth = !currentLine.isEmpty() ? currentLineWidth + spaceWidth + width : width;
AppendWord(ConstFirst(subWords), tWidth);
lines.append(currentLine);
if (subWords.size() == 2)
{
currentLine.clear();
currentLineWidth = 0;
// Insert the item after the current item
iterator.insert(ConstLast(subWords));
iterator.previous();
}
}
}
}
// Add the last line
if (!currentLine.isEmpty())
{
lines.append(currentLine);
}
return lines;
}

View File

@ -45,16 +45,13 @@ class VPieceLabelData;
class VAbstractPattern;
class VContainer;
#define MIN_FONT_SIZE 5
#define MAX_FONT_SIZE 128
/**
* @brief The TextLine struct holds the information about one text line
*/
struct TextLine
{
QString m_qsText{};
int m_iFontSize{MIN_FONT_SIZE}; // 0 means default
int m_iFontSize{0}; // 0 means default
bool m_bold{false};
bool m_italic{false};
Qt::Alignment m_eAlign{Qt::AlignCenter};
@ -92,13 +89,14 @@ public:
void SetFont(const QFont &font);
auto GetFont() const -> const QFont &;
void SetFontSize(int iFS);
void FitFontSize(qreal fW, qreal fH);
auto GetAllSourceLines() const -> QVector<TextLine>;
void SetAllSourceLines(const QVector<TextLine> &lines);
auto GetSourceLinesCount() const -> vsizetype;
auto GetSourceLine(vsizetype i) const -> const TextLine &;
auto GetLabelSourceLines(int width, const QFont &font) const -> QVector<TextLine>;
auto MaxLineWidth(int width) const -> int;
void Update(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern);
@ -113,6 +111,8 @@ private:
static const quint32 streamHeader;
static const quint16 classVersion;
auto BreakTextIntoLines(const QString &text, const QFont &font, int maxWidth) const -> QStringList;
};
#endif // VTEXTMANAGER_H

View File

@ -129,6 +129,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingDoublePassmark, (QLatin1String("
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternDefaultSeamAllowance,
(QLatin1String("pattern/defaultSeamAllowance"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternLabelFont, (QLatin1String("pattern/labelFont"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPieceLabelFontPointSize, // NOLINT
(QLatin1String("pattern/pieceLabelFontPointSize")))
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternLineWidth, (QLatin1String("pattern/lineWidth"))) // NOLINT
Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternCurveApproximationScale,
(QLatin1String("pattern/curveApproximationScale"))) // NOLINT
@ -1188,15 +1190,49 @@ void VCommonSettings::SetLabelFont(const QFont &f)
}
//---------------------------------------------------------------------------------------------------------------------
auto VCommonSettings::GetLabelFontSize() const -> int
auto VCommonSettings::GetPieceLabelFontPointSize() const -> int
{
bool ok = false;
int val = value(*settingPieceLabelFontPointSize, VCommonSettings::MinPieceLabelFontPointSize()).toInt(&ok);
if (not ok)
{
qDebug() << "Could not convert value"
<< value(*settingPieceLabelFontPointSize, VCommonSettings::MinPieceLabelFontPointSize())
<< "to int. Return default value for label font size.";
val = 12;
}
else
{
if (val < VCommonSettings::MinPieceLabelFontPointSize())
{
return VCommonSettings::MinPieceLabelFontPointSize();
}
}
return val;
}
//---------------------------------------------------------------------------------------------------------------------
void VCommonSettings::SetPieceLabelFontPointSize(int size)
{
setValue(*settingPieceLabelFontPointSize, size);
}
//---------------------------------------------------------------------------------------------------------------------
auto VCommonSettings::MinPieceLabelFontPointSize() -> int
{
return 5;
}
//---------------------------------------------------------------------------------------------------------------------
auto VCommonSettings::GetPatternLabelFontSize() const -> int
{
if (labelFontSizeCached <= 0)
{
bool ok = false;
labelFontSizeCached = value(*settingPatternLabelFontSize, GetDefLabelFontSize()).toInt(&ok);
labelFontSizeCached = value(*settingPatternLabelFontSize, GetDefPatternLabelFontSize()).toInt(&ok);
if (not ok)
{
labelFontSizeCached = GetDefLabelFontSize();
labelFontSizeCached = GetDefPatternLabelFontSize();
}
labelFontSizeCached = qBound(minLabelFontSize, labelFontSizeCached, maxLabelFontSize);
}
@ -1204,7 +1240,7 @@ auto VCommonSettings::GetLabelFontSize() const -> int
}
//---------------------------------------------------------------------------------------------------------------------
void VCommonSettings::SetLabelFontSize(int size)
void VCommonSettings::SetPatternLabelFontSize(int size)
{
size = qBound(minLabelFontSize, size, maxLabelFontSize);
setValue(*settingPatternLabelFontSize, size);
@ -1212,7 +1248,7 @@ void VCommonSettings::SetLabelFontSize(int size)
}
//---------------------------------------------------------------------------------------------------------------------
auto VCommonSettings::GetDefLabelFontSize() -> int
auto VCommonSettings::GetDefPatternLabelFontSize() -> int
{
return 32;
}

View File

@ -213,9 +213,13 @@ public:
auto GetLabelFont() const -> QFont;
void SetLabelFont(const QFont &f);
auto GetLabelFontSize() const -> int;
void SetLabelFontSize(int size);
static auto GetDefLabelFontSize() -> int;
auto GetPieceLabelFontPointSize() const -> int;
void SetPieceLabelFontPointSize(int size);
static auto MinPieceLabelFontPointSize() -> int;
auto GetPatternLabelFontSize() const -> int;
void SetPatternLabelFontSize(int size);
static auto GetDefPatternLabelFontSize() -> int;
auto GetHideLabels() const -> bool;
void SetHideLabels(bool value);

View File

@ -363,6 +363,11 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
uiTabLabels->checkBoxFold->setChecked(ppData.IsOnFold());
m_templateLines = ppData.GetLabelTemplate();
{
const int piceFontSizeIndex = uiTabLabels->comboBoxPieceLabelSize->findData(ppData.GetFontSize());
uiTabLabels->comboBoxPieceLabelSize->setCurrentIndex(piceFontSizeIndex != -1 ? piceFontSizeIndex : 0);
}
uiTabLabels->groupBoxDetailLabel->setEnabled(not m_templateLines.isEmpty());
int index = uiTabGrainline->comboBoxArrow->findData(static_cast<int>(piece.GetGrainlineGeometry().GetArrowType()));
@ -390,6 +395,11 @@ void DialogSeamAllowance::SetPiece(const VPiece &piece)
SetPLHeight(patternInfo.GetLabelHeight());
SetPLAngle(patternInfo.GetRotation());
{
const int patternFontSizeIndex = uiTabLabels->comboBoxPatternLabelSize->findData(patternInfo.GetFontSize());
uiTabLabels->comboBoxPatternLabelSize->setCurrentIndex(patternFontSizeIndex != -1 ? patternFontSizeIndex : 0);
}
const VGrainlineData &grainlineGeometry = piece.GetGrainlineGeometry();
uiTabGrainline->groupBoxGrainline->setChecked(grainlineGeometry.IsVisible());
ChangeCurrentData(uiTabGrainline->comboBoxGrainlineCenterPin, grainlineGeometry.CenterPin());
@ -2725,6 +2735,7 @@ auto DialogSeamAllowance::CreatePiece() const -> VPiece
piece.GetPieceLabelData().SetLabelTemplate(m_templateLines);
piece.GetPieceLabelData().SetRotation(GetFormulaFromUser(uiTabLabels->lineEditDLAngleFormula));
piece.GetPieceLabelData().SetVisible(uiTabLabels->groupBoxDetailLabel->isChecked());
piece.GetPieceLabelData().SetFontSize(uiTabLabels->comboBoxPieceLabelSize->currentData().toInt());
if (not flagDPin)
{
@ -2745,6 +2756,7 @@ auto DialogSeamAllowance::CreatePiece() const -> VPiece
piece.GetPatternLabelData().SetVisible(uiTabLabels->groupBoxPatternLabel->isChecked());
piece.GetPatternLabelData().SetRotation(GetFormulaFromUser(uiTabLabels->lineEditPLAngleFormula));
piece.GetPatternLabelData().SetFontSize(uiTabLabels->comboBoxPatternLabelSize->currentData().toInt());
if (not flagPPin)
{
@ -3387,6 +3399,9 @@ void DialogSeamAllowance::InitPatternPieceDataTab()
//---------------------------------------------------------------------------------------------------------------------
void DialogSeamAllowance::InitLabelsTab()
{
InitLabelFontSize(uiTabLabels->comboBoxPatternLabelSize);
InitLabelFontSize(uiTabLabels->comboBoxPieceLabelSize);
uiTabLabels->lineEditDLWidthFormula->setPlainText(m_defLabelValue);
uiTabLabels->lineEditDLHeightFormula->setPlainText(m_defLabelValue);
uiTabLabels->lineEditPLWidthFormula->setPlainText(m_defLabelValue);
@ -3665,6 +3680,23 @@ void DialogSeamAllowance::InitAllPinComboboxes()
InitPinPoint(uiTabLabels->comboBoxPLBottomRightPin);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogSeamAllowance::InitLabelFontSize(QComboBox *box)
{
SCASSERT(box != nullptr);
box->clear();
box->addItem(tr("Default"), 0);
// Get the available font sizes
for (auto size : QFontDatabase::standardSizes())
{
if (size >= VCommonSettings::MinPieceLabelFontPointSize())
{
box->addItem(QString::number(size), size);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
auto DialogSeamAllowance::GetFormulaSAWidth() const -> QString
{

View File

@ -301,6 +301,7 @@ private:
void InitPassmarksTab();
void InitPlaceLabelsTab();
void InitAllPinComboboxes();
void InitLabelFontSize(QComboBox *box);
void SetFormulaSAWidth(const QString &formula);
void SetFormulaPassmarkLength(const QString &formula);

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>628</width>
<height>516</height>
<width>550</width>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
@ -28,8 +28,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>608</width>
<height>496</height>
<width>530</width>
<height>514</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -455,7 +455,28 @@
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QFormLayout" name="formLayout_8">
<item row="0" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Font size:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxPieceLabelSize"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item alignment="Qt::AlignLeft">
@ -987,7 +1008,7 @@
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<item>
<widget class="QLabel" name="labelDLAngle">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
@ -1112,7 +1133,28 @@
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_14">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QFormLayout" name="formLayout_13">
<item row="0" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Font size:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxPatternLabelSize"/>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_25">
<item alignment="Qt::AlignLeft">

View File

@ -505,7 +505,8 @@ void VToolSeamAllowance::AddPatternPieceData(VAbstractPattern *doc, QDomElement
doc->SetAttribute(domData, AttrMy, data.GetPos().y());
doc->SetAttribute(domData, AttrWidth, data.GetLabelWidth());
doc->SetAttribute(domData, AttrHeight, data.GetLabelHeight());
doc->SetAttribute(domData, AttrFont, data.GetFontSize());
doc->SetAttributeOrRemoveIf<int>(domData, AttrFont, data.GetFontSize(),
[](int size) noexcept { return size == 0; });
doc->SetAttribute(domData, VAbstractPattern::AttrRotation, data.GetRotation());
doc->SetAttributeOrRemoveIf<quint32>(domData, AttrCenterPin, data.CenterPin(),
[](quint32 pin) noexcept { return pin == NULL_ID; });
@ -528,7 +529,8 @@ void VToolSeamAllowance::AddPatternInfo(VAbstractPattern *doc, QDomElement &domE
doc->SetAttribute(domData, AttrMy, geom.GetPos().y());
doc->SetAttribute(domData, AttrWidth, geom.GetLabelWidth());
doc->SetAttribute(domData, AttrHeight, geom.GetLabelHeight());
doc->SetAttribute(domData, AttrFont, geom.GetFontSize());
doc->SetAttributeOrRemoveIf<int>(domData, AttrFont, geom.GetFontSize(),
[](int size) noexcept { return size == 0; });
doc->SetAttribute(domData, VAbstractPattern::AttrRotation, geom.GetRotation());
doc->SetAttributeOrRemoveIf<quint32>(domData, AttrCenterPin, geom.CenterPin(),
[](quint32 pin) noexcept { return pin <= NULL_ID; });
@ -767,6 +769,7 @@ void VToolSeamAllowance::UpdateDetailLabel()
if (PrepareLabelData(labelData, pins, m_dataLabel, pos, labelAngle))
{
m_dataLabel->SetPieceName(detail.GetName());
m_dataLabel->UpdateData(detail.GetName(), labelData, getData());
UpdateLabelItem(m_dataLabel, pos, labelAngle);
}
@ -794,6 +797,7 @@ void VToolSeamAllowance::UpdatePatternInfo()
if (PrepareLabelData(geom, pins, m_patternInfo, pos, labelAngle))
{
m_patternInfo->SetPieceName(detail.GetName());
m_patternInfo->UpdateData(doc, getData());
UpdateLabelItem(m_patternInfo, pos, labelAngle);
}
@ -872,7 +876,7 @@ void VToolSeamAllowance::SaveMoveDetail(const QPointF &ptPos)
/**
* @brief SaveResizeDetail saves the resize detail label operation to the undo stack
*/
void VToolSeamAllowance::SaveResizeDetail(qreal dLabelW, int iFontSize)
void VToolSeamAllowance::SaveResizeDetail(qreal dLabelW)
{
VPiece oldDet = VAbstractTool::data.GetPiece(m_id);
VPiece newDet = oldDet;
@ -881,7 +885,6 @@ void VToolSeamAllowance::SaveResizeDetail(qreal dLabelW, int iFontSize)
newDet.GetPieceLabelData().SetLabelWidth(QString().setNum(dLabelW));
const qreal height = FromPixel(m_dataLabel->boundingRect().height(), *VDataTool::data.GetPatternUnit());
newDet.GetPieceLabelData().SetLabelHeight(QString().setNum(height));
newDet.GetPieceLabelData().SetFontSize(iFontSize);
auto *resizeCommand = new SavePieceOptions(oldDet, newDet, doc, m_id);
resizeCommand->setText(tr("resize pattern piece label"));
@ -928,7 +931,7 @@ void VToolSeamAllowance::SaveMovePattern(const QPointF &ptPos)
/**
* @brief: SaveResizePattern saves the pattern label width and font size
*/
void VToolSeamAllowance::SaveResizePattern(qreal dLabelW, int iFontSize)
void VToolSeamAllowance::SaveResizePattern(qreal dLabelW)
{
VPiece oldDet = VAbstractTool::data.GetPiece(m_id);
VPiece newDet = oldDet;
@ -937,7 +940,6 @@ void VToolSeamAllowance::SaveResizePattern(qreal dLabelW, int iFontSize)
newDet.GetPatternLabelData().SetLabelWidth(QString().setNum(dLabelW));
qreal height = FromPixel(m_patternInfo->boundingRect().height(), *VDataTool::data.GetPatternUnit());
newDet.GetPatternLabelData().SetLabelHeight(QString().setNum(height));
newDet.GetPatternLabelData().SetFontSize(iFontSize);
auto *resizeCommand = new SavePieceOptions(oldDet, newDet, doc, m_id);
resizeCommand->setText(tr("resize pattern info label"));
@ -1372,8 +1374,8 @@ VToolSeamAllowance::VToolSeamAllowance(const VToolSeamAllowanceInitData &initDat
m_sceneDetails(initData.scene),
m_drawName(initData.drawName),
m_seamAllowance(new VNoBrushScalePathItem(this)),
m_dataLabel(new VTextGraphicsItem(this)),
m_patternInfo(new VTextGraphicsItem(this)),
m_dataLabel(new VTextGraphicsItem(VTextGraphicsItem::ItemType::PieceLabel, this)),
m_patternInfo(new VTextGraphicsItem(VTextGraphicsItem::ItemType::PatternLabel, this)),
m_grainLine(new VGrainlineItem(this)),
m_passmarks(new QGraphicsPathItem(this)),
m_placeLabels(new QGraphicsPathItem(this))
@ -2116,10 +2118,12 @@ auto VToolSeamAllowance::PrepareLabelData(const VPatternLabelData &labelData, co
}
labelItem->SetMoveType(type);
QFont fnt = VAbstractApplication::VApp()->Settings()->GetLabelFont();
VCommonSettings *settings = VAbstractApplication::VApp()->Settings();
QFont fnt = settings->GetLabelFont();
{
const int iFS = labelData.GetFontSize();
iFS < MIN_FONT_SIZE ? fnt.setPixelSize(MIN_FONT_SIZE) : fnt.setPixelSize(iFS);
iFS < VCommonSettings::MinPieceLabelFontPointSize() ? fnt.setPointSize(settings->GetPieceLabelFontPointSize())
: fnt.setPointSize(iFS);
}
labelItem->SetFont(fnt);
labelItem->SetSize(ToPixel(labelWidth, *VDataTool::data.GetPatternUnit()),

View File

@ -136,10 +136,10 @@ public slots:
protected slots:
void UpdateGrainline();
void SaveMoveDetail(const QPointF &ptPos);
void SaveResizeDetail(qreal dLabelW, int iFontSize);
void SaveResizeDetail(qreal dLabelW);
void SaveRotationDetail(qreal dRot);
void SaveMovePattern(const QPointF &ptPos);
void SaveResizePattern(qreal dLabelW, int iFontSize);
void SaveResizePattern(qreal dLabelW);
void SaveRotationPattern(qreal dRot);
void SaveMoveGrainline(const QPointF &ptPos);
void SaveResizeGrainline(qreal dLength);

View File

@ -92,9 +92,9 @@ void VGraphicsSimpleTextItem::paint(QPainter *painter, const QStyleOptionGraphic
};
QFont font = this->font();
if (font.pointSize() != VAbstractApplication::VApp()->Settings()->GetLabelFontSize())
if (font.pointSize() != VAbstractApplication::VApp()->Settings()->GetPatternLabelFontSize())
{
font.setPointSize(VAbstractApplication::VApp()->Settings()->GetLabelFontSize());
font.setPointSize(VAbstractApplication::VApp()->Settings()->GetPatternLabelFontSize());
setFont(font);
}
@ -373,8 +373,8 @@ void VGraphicsSimpleTextItem::Init()
this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
this->setAcceptHoverEvents(true);
QFont font = this->font();
font.setPointSize(VAbstractApplication::VApp()->Settings()->GetLabelFontSize());
font.setPointSize(VAbstractApplication::VApp()->Settings()->GetPatternLabelFontSize());
setFont(font);
m_oldScale = minVisibleFontSize / VAbstractApplication::VApp()->Settings()->GetLabelFontSize();
m_oldScale = minVisibleFontSize / VAbstractApplication::VApp()->Settings()->GetPatternLabelFontSize();
setScale(m_oldScale);
}

View File

@ -82,8 +82,8 @@ void VScenePoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio
painter->drawEllipse(PointRect(accuracyPointOnLine));
painter->restore();
}
if (settings->GetLabelFontSize()*scale < minVisibleFontSize || settings->GetHideLabels())
if (settings->GetPatternLabelFontSize()*scale < minVisibleFontSize || settings->GetHideLabels())
{
m_namePoint->setVisible(false);
m_lineName->setVisible(false);

View File

@ -39,9 +39,10 @@
#include <QStyleOptionGraphicsItem>
#include <Qt>
#include "../vmisc/compatibility.h"
#include "../ifc/exception/vexception.h"
#include "../vmisc/def.h"
#include "../vmisc/literals.h"
#include "../vmisc/vabstractvalapplication.h"
#include "vtextgraphicsitem.h"
namespace
@ -116,8 +117,9 @@ auto GetBoundingRect(const QRectF &rectBB, qreal dRot) -> QRectF
* @brief VTextGraphicsItem::VTextGraphicsItem constructor
* @param pParent pointer to the parent item
*/
VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem *pParent)
: VPieceItem(pParent)
VTextGraphicsItem::VTextGraphicsItem(ItemType type, QGraphicsItem *pParent)
: VPieceItem(pParent),
m_itemType(type)
{
m_inactiveZ = 2;
SetSize(minW, minH);
@ -147,38 +149,9 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
Q_UNUSED(option)
painter->fillRect(m_rectBoundingBox, QColor(251, 251, 175, 128 /*50% opacity*/));
painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter->setPen(Qt::black);
QFont fnt = m_tm.GetFont();
int iW = qFloor(boundingRect().width());
// draw text lines
int iY = 0;
for (int i = 0; i < m_tm.GetSourceLinesCount(); ++i)
{
const TextLine &tl = m_tm.GetSourceLine(i);
fnt.setPixelSize(m_tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QString qsText = tl.m_qsText;
QFontMetrics fm(fnt);
// check if the next line will go out of bounds
if (iY + fm.height() > boundingRect().height())
{
break;
}
if (TextWidth(fm, qsText) > iW)
{
qsText = fm.elidedText(qsText, Qt::ElideMiddle, iW);
}
painter->setFont(fnt);
painter->drawText(0, iY, iW, fm.height(), static_cast<int>(tl.m_eAlign), qsText);
iY += fm.height() + m_tm.GetSpacing();
}
PaintLabel(painter);
// now draw the features specific to non-normal modes
if (m_eMode != mNormal)
@ -329,6 +302,12 @@ auto VTextGraphicsItem::GetTextLines() const -> vsizetype
return m_tm.GetSourceLinesCount();
}
//---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::SetPieceName(const QString &name)
{
m_pieceName = name;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VTextGraphicsItem::GetFontSize returns the currently used text base font size
@ -496,7 +475,7 @@ void VTextGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *pME)
}
else if (m_moveType & IsResizable)
{
emit SignalResized(m_rectBoundingBox.width(), m_tm.GetFont().pixelSize());
emit SignalResized(m_rectBoundingBox.width());
Update();
}
}
@ -573,7 +552,6 @@ void VTextGraphicsItem::CorrectLabel()
// put the label inside the pattern
setPos(pos().x() + dX, pos().y() + dY);
}
m_tm.FitFontSize(m_rectBoundingBox.width(), m_rectBoundingBox.height());
UpdateBox();
}
@ -724,3 +702,59 @@ void VTextGraphicsItem::RotateLabel(QGraphicsSceneMouseEvent *pME)
Update();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::PaintLabel(QPainter *painter)
{
const QRectF boundingRect = this->boundingRect();
const int iW = qFloor(boundingRect.width());
QFont fnt = m_tm.GetFont();
const QVector<TextLine> labelLines = m_tm.GetLabelSourceLines(iW, fnt);
// draw text lines
int iY = 0;
for (const auto &tl : labelLines)
{
fnt.setPointSize(m_tm.GetFont().pointSize() + tl.m_iFontSize);
fnt.setBold(tl.m_bold);
fnt.setItalic(tl.m_italic);
QString qsText = tl.m_qsText;
QFontMetrics fm(fnt);
int lineHeight = fm.height();
if (iY + fm.height() > boundingRect.height())
{
lineHeight = qFloor(boundingRect.height()) - iY;
}
painter->setFont(fnt);
painter->drawText(0, iY, iW, lineHeight, static_cast<int>(tl.m_eAlign), qsText);
// check if the next line will go out of bounds
if (iY + fm.height() > boundingRect.height())
{
QString errorMsg;
switch (m_itemType)
{
case PatternLabel:
errorMsg = tr("Piece '%1'. Not enough space for pattern info label.").arg(m_pieceName);
break;
case PieceLabel:
errorMsg = tr("Piece '%1'. Not enough space for piece info label.").arg(m_pieceName);
break;
case Unknown:
default:
errorMsg = tr("Piece '%1'. Not enough space for label.").arg(m_pieceName);
break;
};
VAbstractApplication::VApp()->IsPedantic()
? throw VException(errorMsg)
: qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg;
break;
}
iY += fm.height() + m_tm.GetSpacing();
}
}

View File

@ -53,7 +53,14 @@ class VTextGraphicsItem final : public VPieceItem
Q_OBJECT // NOLINT
public:
explicit VTextGraphicsItem(QGraphicsItem *pParent = nullptr);
enum ItemType
{
PatternLabel,
PieceLabel,
Unknown
};
explicit VTextGraphicsItem(ItemType type, QGraphicsItem *pParent = nullptr);
~VTextGraphicsItem() override = default;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
@ -72,6 +79,7 @@ public:
void UpdateData(const QString &qsName, const VPieceLabelData &data, const VContainer *pattern);
void UpdateData(VAbstractPattern *pDoc, const VContainer *pattern);
auto GetTextLines() const -> vsizetype;
void SetPieceName(const QString &name);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *pME) override;
@ -84,7 +92,7 @@ protected:
void CorrectLabel();
signals:
void SignalResized(qreal iTW, int iFontSize);
void SignalResized(qreal iTW);
void SignalRotated(qreal dAng);
void SignalShrink();
@ -97,6 +105,8 @@ private:
double m_dAngle{0};
QRectF m_rectResize{};
VTextManager m_tm{};
QString m_pieceName{};
ItemType m_itemType{Unknown};
void AllUserModifications(const QPointF &pos);
void UserRotateAndMove();
@ -105,6 +115,8 @@ private:
void MoveLabel(QGraphicsSceneMouseEvent *pME);
void ResizeLabel(QGraphicsSceneMouseEvent *pME);
void RotateLabel(QGraphicsSceneMouseEvent *pME);
void PaintLabel(QPainter *painter);
};
#endif // VTEXTGRAPHICSITEM_H