Refactored the text managing in labels

--HG--
branch : feature
This commit is contained in:
BojanKverh 2016-07-18 22:30:14 +02:00
parent 363714985c
commit c9ee648cb8
5 changed files with 176 additions and 96 deletions

View file

@ -51,7 +51,8 @@ HEADERS += \
$$PWD/drawTools/toolcurve/vtoolcubicbezier.h \ $$PWD/drawTools/toolcurve/vtoolcubicbezier.h \
$$PWD/drawTools/toolcurve/vtoolcubicbezierpath.h \ $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.h \
$$PWD/drawTools/operation/vtoolrotation.h \ $$PWD/drawTools/operation/vtoolrotation.h \
$$PWD/vtextgraphicsitem.h $$PWD/vtextgraphicsitem.h \
$$PWD/vtextmanager.h
SOURCES += \ SOURCES += \
$$PWD/vtooldetail.cpp \ $$PWD/vtooldetail.cpp \
@ -100,4 +101,5 @@ SOURCES += \
$$PWD/drawTools/toolcurve/vtoolcubicbezier.cpp \ $$PWD/drawTools/toolcurve/vtoolcubicbezier.cpp \
$$PWD/drawTools/toolcurve/vtoolcubicbezierpath.cpp \ $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.cpp \
$$PWD/drawTools/operation/vtoolrotation.cpp \ $$PWD/drawTools/operation/vtoolrotation.cpp \
$$PWD/vtextgraphicsitem.cpp $$PWD/vtextgraphicsitem.cpp \
$$PWD/vtextmanager.cpp

View file

@ -44,23 +44,13 @@
#define ROTATE_ARC 50 #define ROTATE_ARC 50
#define MIN_W 120 #define MIN_W 120
#define MIN_H 60 #define MIN_H 60
#define MIN_FONT_SIZE 12
#define MAX_FONT_SIZE 128
#define SPACING 2
#define TOP_Z 2 #define TOP_Z 2
//---------------------------------------------------------------------------------------------------------------------
TextLine::TextLine()
:m_qsText(), m_iFontSize(MIN_FONT_SIZE), m_eFontWeight(QFont::Normal), m_eStyle(QFont::StyleNormal),
m_eAlign(Qt::AlignCenter), m_iHeight(0)
{}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent) VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent)
:QGraphicsObject(pParent), m_eMode(VTextGraphicsItem::mNormal), m_bReleased(false), :QGraphicsObject(pParent), m_eMode(VTextGraphicsItem::mNormal), m_bReleased(false),
m_ptStartPos(), m_ptStart(), m_ptRotCenter(), m_szStart(), m_dRotation(0), m_dAngle(0), m_ptStartPos(), m_ptStart(), m_ptRotCenter(), m_szStart(), m_dRotation(0), m_dAngle(0),
m_rectResize(), m_iMinH(MIN_H), m_rectBoundingBox(), m_font(), m_liLines(), m_liOutput() m_rectResize(), m_iMinH(MIN_H), m_rectBoundingBox(), m_tm()
{ {
m_rectBoundingBox.setTopLeft(QPointF(0, 0)); m_rectBoundingBox.setTopLeft(QPointF(0, 0));
SetSize(MIN_W, m_iMinH); SetSize(MIN_W, m_iMinH);
@ -74,7 +64,7 @@ VTextGraphicsItem::~VTextGraphicsItem()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::SetFont(const QFont& fnt) void VTextGraphicsItem::SetFont(const QFont& fnt)
{ {
m_font = fnt; m_tm.SetFont(fnt);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -88,17 +78,17 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
int iY = 0; int iY = 0;
int iH = 0; int iH = 0;
painter->setPen(Qt::black); painter->setPen(Qt::black);
QFont fnt = m_font; QFont fnt = m_tm.GetFont();
for (int i = 0; i < m_liOutput.count(); ++i) for (int i = 0; i < m_tm.GetCount(); ++i)
{ {
const TextLine& tl = m_liOutput.at(i); const TextLine& tl = m_tm.GetLine(i);
iH = tl.m_iHeight; iH = tl.m_iHeight;
fnt.setPixelSize(m_font.pixelSize() + tl.m_iFontSize); fnt.setPixelSize(m_tm.GetFont().pixelSize() + tl.m_iFontSize);
fnt.setWeight(tl.m_eFontWeight); fnt.setWeight(tl.m_eFontWeight);
fnt.setStyle(tl.m_eStyle); fnt.setStyle(tl.m_eStyle);
painter->setFont(fnt); painter->setFont(fnt);
painter->drawText(0, iY, qRound(boundingRect().width()), iH, tl.m_eAlign, tl.m_qsText); painter->drawText(0, iY, qRound(boundingRect().width()), iH, tl.m_eAlign, tl.m_qsText);
iY += iH + SPACING; iY += iH + m_tm.GetSpacing();
} }
@ -154,8 +144,8 @@ void VTextGraphicsItem::Reset()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::AddLine(const TextLine& tl) void VTextGraphicsItem::AddLine(const TextLine& tl)
{ {
m_liLines << tl; m_tm.AddLine(tl);
while (IsBigEnough(MIN_W, m_iMinH, MIN_FONT_SIZE) == false) while (m_tm.IsBigEnough(MIN_W, m_iMinH, MIN_FONT_SIZE) == false)
{ {
m_iMinH += 5; m_iMinH += 5;
} }
@ -168,7 +158,7 @@ void VTextGraphicsItem::AddLine(const TextLine& tl)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::Clear() void VTextGraphicsItem::Clear()
{ {
m_liLines.clear(); m_tm.Clear();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -233,7 +223,7 @@ bool VTextGraphicsItem::IsContained(QRectF rectBB, qreal dRot, qreal &dX, qreal
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
int VTextGraphicsItem::GetFontSize() const int VTextGraphicsItem::GetFontSize() const
{ {
return m_font.pixelSize(); return m_tm.GetFont().pixelSize();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -357,7 +347,7 @@ void VTextGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME)
} }
else else
{ {
emit SignalResized(m_rectBoundingBox.width(), m_font.pixelSize()); emit SignalResized(m_rectBoundingBox.width(), m_tm.GetFont().pixelSize());
Update(); Update();
} }
} }
@ -387,73 +377,22 @@ void VTextGraphicsItem::UpdateBox()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VTextGraphicsItem::UpdateFont() void VTextGraphicsItem::UpdateFont()
{ {
int iFS = m_font.pixelSize(); int iFS = m_tm.GetFont().pixelSize();
// increase the font size until the bounding rect is not big enough // increase the font size until the bounding rect is not big enough
while (iFS < MAX_FONT_SIZE && IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == true) while (iFS < MAX_FONT_SIZE && m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == true)
{ {
++iFS; ++iFS;
} }
// decrease the font size until the bounding rect is big enough // decrease the font size until the bounding rect is big enough
while (iFS >= MIN_FONT_SIZE && IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == false) while (iFS >= MIN_FONT_SIZE && m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == false)
{ {
--iFS; --iFS;
} }
m_font.setPixelSize(iFS); m_tm.SetFontSize(iFS);
UpdateBox(); UpdateBox();
} }
//---------------------------------------------------------------------------------------------------------------------
bool VTextGraphicsItem::IsBigEnough(qreal fW, qreal fH, int iFontSize)
{
m_liOutput.clear();
QFont fnt = m_font;
int iY = 0;
for (int i = 0; i < m_liLines.count(); ++i)
{
const TextLine& tl = m_liLines.at(i);
TextLine tlOut = tl;
fnt.setPixelSize(iFontSize + tl.m_iFontSize);
QFontMetrics fm(fnt);
tlOut.m_iHeight = fm.height();
QStringList qslLines = SplitString(tlOut.m_qsText, fW, fm);
for (int iL = 0; iL < qslLines.count(); ++iL)
{
tlOut.m_qsText = qslLines[iL];
m_liOutput << tlOut;
iY += tlOut.m_iHeight + SPACING;
}
}
return iY < fH;
}
//---------------------------------------------------------------------------------------------------------------------
QStringList VTextGraphicsItem::SplitString(const QString &qs, qreal fW, const QFontMetrics &fm)
{
QRegularExpression reg("\\s+");
QStringList qslWords = qs.split(reg);
QStringList qslLines;
QString qsCurrent;
for (int i = 0; i < qslWords.count(); ++i)
{
if (qsCurrent.length() > 0)
{
qsCurrent += QLatin1Literal(" ");
}
if (fm.width(qsCurrent + qslWords[i]) > fW)
{
qslLines << qsCurrent;
qsCurrent = qslWords[i];
}
else
{
qsCurrent += qslWords[i];
}
}
qslLines << qsCurrent;
return qslLines;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
double VTextGraphicsItem::GetAngle(QPointF pt) const double VTextGraphicsItem::GetAngle(QPointF pt) const
{ {
@ -466,7 +405,7 @@ double VTextGraphicsItem::GetAngle(QPointF pt) const
} }
else else
{ {
return atan2(dY, dX); return qAtan2(dY, dX);
} }
} }

View file

@ -33,17 +33,7 @@
#include <QFont> #include <QFont>
#include <QList> #include <QList>
struct TextLine #include "vtextmanager.h"
{
QString m_qsText;
int m_iFontSize; // 0 means default
QFont::Weight m_eFontWeight;
QFont::Style m_eStyle;
Qt::Alignment m_eAlign;
int m_iHeight;
TextLine();
};
class VTextGraphicsItem : public QGraphicsObject class VTextGraphicsItem : public QGraphicsObject
{ {
@ -79,8 +69,6 @@ protected:
void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME); void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME);
void UpdateBox(); void UpdateBox();
void UpdateFont(); void UpdateFont();
bool IsBigEnough(qreal fW, qreal fH, int iFontSize);
QStringList SplitString(const QString& qs, qreal fW, const QFontMetrics& fm);
double GetAngle(QPointF pt) const; double GetAngle(QPointF pt) const;
@ -102,9 +90,7 @@ private:
QRectF m_rectResize; QRectF m_rectResize;
int m_iMinH; int m_iMinH;
QRectF m_rectBoundingBox; QRectF m_rectBoundingBox;
QFont m_font; VTextManager m_tm;
QList<TextLine> m_liLines;
QList<TextLine> m_liOutput;
QRectF GetBoundingRect(QRectF rectBB, qreal dRot) const; QRectF GetBoundingRect(QRectF rectBB, qreal dRot) const;
}; };

View file

@ -0,0 +1,106 @@
#include <QRegularExpression>
#include <QFontMetrics>
#include "vtextmanager.h"
//---------------------------------------------------------------------------------------------------------------------
TextLine::TextLine()
:m_qsText(), m_iFontSize(MIN_FONT_SIZE), m_eFontWeight(QFont::Normal), m_eStyle(QFont::StyleNormal),
m_eAlign(Qt::AlignCenter), m_iHeight(0)
{}
//---------------------------------------------------------------------------------------------------------------------
VTextManager::VTextManager()
:m_liLines(), m_liOutput()
{}
//---------------------------------------------------------------------------------------------------------------------
VTextManager::~VTextManager()
{}
//---------------------------------------------------------------------------------------------------------------------
int VTextManager::GetSpacing() const
{ return 2; }
//---------------------------------------------------------------------------------------------------------------------
void VTextManager::SetFont(const QFont& font)
{ m_font = font; }
//---------------------------------------------------------------------------------------------------------------------
const QFont& VTextManager::GetFont() const
{ return m_font; }
//---------------------------------------------------------------------------------------------------------------------
void VTextManager::SetFontSize(int iFS)
{ m_font.setPixelSize(iFS); }
//---------------------------------------------------------------------------------------------------------------------
void VTextManager::AddLine(const TextLine& tl)
{ m_liLines << tl; }
//---------------------------------------------------------------------------------------------------------------------
void VTextManager::Clear()
{ m_liLines.clear(); }
//---------------------------------------------------------------------------------------------------------------------
int VTextManager::GetCount() const
{ return m_liOutput.count(); }
//---------------------------------------------------------------------------------------------------------------------
const TextLine& VTextManager::GetLine(int i) const
{ return m_liOutput[i]; }
//---------------------------------------------------------------------------------------------------------------------
bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize)
{
m_liOutput.clear();
QFont fnt = m_font;
int iY = 0;
for (int i = 0; i < m_liLines.count(); ++i)
{
const TextLine& tl = m_liLines.at(i);
TextLine tlOut = tl;
fnt.setPixelSize(iFontSize + tl.m_iFontSize);
QFontMetrics fm(fnt);
tlOut.m_iHeight = fm.height();
QStringList qslLines = SplitString(tlOut.m_qsText, fW, fm);
for (int iL = 0; iL < qslLines.count(); ++iL)
{
tlOut.m_qsText = qslLines[iL];
m_liOutput << tlOut;
iY += tlOut.m_iHeight + GetSpacing();
}
}
return iY < fH;
}
//---------------------------------------------------------------------------------------------------------------------
QStringList VTextManager::SplitString(const QString &qs, qreal fW, const QFontMetrics &fm)
{
QRegularExpression reg("\\s+");
QStringList qslWords = qs.split(reg);
QStringList qslLines;
QString qsCurrent;
for (int i = 0; i < qslWords.count(); ++i)
{
if (qsCurrent.length() > 0)
{
qsCurrent += QLatin1Literal(" ");
}
if (fm.width(qsCurrent + qslWords[i]) > fW)
{
qslLines << qsCurrent;
qsCurrent = qslWords[i];
}
else
{
qsCurrent += qslWords[i];
}
}
qslLines << qsCurrent;
return qslLines;
}

View file

@ -0,0 +1,47 @@
#ifndef VTEXTMANAGER_H
#define VTEXTMANAGER_H
#include <QString>
#include <QFont>
#define MIN_FONT_SIZE 12
#define MAX_FONT_SIZE 128
struct TextLine
{
QString m_qsText;
int m_iFontSize; // 0 means default
QFont::Weight m_eFontWeight;
QFont::Style m_eStyle;
Qt::Alignment m_eAlign;
int m_iHeight;
TextLine();
};
class VTextManager
{
public:
VTextManager();
~VTextManager();
int GetSpacing() const;
void SetFont(const QFont& font);
const QFont& GetFont() const;
void SetFontSize(int iFS);
void AddLine(const TextLine& tl);
void Clear();
int GetCount() const;
const TextLine& GetLine(int i) const;
bool IsBigEnough(qreal fW, qreal fH, int iFontSize);
protected:
QStringList SplitString(const QString& qs, qreal fW, const QFontMetrics& fm);
private:
QFont m_font;
QList<TextLine> m_liLines;
QList<TextLine> m_liOutput;
};
#endif // VTEXTMANAGER_H