From 21debaf2491a327158f43a447459778b60028310 Mon Sep 17 00:00:00 2001 From: BojanKverh Date: Sat, 25 Jun 2016 17:19:44 +0200 Subject: [PATCH] Reimplemented QTextGraphicsItem class --HG-- branch : feature --- src/libs/vtools/tools/vtextgraphicsitem.cpp | 285 ++++++++++++-------- src/libs/vtools/tools/vtextgraphicsitem.h | 38 ++- src/libs/vtools/tools/vtooldetail.cpp | 42 ++- src/libs/vtools/tools/vtooldetail.h | 1 + 4 files changed, 228 insertions(+), 138 deletions(-) diff --git a/src/libs/vtools/tools/vtextgraphicsitem.cpp b/src/libs/vtools/tools/vtextgraphicsitem.cpp index 9f97f2702..13ec56b12 100644 --- a/src/libs/vtools/tools/vtextgraphicsitem.cpp +++ b/src/libs/vtools/tools/vtextgraphicsitem.cpp @@ -38,20 +38,19 @@ #define MIN_W 120 #define MIN_H 60 #define MIN_FONT_SIZE 12 -#define MAX_FONT_SIZE 36 +#define MAX_FONT_SIZE 48 +#define SPACING 2 //--------------------------------------------------------------------------------------------------------------------- VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent) - : QGraphicsTextItem(pParent) + : QGraphicsObject(pParent) { setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); m_eMode = mNormal; m_rectBoundingBox.setTopLeft(QPointF(0, 0)); - setTextWidth(MIN_W); - m_rectBoundingBox.setWidth(MIN_W); m_iMinH = MIN_H; - m_rectBoundingBox.setHeight(m_iMinH); + Resize(MIN_W, m_iMinH); setZValue(2); } @@ -59,11 +58,33 @@ VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent) VTextGraphicsItem::~VTextGraphicsItem() {} +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::SetFont(const QFont& fnt) +{ + m_font = fnt; +} + //--------------------------------------------------------------------------------------------------------------------- void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->fillRect(option->rect, QColor(251, 251, 175)); - QGraphicsTextItem::paint(painter, option, widget); + + // draw text lines + int iY = 0; + int iH; + painter->setPen(Qt::black); + QFont fnt = m_font; + for (int i = 0; i < m_liOutput.count(); ++i) + { + const TextLine& tl = m_liOutput.at(i); + iH = tl.m_iHeight; + fnt.setPixelSize(m_font.pixelSize() + tl.m_iFontSize); + fnt.setWeight(tl.m_eFontWeight); + painter->setFont(fnt); + painter->drawText(0, iY, boundingRect().width(), iH, tl.m_eAlign, tl.m_qsText); + iY += iH + SPACING; + } + if (m_eMode != mNormal) { @@ -72,149 +93,175 @@ void VTextGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem painter->setPen(Qt::black); painter->setBrush(Qt::black); - SetResizeArea(); painter->drawRect(m_rectResize); + + if (m_eMode == mResize) + { + painter->drawLine(0, 0, m_rectBoundingBox.width(), m_rectBoundingBox.height()); + painter->drawLine(0, m_rectBoundingBox.height(), m_rectBoundingBox.width(), 0); + } } } +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::AddLine(const TextLine& tl) +{ + m_liLines << tl; + while (IsBigEnough(MIN_W, m_iMinH, MIN_FONT_SIZE) == false) + { + m_iMinH += 5; + } + if (m_rectBoundingBox.height() < m_iMinH) + { + Resize(m_rectBoundingBox.width(), m_iMinH); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::Clear() +{ + m_liLines.clear(); +} + //--------------------------------------------------------------------------------------------------------------------- void VTextGraphicsItem::Reset() { m_eMode = mNormal; - Update(); + UpdateFont(); } //--------------------------------------------------------------------------------------------------------------------- QRectF VTextGraphicsItem::boundingRect() const -{ return m_rectBoundingBox; } - -//--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::SetHTML(const QString& qsHtml) { - QGraphicsTextItem::setHtml(qsHtml); - m_rectBoundingBox.setHeight(document()->size().height()); - - // calculate the minimal height - QScopedPointer pDoc(document()->clone()); - QFont fnt = font(); - fnt.setPixelSize(MIN_FONT_SIZE); - pDoc->setDefaultFont(fnt); - m_iMinH = pDoc->size().height(); + return m_rectBoundingBox; } //--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *pME) +void VTextGraphicsItem::Resize(qreal fW, qreal fH) { - if ((pME->button() & Qt::LeftButton) > 0) - { - SetResizeArea(); - if (m_rectResize.contains(pME->pos()) == true) - { - m_eMode = mResize; - } - else - { - m_eMode = mMove; - } - Update(); - m_ptStart = pME->pos(); - } -} + // don't allow resize under specific size + if (fW < MIN_W || fH < m_iMinH) + return; -//--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *pME) -{ - if (m_eMode == mMove) - { - m_eMode = mMove; - QPointF ptRel = pME->pos() - m_ptStart; - moveBy(ptRel.x(), ptRel.y()); - } - else if (m_eMode == mResize) - { - prepareGeometryChange(); - qreal fW = m_rectBoundingBox.width() + pME->pos().x() - m_ptStart.x(); - qreal fH = m_rectBoundingBox.height() + pME->pos().y() - m_ptStart.y(); - - if (fW >= MIN_W) - { - m_rectBoundingBox.setWidth(fW); - setTextWidth(fW); - } - if (fH >= m_iMinH) - { - m_rectBoundingBox.setHeight(fH); - } - m_ptStart = pME->pos(); - - UpdateFont(); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *pME) -{ - if ((pME->button() & Qt::LeftButton) > 0) - { - if (m_eMode == mMove) - { - m_eMode = mActivated; - emit SignalMoved(pos()); - } - else if (m_eMode == mResize) - { - m_eMode = mActivated; - emit SignalResized(textWidth(), font().pixelSize()); - } - Update(); - } -} - -//--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::Update() -{ - update(boundingRect()); -} - -//--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::SetResizeArea() -{ - m_rectResize.setLeft(boundingRect().right() - RESIZE_SQUARE); - m_rectResize.setTop(boundingRect().bottom() - RESIZE_SQUARE); + m_rectBoundingBox.setWidth(fW); + m_rectBoundingBox.setHeight(fH); + m_rectResize.setTopLeft(QPointF(fW - RESIZE_SQUARE, fH - RESIZE_SQUARE)); m_rectResize.setWidth(RESIZE_SQUARE); m_rectResize.setHeight(RESIZE_SQUARE); } //--------------------------------------------------------------------------------------------------------------------- -void VTextGraphicsItem::UpdateFont() +void VTextGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *pME) { - QScopedPointer pDoc(document()->clone()); - pDoc->setTextWidth(m_rectBoundingBox.width()); - - QFont fnt = font(); - int iFS = fnt.pixelSize(); - QSizeF sz = pDoc->size(); - while (sz.width() < m_rectBoundingBox.width() && sz.height() < m_rectBoundingBox.height() && iFS < MAX_FONT_SIZE) + m_ptStart = pME->pos(); + m_szStart = m_rectBoundingBox.size(); + if (m_rectResize.contains(m_ptStart) == true) { - ++iFS; - fnt.setPixelSize(iFS); - pDoc->setDefaultFont(fnt); - sz = pDoc->size(); + m_eMode = mResize; } - - while ((sz.width() >= m_rectBoundingBox.width() || sz.height() >= m_rectBoundingBox.height()) && iFS > MIN_FONT_SIZE) + else { - --iFS; - fnt.setPixelSize(iFS); - pDoc->setDefaultFont(fnt); - sz = pDoc->size(); - + m_eMode = mMove; } - - fnt.setPixelSize(iFS); - setFont(fnt); Update(); } //--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME) +{ + QPointF ptDiff = pME->pos() - m_ptStart; + if (m_eMode == mMove) + { + moveBy(ptDiff.x(), ptDiff.y()); + Update(); + } + else if (m_eMode == mResize) + { + Resize(m_szStart.width() + ptDiff.x(), m_szStart.height() + ptDiff.y()); + UpdateFont(); + emit SignalShrink(); + } +} +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) +{ + m_eMode = mActivated; + Update(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::Update() +{ + update(m_rectBoundingBox); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VTextGraphicsItem::UpdateFont() +{ + int iFS = m_font.pixelSize(); + + // 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) + { + ++iFS; + } + // 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) + { + --iFS; + } + m_font.setPixelSize(iFS); + Update(); +} + +//--------------------------------------------------------------------------------------------------------------------- +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 i = 0; i < qslLines.count(); ++i) + { + tlOut.m_qsText = qslLines[i]; + m_liOutput << tlOut; + iY += tlOut.m_iHeight + SPACING; + } + } + return iY < fH; +} + +//--------------------------------------------------------------------------------------------------------------------- +QStringList VTextGraphicsItem::SplitString(const QString &qs, qreal fW, const QFontMetrics &fm) +{ + QRegExp reg("\\s+"); + QStringList qslWords = qs.split(reg); + QStringList qslLines; + QString qsCurrent; + for (int i = 0; i < qslWords.count(); ++i) + { + if (qsCurrent.length() > 0) + { + qsCurrent += " "; + } + if (fm.width(qsCurrent + qslWords[i]) > fW) + { + qslLines << qsCurrent; + qsCurrent = qslWords[i]; + } + else + { + qsCurrent += qslWords[i]; + } + } + qslLines << qsCurrent; + return qslLines; +} diff --git a/src/libs/vtools/tools/vtextgraphicsitem.h b/src/libs/vtools/tools/vtextgraphicsitem.h index 9a840f526..165857d95 100644 --- a/src/libs/vtools/tools/vtextgraphicsitem.h +++ b/src/libs/vtools/tools/vtextgraphicsitem.h @@ -29,9 +29,20 @@ #ifndef VTEXTGRAPHICSITEM_H #define VTEXTGRAPHICSITEM_H -#include +#include +#include +#include -class VTextGraphicsItem : public QGraphicsTextItem +struct TextLine +{ + QString m_qsText; + int m_iFontSize; // 0 means default + QFont::Weight m_eFontWeight; + Qt::Alignment m_eAlign; + int m_iHeight; +}; + +class VTextGraphicsItem : public QGraphicsObject { Q_OBJECT @@ -46,33 +57,40 @@ public: VTextGraphicsItem(QGraphicsItem* pParent = 0); ~VTextGraphicsItem(); + void SetFont(const QFont& fnt); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void Reset(); QRectF boundingRect() const; - void SetHTML(const QString& qsHtml); - -signals: - void SignalMoved(QPointF ptPos); - void SignalResized(qreal dTW, int iFontSize); + void AddLine(const TextLine& tl); + void Clear(); protected: + void Resize(qreal fW, qreal fH); void mousePressEvent(QGraphicsSceneMouseEvent* pME); void mouseMoveEvent(QGraphicsSceneMouseEvent* pME); void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME); - void Update(); - void SetResizeArea(); - void UpdateFont(); + bool IsBigEnough(qreal fW, qreal fH, int iFontSize); + QStringList SplitString(const QString& qs, qreal fW, const QFontMetrics& fm); + +signals: + void SignalMoved(QPointF ptPos); + void SignalResized(qreal iTW, int iFontSize); + void SignalShrink(); private: Mode m_eMode; QPointF m_ptStart; + QSizeF m_szStart; QRectF m_rectResize; int m_iMinH; QRectF m_rectBoundingBox; + QFont m_font; + QList m_liLines; + QList m_liOutput; }; #endif // VTEXTGRAPHICSITEM_H diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp index c4a0f588c..47729189d 100644 --- a/src/libs/vtools/tools/vtooldetail.cpp +++ b/src/libs/vtools/tools/vtooldetail.cpp @@ -130,6 +130,7 @@ VToolDetail::VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 connect(dataLabel, &VTextGraphicsItem::SignalMoved, this, &VToolDetail::SaveMove); connect(dataLabel, &VTextGraphicsItem::SignalResized, this, &VToolDetail::SaveResize); + connect(dataLabel, &VTextGraphicsItem::SignalShrink, this, &VToolDetail::UpdateAll); UpdateLabel(); } @@ -640,22 +641,38 @@ void VToolDetail::UpdateLabel() const VPatternPieceData& data = detail.GetPatternPieceData(); if (data.GetLetter().isEmpty() == false || data.GetName().isEmpty() == false || data.GetMCPCount() > 0) { - QString qsText = "Cut %1 on %2%3"; + QString qsText = "Cut %1 of %2%3"; QStringList qslPlace; qslPlace << "" << " on Fold"; QFont fnt = qApp->font(); fnt.setPixelSize(data.GetFontSize()); - dataLabel->setFont(fnt); - QString qsHTML = "
" + data.GetLetter() + "

"; - qsHTML += "" + data.GetName() + "
"; - for (int i = 0; i < data.GetMCPCount(); ++i) - { + dataLabel->SetFont(fnt); + dataLabel->Clear(); + TextLine tl; + // letter + tl.m_qsText = data.GetLetter(); + tl.m_eAlign = Qt::AlignCenter; + tl.m_eFontWeight = QFont::Bold; + tl.m_iFontSize = 4; + dataLabel->AddLine(tl); + tl.m_qsText = data.GetName(); + tl.m_eAlign = Qt::AlignCenter; + tl.m_eFontWeight = QFont::DemiBold; + tl.m_iFontSize = 2; + dataLabel->AddLine(tl); + + // MCP + tl.m_eAlign = Qt::AlignLeft | Qt::AlignVCenter; + tl.m_eFontWeight = QFont::Normal; + tl.m_iFontSize = 0; + for (int i = 0; i < data.GetMCPCount(); ++i) { MaterialCutPlacement mcp = data.GetMCP(i); - QString qsLine = qsText.arg(mcp.m_iCutNumber).arg(mcp.m_qsMaterialUserDef).arg(qslPlace[int(mcp.m_ePlacement)]); - qsHTML += qsLine + "
"; + tl.m_qsText = qsText.arg(mcp.m_iCutNumber).arg(mcp.m_qsMaterialUserDef).arg(qslPlace[int(mcp.m_ePlacement)]); + dataLabel->AddLine(tl); } - dataLabel->SetHTML(qsHTML); + dataLabel->setPos(data.GetPos()); + dataLabel->Reset(); dataLabel->show(); } else @@ -848,3 +865,10 @@ void VToolDetail::ResetChild() { dataLabel->Reset(); } + +//--------------------------------------------------------------------------------------------------------------------- +void VToolDetail::UpdateAll() +{ + sceneDetails->update(); + update(); +} diff --git a/src/libs/vtools/tools/vtooldetail.h b/src/libs/vtools/tools/vtooldetail.h index 322129eac..f4fd7eba9 100644 --- a/src/libs/vtools/tools/vtooldetail.h +++ b/src/libs/vtools/tools/vtooldetail.h @@ -92,6 +92,7 @@ public slots: virtual void AllowHover(bool enabled) Q_DECL_OVERRIDE; virtual void AllowSelecting(bool enabled) Q_DECL_OVERRIDE; virtual void ResetChild(); + virtual void UpdateAll(); protected: virtual void AddToFile () Q_DECL_OVERRIDE; virtual void RefreshDataInFile() Q_DECL_OVERRIDE;