diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index d5a0eab35..b9e60f453 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -39,6 +39,7 @@ #include "../vlayout/vposter.h" #include "../vpatterndb/vpatternpiecedata.h" #include "../vpatterndb/vpatterninfogeometry.h" +#include "../vpatterndb/vgrainlinegeometry.h" #include #include @@ -496,6 +497,11 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash *de } det.SetPatternInfo(pDoc, geom, qApp->font(), pattern->size(), pattern->height()); } + const VGrainlineGeometry& grainlineGeom = d.GetGrainlineGeometry(); + if (grainlineGeom.IsVisible() == true) + { + det.SetGrainline(grainlineGeom, *pattern); + } det.setWidth(qApp->toPixel(d.getWidth())); det.CreateTextItems(); det.setForbidFlipping(d.getForbidFlipping()); diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index e2d6fe44f..c6186ca16 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -51,6 +51,7 @@ #include "../vpatterndb/calculator.h" #include "../vpatterndb/vpatternpiecedata.h" #include "../vpatterndb/vpatterninfogeometry.h" +#include "../vpatterndb/vgrainlinegeometry.h" #include #include @@ -718,6 +719,18 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document qreal dRot = GetParametrDouble(element, VToolDetail::AttrRotation, "0"); detail.GetPatternInfo().SetRotation(dRot); } + else if (element.tagName() == TagGrainline) + { + detail.GetGrainlineGeometry().SetVisible(GetParametrBool(element, AttrVisible, falseStr)); + QPointF ptPos; + ptPos.setX(GetParametrDouble(element, AttrMx, "0")); + ptPos.setY(GetParametrDouble(element, AttrMy, "0")); + detail.GetGrainlineGeometry().SetPos(ptPos); + QString qsLength = GetParametrString(element, AttrLength, "0"); + detail.GetGrainlineGeometry().SetLength(qsLength); + QString qsRot = GetParametrString(element, VToolDetail::AttrRotation, "0"); + detail.GetGrainlineGeometry().SetRotation(qsRot); + } } } VToolDetail::Create(id, detail, sceneDetail, this, data, parse, Source::FromFile); diff --git a/src/libs/ifc/schema/pattern/v0.3.5.xsd b/src/libs/ifc/schema/pattern/v0.3.5.xsd index 8499e9604..cf8050fa6 100644 --- a/src/libs/ifc/schema/pattern/v0.3.5.xsd +++ b/src/libs/ifc/schema/pattern/v0.3.5.xsd @@ -578,4 +578,4 @@ - + \ No newline at end of file diff --git a/src/libs/ifc/schema/pattern/v0.3.6.xsd b/src/libs/ifc/schema/pattern/v0.3.6.xsd index 8c062ebb1..3d757bb57 100644 --- a/src/libs/ifc/schema/pattern/v0.3.6.xsd +++ b/src/libs/ifc/schema/pattern/v0.3.6.xsd @@ -377,6 +377,15 @@ + + + + + + + + + @@ -579,4 +588,4 @@ - + \ No newline at end of file diff --git a/src/libs/ifc/schema/pattern/v0.3.7.xsd b/src/libs/ifc/schema/pattern/v0.3.7.xsd index 7979e681b..d01677abf 100644 --- a/src/libs/ifc/schema/pattern/v0.3.7.xsd +++ b/src/libs/ifc/schema/pattern/v0.3.7.xsd @@ -377,6 +377,15 @@ + + + + + + + + + diff --git a/src/libs/ifc/xml/vabstractpattern.cpp b/src/libs/ifc/xml/vabstractpattern.cpp index 2975f223b..bade5069f 100644 --- a/src/libs/ifc/xml/vabstractpattern.cpp +++ b/src/libs/ifc/xml/vabstractpattern.cpp @@ -88,6 +88,7 @@ const QString VAbstractPattern::TagCompanyName = QStringLiteral("company"); const QString VAbstractPattern::TagSize = QStringLiteral("size"); const QString VAbstractPattern::TagShowDate = QStringLiteral("showDate"); const QString VAbstractPattern::TagShowMeasurements = QStringLiteral("showMeasurements"); +const QString VAbstractPattern::TagGrainline = QStringLiteral("grainline"); const QString VAbstractPattern::AttrName = QStringLiteral("name"); const QString VAbstractPattern::AttrVisible = QStringLiteral("visible"); diff --git a/src/libs/ifc/xml/vabstractpattern.h b/src/libs/ifc/xml/vabstractpattern.h index ca4b8faef..9c2ba8003 100644 --- a/src/libs/ifc/xml/vabstractpattern.h +++ b/src/libs/ifc/xml/vabstractpattern.h @@ -193,6 +193,7 @@ public: static const QString TagSize; static const QString TagShowDate; static const QString TagShowMeasurements; + static const QString TagGrainline; static const QString AttrName; static const QString AttrVisible; diff --git a/src/libs/vlayout/vgraphicsfillitem.cpp b/src/libs/vlayout/vgraphicsfillitem.cpp new file mode 100644 index 000000000..4edcb17cb --- /dev/null +++ b/src/libs/vlayout/vgraphicsfillitem.cpp @@ -0,0 +1,52 @@ +/************************************************************************ + ** + ** @file vgraphicsfillitem.cpp + ** @author Bojan Kverh + ** @date October 16, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#include "vgraphicsfillitem.h" + +//--------------------------------------------------------------------------------------------------------------------- +VGraphicsFillItem::VGraphicsFillItem() + :QGraphicsPathItem() +{} + +//--------------------------------------------------------------------------------------------------------------------- +VGraphicsFillItem::~VGraphicsFillItem() +{} + +//--------------------------------------------------------------------------------------------------------------------- +void VGraphicsFillItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + painter->save(); + painter->setBrush(painter->pen().color()); + painter->drawPath(path()); + painter->restore(); +} + +//--------------------------------------------------------------------------------------------------------------------- + diff --git a/src/libs/vlayout/vgraphicsfillitem.h b/src/libs/vlayout/vgraphicsfillitem.h new file mode 100644 index 000000000..467d62e12 --- /dev/null +++ b/src/libs/vlayout/vgraphicsfillitem.h @@ -0,0 +1,55 @@ +/************************************************************************ + ** + ** @file vgraphicsfillitem.h + ** @author Bojan Kverh + ** @date October 16, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VGRAPHICSFILLITEM_H +#define VGRAPHICSFILLITEM_H + +#include +#include + +class VGraphicsFillItem : public QGraphicsPathItem +{ +public: + /** + * @brief VGraphicsFillItem Constructor + */ + VGraphicsFillItem(); + /** + * @brief ~VGraphicsFillItem Destructor + */ + ~VGraphicsFillItem(); + /** + * @brief paint Paints the item, filling the inside surface + * @param painter pointer to the painter object + * @param option unused + * @param widget unused + */ + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +}; + +#endif // VGRAPHICSFILLITEM_H diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri index d1cc7645f..6d82d469f 100644 --- a/src/libs/vlayout/vlayout.pri +++ b/src/libs/vlayout/vlayout.pri @@ -17,7 +17,8 @@ HEADERS += \ $$PWD/vbestsquare.h \ $$PWD/vposition.h \ $$PWD/vtextmanager.h \ - vposter.h + vposter.h \ + vgraphicsfillitem.h SOURCES += \ $$PWD/vlayoutgenerator.cpp \ @@ -29,6 +30,7 @@ SOURCES += \ $$PWD/vbestsquare.cpp \ $$PWD/vposition.cpp \ $$PWD/vtextmanager.cpp \ - vposter.cpp + vposter.cpp \ + vgraphicsfillitem.cpp win32-msvc*:SOURCES += $$PWD/stable.cpp diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp index fc4de3307..dc666987f 100644 --- a/src/libs/vlayout/vlayoutdetail.cpp +++ b/src/libs/vlayout/vlayoutdetail.cpp @@ -46,9 +46,12 @@ #include "../vpatterndb/vpatterninfogeometry.h" #include "../vpatterndb/vpatternpiecedata.h" #include "../vmisc/vmath.h" +#include "../vmisc/vabstractapplication.h" +#include "../vpatterndb/calculator.h" #include "vlayoutdef.h" #include "vlayoutdetail_p.h" #include "vtextmanager.h" +#include "vgraphicsfillitem.h" class QGraphicsPathItem; class QLineF; @@ -180,6 +183,66 @@ void VLayoutDetail::SetPatternInfo(const VAbstractPattern* pDoc, const VPatternI d->m_tmPattern.FitFontSize(geom.GetLabelWidth(), geom.GetLabelHeight()); } +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetGrainline(const VGrainlineGeometry& geom, const VContainer& rPattern) +{ + d->grainlineGeom = geom; + qreal dAng; + qreal dLen; + + try + { + QString qsFormula = geom.GetRotation().replace("\n", " "); + qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator()); + Calculator cal1; + dAng = cal1.EvalFormula(rPattern.PlainVariables(), qsFormula); + dAng = qDegreesToRadians(dAng); + + qsFormula = geom.GetLength().replace("\n", " "); + qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator()); + Calculator cal2; + dLen = cal2.EvalFormula(rPattern.PlainVariables(), qsFormula); + dLen = ToPixel(dLen, *rPattern.GetPatternUnit()); + } + catch(...) + { + return; + } + + QPointF pt1 = geom.GetPos(); + QPointF pt2; + pt2.setX(pt1.x() + dLen * qCos(dAng)); + pt2.setY(pt1.y() - dLen * qSin(dAng)); + QVector v; + QPointF pt; + qreal dArrowLen = ToPixel(0.5, *rPattern.GetPatternUnit()); + qreal dArrowAng = M_PI/9; + + v << pt1; + + pt.setX(pt1.x() + dArrowLen * qCos(dAng + dArrowAng)); + pt.setY(pt1.y() - dArrowLen * qSin(dAng + dArrowAng)); + v << pt; + pt.setX(pt1.x() + dArrowLen * qCos(dAng - dArrowAng)); + pt.setY(pt1.y() - dArrowLen * qSin(dAng - dArrowAng)); + v << pt; + + v << pt1 << pt2; + + dAng += M_PI; + + pt.setX(pt2.x() + dArrowLen * qCos(dAng + dArrowAng)); + pt.setY(pt2.y() - dArrowLen * qSin(dAng + dArrowAng)); + v << pt; + pt.setX(pt2.x() + dArrowLen * qCos(dAng - dArrowAng)); + pt.setY(pt2.y() - dArrowLen * qSin(dAng - dArrowAng)); + v << pt; + + v << pt2; + + d->grainlinePoints = RoundPoints(v); +} + //--------------------------------------------------------------------------------------------------------------------- QTransform VLayoutDetail::GetMatrix() const { @@ -673,6 +736,25 @@ QGraphicsItem *VLayoutDetail::GetItem() const return item; } +//--------------------------------------------------------------------------------------------------------------------- +QGraphicsItem* VLayoutDetail::GetGrainlineItem() const +{ + if (d->grainlinePoints.count() < 6) + { + return 0; + } + VGraphicsFillItem* item = new VGraphicsFillItem(); + QPainterPath path; + QVector v = Map(d->grainlinePoints); + path.moveTo(v.at(0)); + for (int i = 1; i < v.count(); ++i) + { + path.lineTo(v.at(i)); + } + item->setPath(path); + return item; +} + //--------------------------------------------------------------------------------------------------------------------- bool VLayoutDetail::IsMirror() const { diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h index ef9cbd5cb..1c85855a9 100644 --- a/src/libs/vlayout/vlayoutdetail.h +++ b/src/libs/vlayout/vlayoutdetail.h @@ -44,6 +44,7 @@ #include "../ifc/xml/vabstractpattern.h" #include "../vpatterndb/vpatterninfogeometry.h" #include "../vpatterndb/vpatternpiecedata.h" +#include "../vpatterndb/vcontainer.h" #include "vabstractdetail.h" class QFont; @@ -57,6 +58,7 @@ class VAbstractPattern; class VLayoutDetailData; class VPatternInfoGeometry; class VPatternPieceData; +class VGrainlineGeometry; class VLayoutDetail :public VAbstractDetail { @@ -80,6 +82,8 @@ public: void SetPatternInfo(const VAbstractPattern* pDoc, const VPatternInfoGeometry& geom, const QFont& font, qreal dSize, qreal dHeight); + void SetGrainline(const VGrainlineGeometry& geom, const VContainer& rPattern); + QTransform GetMatrix() const; void SetMatrix(const QTransform &matrix); @@ -110,6 +114,7 @@ public: QGraphicsItem* GetTextItem(int i) const Q_REQUIRED_RESULT; QPainterPath LayoutAllowencePath() const; QGraphicsItem *GetItem() const Q_REQUIRED_RESULT; + QGraphicsItem* GetGrainlineItem() const Q_REQUIRED_RESULT; private: QSharedDataPointer d; diff --git a/src/libs/vlayout/vlayoutdetail_p.h b/src/libs/vlayout/vlayoutdetail_p.h index efbdf8ca6..289af3275 100644 --- a/src/libs/vlayout/vlayoutdetail_p.h +++ b/src/libs/vlayout/vlayoutdetail_p.h @@ -36,6 +36,8 @@ #include "../vpatterndb/vpatternpiecedata.h" #include "../vpatterndb/vpatterninfogeometry.h" +#include "../vpatterndb/vgrainlinegeometry.h" + #include "vtextmanager.h" QT_WARNING_PUSH @@ -47,45 +49,50 @@ public: VLayoutDetailData() :contour(QVector()), seamAllowence(QVector()), layoutAllowence(QVector()), matrix(QMatrix()), layoutWidth(0), mirror(false), detailLabel(QVector()), - patternInfo(QVector()), detailData(), patternGeom(), m_tmDetail(), - m_tmPattern(), m_liPP(QList()) + patternInfo(QVector()), grainlinePoints(QVector()), detailData(), patternGeom(), + grainlineGeom(), m_tmDetail(), m_tmPattern(), m_liPP(QList()) {} VLayoutDetailData(const VLayoutDetailData &detail) :QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence), layoutAllowence(detail.layoutAllowence), matrix(detail.matrix), layoutWidth(detail.layoutWidth), mirror(detail.mirror), detailLabel(detail.detailLabel), - patternInfo(detail.patternInfo), detailData(detail.detailData), patternGeom(detail.patternGeom), - m_tmDetail(detail.m_tmDetail), m_tmPattern(detail.m_tmPattern), m_liPP(detail.m_liPP) + patternInfo(detail.patternInfo), grainlinePoints(detail.grainlinePoints), detailData(detail.detailData), + patternGeom(detail.patternGeom), grainlineGeom(detail.grainlineGeom), m_tmDetail(detail.m_tmDetail), + m_tmPattern(detail.m_tmPattern), m_liPP(detail.m_liPP) {} ~VLayoutDetailData() {} /** @brief contour list of contour points. */ - QVector contour; + QVector contour; /** @brief seamAllowence list of seam allowence points. */ - QVector seamAllowence; + QVector seamAllowence; /** @brief layoutAllowence list of layout allowence points. */ - QVector layoutAllowence; + QVector layoutAllowence; /** @brief matrix transformation matrix*/ - QTransform matrix; + QTransform matrix; /** @brief layoutWidth value layout allowence width in pixels. */ - qreal layoutWidth; + qreal layoutWidth; - bool mirror; + bool mirror; /** @brief detailLabel detail label rectangle */ - QVector detailLabel; + QVector detailLabel; /** @brief patternInfo pattern info rectangle */ - QVector patternInfo; + QVector patternInfo; + /** @brief grainlineInfo line */ + QVector grainlinePoints; /** @brief detailData detail data */ - VPatternPieceData detailData; + VPatternPieceData detailData; /** @brief patternGeom pattern geometry */ - VPatternInfoGeometry patternGeom; + VPatternInfoGeometry patternGeom; + /** @brief grainlineGeom grainline geometry */ + VGrainlineGeometry grainlineGeom; /** @brief m_tmDetail text manager for laying out detail info */ VTextManager m_tmDetail; /** @brief m_tmPattern text manager for laying out pattern info */ diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp index 638d43503..169c51457 100644 --- a/src/libs/vlayout/vlayoutpaper.cpp +++ b/src/libs/vlayout/vlayoutpaper.cpp @@ -348,6 +348,12 @@ QList VLayoutPaper::GetItemDetails() const { list.append(d->details.at(i).GetTextItem(iT)); } + + QGraphicsItem* pItem = d->details.at(i).GetGrainlineItem(); + if (pItem != 0) + { + list.append(pItem); + } } return list; } diff --git a/src/libs/vlayout/vtextmanager.cpp b/src/libs/vlayout/vtextmanager.cpp index 936a1a95e..b375e3c73 100644 --- a/src/libs/vlayout/vtextmanager.cpp +++ b/src/libs/vlayout/vtextmanager.cpp @@ -159,13 +159,18 @@ const TextLine& VTextManager::GetLine(int i) const * @param fW rectangle width * @param fH rectangle height * @param iFontSize base font size + * @param fMinW minimal required rectangle width to fit the text + * @param fMinH minimal required rectangle height to fit the text * @return true, if rectangle of size (fW, fH) */ -bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize) +bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize, qreal& fMinW, qreal& fMinH) { m_liOutput.clear(); QFont fnt = m_font; int iY = 0; + fMinW = fW; + fMinH = fH; + for (int i = 0; i < m_liLines.count(); ++i) { const TextLine& tl = m_liLines.at(i); @@ -180,6 +185,7 @@ bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize) // check if every line fits within the label width if (fm.width(qslLines[iL]) + iHorSp > fW) { + fMinW = fm.width(qslLines[iL]) + iHorSp; return false; } tlOut.m_qsText = qslLines[iL]; @@ -187,7 +193,11 @@ bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize) iY += tlOut.m_iHeight + GetSpacing(); } } - return iY < fH; + if (iY > fH) + { + fMinH = iY; + } + return iY <= fH; } //--------------------------------------------------------------------------------------------------------------------- @@ -200,11 +210,14 @@ bool VTextManager::IsBigEnough(qreal fW, qreal fH, int iFontSize) void VTextManager::FitFontSize(qreal fW, qreal fH) { int iFontSize = GetFont().pixelSize(); - while (IsBigEnough(fW, fH, iFontSize) == true && iFontSize <= MAX_FONT_SIZE) + qreal fMinW; + qreal fMinH; + + while (IsBigEnough(fW, fH, iFontSize, fMinW, fMinH) == true && iFontSize <= MAX_FONT_SIZE) { ++iFontSize; } - while (IsBigEnough(fW, fH, iFontSize) == false && iFontSize >= MIN_FONT_SIZE) + while (IsBigEnough(fW, fH, iFontSize, fMinW, fMinH) == false && iFontSize >= MIN_FONT_SIZE) { --iFontSize; } diff --git a/src/libs/vlayout/vtextmanager.h b/src/libs/vlayout/vtextmanager.h index 1e3d2bf77..98d41aeb1 100644 --- a/src/libs/vlayout/vtextmanager.h +++ b/src/libs/vlayout/vtextmanager.h @@ -82,7 +82,7 @@ public: int GetCount() const; int GetSourceLineCount() const; const TextLine& GetLine(int i) const; - bool IsBigEnough(qreal fW, qreal fH, int iFontSize); + bool IsBigEnough(qreal fW, qreal fH, int iFontSize, qreal& fMinW, qreal& fMinH); void FitFontSize(qreal fW, qreal fH); void Update(const QString& qsName, const VPatternPieceData& data); void Update(const VAbstractPattern* pDoc, qreal dSize, qreal dHeight); diff --git a/src/libs/vpatterndb/vdetail.cpp b/src/libs/vpatterndb/vdetail.cpp index cd364168f..3da63174e 100644 --- a/src/libs/vpatterndb/vdetail.cpp +++ b/src/libs/vpatterndb/vdetail.cpp @@ -47,6 +47,7 @@ #include "vdetail_p.h" #include "vnodedetail.h" #include "vpatternpiecedata.h" +#include "vgrainlinegeometry.h" class QPointF; @@ -592,6 +593,28 @@ const VPatternInfoGeometry& VDetail::GetPatternInfo() const return d->m_piPatternInfo; } +//--------------------------------------------------------------------------------------------------------------------- + +/** + * @brief VDetail::GetGrainlineGeometry full access to the grainline geometry object + * @return reference to grainline geometry object + */ +VGrainlineGeometry& VDetail::GetGrainlineGeometry() +{ + return d->m_glGrainline; +} + +//--------------------------------------------------------------------------------------------------------------------- + +/** + * @brief VDetail::GetGrainlineGeometry returns the read-only reference to the grainline geometry object + * @return reference to grainline geometry object + */ +const VGrainlineGeometry& VDetail::GetGrainlineGeometry() const +{ + return d->m_glGrainline; +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief indexOfNode return index in list node using id object. diff --git a/src/libs/vpatterndb/vdetail.h b/src/libs/vpatterndb/vdetail.h index 8ea1f0be9..54eb0c958 100644 --- a/src/libs/vpatterndb/vdetail.h +++ b/src/libs/vpatterndb/vdetail.h @@ -47,6 +47,7 @@ class VDetailData; class VNodeDetail; class VPatternInfoGeometry; class VPatternPieceData; +class VGrainlineGeometry; /** * @brief The VDetail class for path of object (points, arcs, splines). @@ -105,6 +106,8 @@ public: void SetPatternInfo(const VPatternInfoGeometry &info); VPatternInfoGeometry& GetPatternInfo(); const VPatternInfoGeometry& GetPatternInfo() const; + VGrainlineGeometry& GetGrainlineGeometry(); + const VGrainlineGeometry& GetGrainlineGeometry() const; private: QSharedDataPointer d; diff --git a/src/libs/vpatterndb/vdetail_p.h b/src/libs/vpatterndb/vdetail_p.h index 7e256b9e5..d3692ca24 100644 --- a/src/libs/vpatterndb/vdetail_p.h +++ b/src/libs/vpatterndb/vdetail_p.h @@ -33,6 +33,7 @@ #include "vnodedetail.h" #include "vpatternpiecedata.h" #include "vpatterninfogeometry.h" +#include "vgrainlinegeometry.h" #include "../ifc/ifcdef.h" #include "../vmisc/diagnostic.h" @@ -52,7 +53,8 @@ public: VDetailData(const VDetailData &detail) :QSharedData(detail), _id(NULL_ID), nodes(detail.nodes), mx(detail.mx), my(detail.my), - m_ppData(detail.m_ppData), m_piPatternInfo(detail.m_piPatternInfo), inLayout(detail.inLayout) + m_ppData(detail.m_ppData), m_piPatternInfo(detail.m_piPatternInfo), + m_glGrainline(detail.m_glGrainline), inLayout(detail.inLayout) {} ~VDetailData() {} @@ -73,6 +75,10 @@ public: VPatternPieceData m_ppData; /** @brief Pattern info coordinates */ VPatternInfoGeometry m_piPatternInfo; + /** + * @brief m_glGrainline grainline geometry object + */ + VGrainlineGeometry m_glGrainline; bool inLayout; diff --git a/src/libs/vpatterndb/vgrainlinegeometry.cpp b/src/libs/vpatterndb/vgrainlinegeometry.cpp new file mode 100644 index 000000000..336d5da76 --- /dev/null +++ b/src/libs/vpatterndb/vgrainlinegeometry.cpp @@ -0,0 +1,101 @@ +/************************************************************************ + ** + ** @file vgrainlinegeometry.cpp + ** @author Bojan Kverh + ** @date September 06, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#include + +#include "vgrainlinegeometry.h" + +//--------------------------------------------------------------------------------------------------------------------- + +VGrainlineGeometry::VGrainlineGeometry() + :m_ptPos(0, 0), m_qsLength(), m_qsRotation(), m_bVisible(false) +{} + +//--------------------------------------------------------------------------------------------------------------------- + +VGrainlineGeometry::~VGrainlineGeometry() +{} + +//--------------------------------------------------------------------------------------------------------------------- + +QPointF VGrainlineGeometry::GetPos() const +{ + return m_ptPos; +} + +//--------------------------------------------------------------------------------------------------------------------- + +void VGrainlineGeometry::SetPos(const QPointF &ptPos) +{ + m_ptPos = ptPos; +} + +//--------------------------------------------------------------------------------------------------------------------- + +QString VGrainlineGeometry::GetLength() const +{ + return m_qsLength; +} + +//--------------------------------------------------------------------------------------------------------------------- + +void VGrainlineGeometry::SetLength(const QString& qsLen) +{ + m_qsLength = qsLen; +} + +//--------------------------------------------------------------------------------------------------------------------- + +QString VGrainlineGeometry::GetRotation() const +{ + return m_qsRotation; +} + +//--------------------------------------------------------------------------------------------------------------------- + +void VGrainlineGeometry::SetRotation(const QString& qsRot) +{ + m_qsRotation = qsRot; +} + +//--------------------------------------------------------------------------------------------------------------------- + +bool VGrainlineGeometry::IsVisible() const +{ + return m_bVisible; +} + +//--------------------------------------------------------------------------------------------------------------------- + +void VGrainlineGeometry::SetVisible(bool bVisible) +{ + m_bVisible = bVisible; +} + +//--------------------------------------------------------------------------------------------------------------------- + diff --git a/src/libs/vpatterndb/vgrainlinegeometry.h b/src/libs/vpatterndb/vgrainlinegeometry.h new file mode 100644 index 000000000..0b27c3adf --- /dev/null +++ b/src/libs/vpatterndb/vgrainlinegeometry.h @@ -0,0 +1,77 @@ +/************************************************************************ + ** + ** @file vgrainlinegeometry.h + ** @author Bojan Kverh + ** @date September 06, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VGRAINLINEGEOMETRY_H +#define VGRAINLINEGEOMETRY_H + +#include +#include + +class QPointF; + +/** + * @brief The VGrainlineGeometry class holds information about a grainline like + * position, size, rotation and visibility + */ +class VGrainlineGeometry +{ +public: + VGrainlineGeometry(); + ~VGrainlineGeometry(); + + // methods, which set and return values of different parameters + QPointF GetPos() const; + void SetPos(const QPointF& ptPos); + QString GetLength() const; + void SetLength(const QString& qsLen); + QString GetRotation() const; + void SetRotation(const QString& qsRot); + bool IsVisible() const; + void SetVisible(bool bVisible); + +private: + /** + * @brief m_ptPos position of grainline's center + */ + QPointF m_ptPos; + /** + * @brief m_dLength formula to calculate the length of grainline + */ + QString m_qsLength; + /** + * @brief m_dRotation formula to calculate the rotation of grainline in [degrees] + */ + QString m_qsRotation; + /** + * @brief m_bVisible visibility flag + */ + bool m_bVisible; +}; + +#endif // VGRAINLINEGEOMETRY_H + diff --git a/src/libs/vpatterndb/vpatterndb.pri b/src/libs/vpatterndb/vpatterndb.pri index 93f7d3490..c1ae5168a 100644 --- a/src/libs/vpatterndb/vpatterndb.pri +++ b/src/libs/vpatterndb/vpatterndb.pri @@ -20,6 +20,7 @@ SOURCES += \ $$PWD/vformula.cpp \ $$PWD/vpatternpiecedata.cpp \ $$PWD/vpatterninfogeometry.cpp \ + $$PWD/vgrainlinegeometry.cpp \ $$PWD/variables/vcurveclength.cpp win32-msvc*:SOURCES += $$PWD/stable.cpp @@ -55,4 +56,5 @@ HEADERS += \ $$PWD/vformula.h \ $$PWD/vpatternpiecedata.h \ $$PWD/vpatterninfogeometry.h \ + $$PWD/vgrainlinegeometry.h \ $$PWD/variables/vcurveclength.h diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.cpp b/src/libs/vtools/dialogs/tools/dialogdetail.cpp index 6ee916db0..e82f2e704 100644 --- a/src/libs/vtools/dialogs/tools/dialogdetail.cpp +++ b/src/libs/vtools/dialogs/tools/dialogdetail.cpp @@ -28,6 +28,7 @@ #include "dialogdetail.h" +#include #include #include #include @@ -60,10 +61,12 @@ #include "../ifc/xml/vdomdocument.h" #include "../vpatterndb/vcontainer.h" +#include "../vpatterndb/calculator.h" #include "../vgeometry/vgobject.h" #include "../vmisc/vabstractapplication.h" #include "dialogtool.h" #include "vnodedetail.h" +#include "../support/dialogeditwrongformula.h" class QPointF; class QWidget; @@ -76,7 +79,8 @@ class QWidget; */ DialogDetail::DialogDetail(const VContainer *data, const quint32 &toolId, QWidget *parent) :DialogTool(data, toolId, parent), ui(), detail(VDetail()), supplement(true), closed(true), flagWidth(true), - m_bAddMode(true), m_qslMaterials(), m_qslPlacements(), m_conMCP(), m_oldData(), m_oldGeom() + m_bAddMode(true), m_qslMaterials(), m_qslPlacements(), m_conMCP(), m_oldData(), m_oldGeom(), m_oldGrainline(), + m_iRotBaseHeight(0), m_iLenBaseHeight(0) { ui.setupUi(this); @@ -144,15 +148,30 @@ DialogDetail::DialogDetail(const VContainer *data, const quint32 &toolId, QWidge m_qslPlacements << tr("None") << tr("Cut on fold"); ui.comboBoxPlacement->addItems(m_qslPlacements); + ui.pushButtonRot->setIcon(QIcon("://icon/16x16/fx.png")); + ui.pushButtonLen->setIcon(QIcon("://icon/16x16/fx.png")); connect(ui.pushButtonAdd, &QPushButton::clicked, this, &DialogDetail::AddUpdate); connect(ui.pushButtonCancel, &QPushButton::clicked, this, &DialogDetail::Cancel); connect(ui.pushButtonRemove, &QPushButton::clicked, this, &DialogDetail::Remove); connect(ui.listWidgetMCP, &QListWidget::itemClicked, this, &DialogDetail::SetEditMode); connect(ui.comboBoxMaterial, &QComboBox::currentTextChanged, this, &DialogDetail::MaterialChanged); + connect(ui.checkBoxGrainline, &QCheckBox::toggled, this, &DialogDetail::EnableGrainlineRotation); + connect(ui.pushButtonRot, &QPushButton::clicked, this, &DialogDetail::EditFormula); + connect(ui.pushButtonLen, &QPushButton::clicked, this, &DialogDetail::EditFormula); + connect(ui.lineEditLenFormula, &QPlainTextEdit::textChanged, this, &DialogDetail::UpdateValues); + connect(ui.lineEditRotFormula, &QPlainTextEdit::textChanged, this, &DialogDetail::UpdateValues); + + connect(ui.pushButtonShowRot, &QPushButton::clicked, this, &DialogDetail::DeployRotation); + connect(ui.pushButtonShowLen, &QPushButton::clicked, this, &DialogDetail::DeployLength); + SetAddMode(); + EnableGrainlineRotation(); ui.tabWidget->setCurrentIndex(0); + + m_iRotBaseHeight = ui.lineEditRotFormula->height(); + m_iLenBaseHeight = ui.lineEditLenFormula->height(); } //--------------------------------------------------------------------------------------------------------------------- @@ -463,6 +482,10 @@ VDetail DialogDetail::CreateDetail() const detail.GetPatternInfo() = m_oldGeom; detail.GetPatternInfo().SetVisible(ui.checkBoxPattern->isChecked()); + detail.GetGrainlineGeometry() = m_oldGrainline; + detail.GetGrainlineGeometry().SetVisible(ui.checkBoxGrainline->isChecked()); + detail.GetGrainlineGeometry().SetRotation(ui.lineEditRotFormula->toPlainText()); + detail.GetGrainlineGeometry().SetLength(ui.lineEditLenFormula->toPlainText()); return detail; } @@ -532,10 +555,17 @@ void DialogDetail::setDetail(const VDetail &value) } UpdateList(); + + ui.checkBoxGrainline->setChecked(detail.GetGrainlineGeometry().IsVisible()); + ui.lineEditRotFormula->setPlainText(detail.GetGrainlineGeometry().GetRotation()); + ui.lineEditLenFormula->setPlainText(detail.GetGrainlineGeometry().GetLength()); + m_oldData = detail.GetPatternPieceData(); m_oldGeom = detail.GetPatternInfo(); + m_oldGrainline = detail.GetGrainlineGeometry(); ValidObjects(DetailIsValid()); + EnableGrainlineRotation(); } //--------------------------------------------------------------------------------------------------------------------- @@ -801,6 +831,83 @@ void DialogDetail::ClearFields() ui.comboBoxPlacement->setCurrentIndex(0); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogDetail::UpdateValues() +{ + QPlainTextEdit* apleSender[2]; + apleSender[0] = ui.lineEditRotFormula; + apleSender[1] = ui.lineEditLenFormula; + bool bFormulasOK = true; + + for (int i = 0; i < 2; ++i) + { + QLabel* plbVal; + QLabel* plbText; + QString qsUnit; + if (i == 0) + { + plbVal = ui.labelRot; + plbText = ui.labelEditRot; + QChar ch(0x00b0); + qsUnit = ch; + } + else + { + plbVal = ui.labelLen; + plbText = ui.labelEditLen; + qsUnit = " " + VDomDocument::UnitsToStr(qApp->patternUnit()); + } + + QString qsFormula = apleSender[i]->toPlainText().simplified(); + Calculator cal; + QString qsVal; + try + { + qsFormula.replace("\n", " "); + qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator()); + qreal dVal; + dVal = cal.EvalFormula(data->PlainVariables(), qsFormula); + if (qIsInf(dVal) == true || qIsNaN(dVal) == true) + { + throw qmu::QmuParserError(tr("Infinite/undefined result")); + } + else if (i == 1 && dVal <= 0.0) + { + throw qmu::QmuParserError(tr("Length should be positive")); + } + else + { + qsVal.setNum(dVal, 'f', 2); + ChangeColor(plbText, okColor); + } + } + catch (...) + { + qsVal.clear(); + ChangeColor(plbText, Qt::red); + bFormulasOK = false; + } + + if (qsVal.isEmpty() == false) + { + qsVal += qsUnit; + } + plbVal->setText(qsVal); + } + + bOk->setEnabled(bFormulasOK); + if (bFormulasOK == false) + { + QIcon icon(":/icons/win.icon.theme/16x16/status/dialog-warning.png"); + ui.tabWidget->setTabIcon(2, icon); + } + else + { + QIcon icon; + ui.tabWidget->setTabIcon(2, icon); + } +} + //--------------------------------------------------------------------------------------------------------------------- void DialogDetail::SetAddMode() { @@ -847,3 +954,73 @@ void DialogDetail::SetEditMode() m_bAddMode = false; } + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDetail::EnableGrainlineRotation() +{ + ui.lineEditRotFormula->setEnabled(ui.checkBoxGrainline->isChecked()); + ui.lineEditLenFormula->setEnabled(ui.checkBoxGrainline->isChecked()); + ui.pushButtonRot->setEnabled(ui.checkBoxGrainline->isChecked()); + ui.pushButtonLen->setEnabled(ui.checkBoxGrainline->isChecked()); + ui.pushButtonShowLen->setEnabled(ui.checkBoxGrainline->isChecked()); + ui.pushButtonShowRot->setEnabled(ui.checkBoxGrainline->isChecked()); + + if (ui.checkBoxGrainline->isChecked() == true) + { + UpdateValues(); + } + else + { + ChangeColor(ui.labelEditLen, okColor); + ChangeColor(ui.labelEditRot, okColor); + bOk->setEnabled(true); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDetail::EditFormula() +{ + QPlainTextEdit* pleFormula; + bool bCheckZero; + + if (sender() == ui.pushButtonLen) + { + pleFormula = ui.lineEditLenFormula; + bCheckZero = true; + } + else if (sender() == ui.pushButtonRot) + { + pleFormula = ui.lineEditRotFormula; + bCheckZero = false; + } + else + { + // should not get here! + return; + } + + DialogEditWrongFormula dlg(data, NULL_ID, this); + dlg.SetFormula(pleFormula->toPlainText()); + dlg.setCheckZero(bCheckZero); + if (dlg.exec() == true) + { + QString qsFormula = dlg.GetFormula(); + qsFormula.replace("\n", " "); + pleFormula->setPlainText(qsFormula); + UpdateValues(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDetail::DeployRotation() +{ + DeployFormula(ui.lineEditRotFormula, ui.pushButtonShowRot, m_iRotBaseHeight); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogDetail::DeployLength() +{ + DeployFormula(ui.lineEditLenFormula, ui.pushButtonShowLen, m_iLenBaseHeight); +} + +//--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.h b/src/libs/vtools/dialogs/tools/dialogdetail.h index 26dbe48a0..c40cb37a6 100644 --- a/src/libs/vtools/dialogs/tools/dialogdetail.h +++ b/src/libs/vtools/dialogs/tools/dialogdetail.h @@ -40,6 +40,7 @@ #include "../vpatterndb/vdetail.h" #include "../vpatterndb/vpatterninfogeometry.h" #include "../vpatterndb/vpatternpiecedata.h" +#include "../vpatterndb/vgrainlinegeometry.h" #include "dialogtool.h" #include "ui_dialogdetail.h" @@ -107,6 +108,9 @@ private: MCPContainer m_conMCP; VPatternPieceData m_oldData; VPatternInfoGeometry m_oldGeom; + VGrainlineGeometry m_oldGrainline; + int m_iRotBaseHeight; + int m_iLenBaseHeight; bool DetailIsValid() const; @@ -124,8 +128,13 @@ private: quint32 RowId(int i) const; private slots: + void UpdateValues(); void SetAddMode(); void SetEditMode(); + void EnableGrainlineRotation(); + void EditFormula(); + void DeployRotation(); + void DeployLength(); }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/dialogs/tools/dialogdetail.ui b/src/libs/vtools/dialogs/tools/dialogdetail.ui index be5300e33..9adf0b18d 100644 --- a/src/libs/vtools/dialogs/tools/dialogdetail.ui +++ b/src/libs/vtools/dialogs/tools/dialogdetail.ui @@ -7,7 +7,7 @@ 0 0 581 - 468 + 478 @@ -24,7 +24,7 @@ - 0 + 2 @@ -318,7 +318,8 @@ - .. + + @@ -332,7 +333,8 @@ - .. + + @@ -526,6 +528,445 @@ + + + ArrowCursor + + + Grainline + + + + + 10 + 10 + 541 + 41 + + + + + + + Grainline visible + + + + + + + + + 10 + 60 + 541 + 41 + + + + + + + + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 159 + 158 + 158 + + + + + + + + Rotation: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Formula wizard + + + ... + + + + :/icon/24x24/fx.png:/icon/24x24/fx.png + + + + 24 + 24 + + + + + + + + + + + :/icon/24x24/equal.png + + + + + + + + 0 + 0 + + + + + 87 + 0 + + + + + 0 + 0 + + + + Value + + + _ + + + + + + + + + 10 + 110 + 541 + 41 + + + + + + + + 0 + 0 + + + + + 16777215 + 28 + + + + Calculation + + + true + + + + + + + + + + + 18 + 18 + + + + + 0 + 0 + + + + <html><head/><body><p>Show full calculation in message box</p></body></html> + + + + + + + + + + + + 16 + 16 + + + + true + + + + + + + + + 10 + 160 + 541 + 41 + + + + + + + + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 159 + 158 + 158 + + + + + + + + Length: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Formula wizard + + + ... + + + + :/icon/24x24/fx.png:/icon/24x24/fx.png + + + + 24 + 24 + + + + + + + + + + + :/icon/24x24/equal.png + + + + + + + + 0 + 0 + + + + + 87 + 0 + + + + + 0 + 0 + + + + Value + + + _ + + + + + + + + + 10 + 210 + 541 + 41 + + + + + + + + 0 + 0 + + + + + 16777215 + 28 + + + + Calculation + + + true + + + + + + + + + + + 18 + 18 + + + + + 0 + 0 + + + + <html><head/><body><p>Show full calculation in message box</p></body></html> + + + + + + + + + + + + 16 + 16 + + + + true + + + + + + @@ -539,11 +980,8 @@ - buttonBox - tabWidget - lineEditLetter lineEditName comboBoxMaterial spinBoxCutNumber @@ -551,8 +989,6 @@ pushButtonAdd pushButtonCancel pushButtonRemove - listWidgetMCP - buttonBox toolButtonUp listWidget checkBoxClosed @@ -563,6 +999,10 @@ checkBoxSeams doubleSpinBoxSeams toolButtonDown + checkBoxForbidFlipping + checkBoxDetail + checkBoxPattern + lineEditLetter diff --git a/src/libs/vtools/dialogs/tools/dialogtool.cpp b/src/libs/vtools/dialogs/tools/dialogtool.cpp index 3b844a682..4e6a92039 100644 --- a/src/libs/vtools/dialogs/tools/dialogtool.cpp +++ b/src/libs/vtools/dialogs/tools/dialogtool.cpp @@ -469,8 +469,11 @@ void DialogTool::ValFormulaChanged(bool &flag, QPlainTextEdit *edit, QTimer *tim */ qreal DialogTool::Eval(const QString &text, bool &flag, QLabel *label, const QString& postfix, bool checkZero) { + qDebug() << "Eval started"; SCASSERT(label != nullptr); + qDebug() << "Label ok"; SCASSERT(labelEditFormula != nullptr); + qDebug() << "lef ok"; qreal result = INT_MIN;//Value can be 0, so use max imposible value diff --git a/src/libs/vtools/tools/tools.pri b/src/libs/vtools/tools/tools.pri index 7f0366f5d..4f4536aae 100644 --- a/src/libs/vtools/tools/tools.pri +++ b/src/libs/vtools/tools/tools.pri @@ -52,6 +52,7 @@ HEADERS += \ $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.h \ $$PWD/drawTools/operation/vtoolrotation.h \ $$PWD/vtextgraphicsitem.h \ + $$PWD/vgrainlineitem.h \ $$PWD/drawTools/operation/flipping/vtoolflippingbyline.h \ $$PWD/drawTools/operation/vabstractoperation.h \ $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.h \ @@ -106,6 +107,7 @@ SOURCES += \ $$PWD/drawTools/toolcurve/vtoolcubicbezierpath.cpp \ $$PWD/drawTools/operation/vtoolrotation.cpp \ $$PWD/vtextgraphicsitem.cpp \ + $$PWD/vgrainlineitem.cpp \ $$PWD/drawTools/operation/flipping/vtoolflippingbyline.cpp \ $$PWD/drawTools/operation/vabstractoperation.cpp \ $$PWD/drawTools/operation/flipping/vtoolflippingbyaxis.cpp \ diff --git a/src/libs/vtools/tools/vgrainlineitem.cpp b/src/libs/vtools/tools/vgrainlineitem.cpp new file mode 100644 index 000000000..ff4ae9bed --- /dev/null +++ b/src/libs/vtools/tools/vgrainlineitem.cpp @@ -0,0 +1,585 @@ +/************************************************************************ + ** + ** @file vgrainlineitem.cpp + ** @author Bojan Kverh + ** @date September 10, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "../vmisc/def.h" +#include "../vmisc/vmath.h" + +#include "vgrainlineitem.h" + +#define ARROW_ANGLE M_PI/9 +#define ARROW_LENGTH 15 +#define RECT_WIDTH 30 +#define RESIZE_RECT_SIZE 10 +#define ROTATE_CIRC_R 7 +#define ACTIVE_Z 10 +#define INACTIVE_Z 5 + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::VGrainlineItem constructor + * @param pParent pointer to the parent item + */ +VGrainlineItem::VGrainlineItem(QGraphicsItem* pParent) + :QGraphicsObject(pParent), m_eMode(VGrainlineItem::mNormal), m_bReleased(false), m_dRotation(0), m_dStartRotation(0), + m_dLength(0), m_rectBoundingBox(), m_polyBound(), m_ptStartPos(), m_ptStartMove(), m_dScale(1), m_polyResize(), + m_ptStart(), m_ptFinish(), m_ptCenter(), m_dAngle(0) +{ + m_rectBoundingBox.setTopLeft(QPointF(0, 0)); + setAcceptHoverEvents(true); + Reset(); + UpdateRectangle(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::~VGrainlineItem destructor + */ +VGrainlineItem::~VGrainlineItem() +{} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::paint paints the item content + * @param pP pointer to the painter object + * @param pOption not used + * @param pWidget not used + */ +void VGrainlineItem::paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget) +{ + Q_UNUSED(pOption); + Q_UNUSED(pWidget); + pP->save(); + QColor clr = Qt::black; + pP->setPen(QPen(clr, 3)); + QPointF pt1(0, 0); + QPointF pt2; + + pt2.setX(pt1.x() + m_dLength * cos(m_dRotation)); + pt2.setY(pt1.y() - m_dLength * sin(m_dRotation)); + + pP->setRenderHints(QPainter::Antialiasing); + // line + pP->drawLine(pt1, pt2); + + // first arrow + QPolygonF poly; + poly << pt1; + QPointF ptA; + qreal dArrLen = ARROW_LENGTH*m_dScale; + ptA.setX(pt1.x() + dArrLen*cos(m_dRotation + ARROW_ANGLE)); + ptA.setY(pt1.y() - dArrLen*sin(m_dRotation + ARROW_ANGLE)); + poly << ptA; + ptA.setX(pt1.x() + dArrLen*cos(m_dRotation - ARROW_ANGLE)); + ptA.setY(pt1.y() - dArrLen*sin(m_dRotation - ARROW_ANGLE)); + poly << ptA; + pP->setBrush(clr); + pP->drawPolygon(poly); + // second arrow + poly.clear(); + poly << pt2; + ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation + ARROW_ANGLE)); + ptA.setY(pt2.y() - dArrLen*sin(M_PI + m_dRotation + ARROW_ANGLE)); + poly << ptA; + ptA.setX(pt2.x() + dArrLen*cos(M_PI + m_dRotation - ARROW_ANGLE)); + ptA.setY(pt2.y() - dArrLen*sin(M_PI + m_dRotation - ARROW_ANGLE)); + poly << ptA; + pP->drawPolygon(poly); + + if (m_eMode != mNormal) + { + pP->setPen(QPen(clr, 2, Qt::DashLine)); + pP->setBrush(Qt::NoBrush); + // bounding polygon + pP->drawPolygon(m_polyBound); + pP->setPen(QPen(clr, 3)); + + if (m_eMode != mRotate) + { + pP->setBrush(clr); + pP->drawPolygon(m_polyResize); + } + + pP->setBrush(Qt::NoBrush); + if (m_eMode == mResize) + { + pP->setPen(clr); + pP->drawLine(m_polyBound.at(0), m_polyBound.at(2)); + pP->drawLine(m_polyBound.at(1), m_polyBound.at(3)); + } + + if (m_eMode == mRotate) + { + QPointF ptC = (m_polyBound.at(0) + m_polyBound.at(2))/2; + qreal dRad = m_dScale * ROTATE_CIRC_R; + pP->setBrush(clr); + pP->drawEllipse(ptC, dRad, dRad); + + pP->setBrush(Qt::NoBrush); + pP->save(); + pP->translate(ptC); + pP->rotate(qRadiansToDegrees(-m_dRotation)); + int iX = int(qRound(m_dLength/2 - 0.5*dRad)); + int iY = int(qRound(RECT_WIDTH - 0.5*dRad)); + int iR = int(qRound(dRad*3)); + pP->drawArc(iX - iR, iY - iR, iR, iR, 0*16, -90*16); + pP->drawArc(-iX, iY - iR, iR, iR, 270*16, -90*16); + pP->drawArc(-iX, -iY, iR, iR, 180*16, -90*16); + pP->drawArc(iX - iR, -iY, iR, iR, 90*16, -90*16); + pP->restore(); + } + + } + pP->restore(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::UpdateGeometry updates the item with grainline parameters + * @param ptPos position of one grainline's end + * @param dRotation rotation of the grainline in [degrees] + * @param dLength length of the grainline in user's units + */ +void VGrainlineItem::UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength) +{ + m_dRotation = qDegreesToRadians(dRotation); + m_dLength = dLength; + + qreal dX; + qreal dY; + QPointF pt = ptPos; + if (IsContained(pt, m_dRotation, dX, dY) == false) + { + pt.setX(pt.x() + dX); + pt.setY(pt.y() + dY); + } + setPos(pt); + UpdateRectangle(); + UpdateBox(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::boundingRect returns the bounding rect around the grainline + * @return bounding rect + */ +QRectF VGrainlineItem::boundingRect() const +{ + return m_rectBoundingBox; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::Reset resets the item parameters. + */ +void VGrainlineItem::Reset() +{ + m_bReleased = false; + m_eMode = mNormal; + setZValue(INACTIVE_Z); + UpdateBox(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::IsIdle returns the idle flag. + * @return true, if item mode is normal and false otherwise. + */ +bool VGrainlineItem::IsIdle() const +{ + return m_eMode == mNormal; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::IsContained checks, if both ends of the grainline, starting at pt, are contained in + * parent widget. + * @param pt starting point of the grainline. + * @param dRot rotation of the grainline in [rad] + * @param dX horizontal translation needed to put the arrow inside parent item + * @param dY vertical translation needed to put the arrow inside parent item + * @return true, if both ends of the grainline, starting at pt, are contained in the parent widget and + * false otherwise. + */ +bool VGrainlineItem::IsContained(const QPointF& pt, qreal dRot, qreal &dX, qreal &dY) const +{ + dX = 0; + dY = 0; + QPointF apt[2]; + apt[0] = pt; + apt[1].setX(pt.x() + m_dLength * cos(dRot)); + apt[1].setY(pt.y() - m_dLength * sin(dRot)); + // single point differences + qreal dPtX; + qreal dPtY; + bool bInside = true; + + QRectF rectParent = parentItem()->boundingRect(); + for (int i = 0; i < 2; ++i) + { + dPtX = 0; + dPtY = 0; + if (rectParent.contains(apt[i]) == false) + { + if (apt[i].x() < rectParent.left()) + { + dPtX = rectParent.left() - apt[i].x(); + } + else if (apt[i].x() > rectParent.right()) + { + dPtX = rectParent.right() - apt[i].x(); + } + if (apt[i].y() < rectParent.top()) + { + dPtY = rectParent.top() - apt[i].y(); + } + else if (apt[i].y() > rectParent.bottom()) + { + dPtY = rectParent.bottom() - apt[i].y(); + } + + if (fabs(dPtX) > fabs(dX)) + { + dX = dPtX; + } + if (fabs(dPtY) > fabs(dY)) + { + dY = dPtY; + } + + bInside = false; + } + } + return bInside; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::SetScale sets the scale for keeping the arrows of constant size + * @param dScale scale factor + */ +void VGrainlineItem::SetScale(qreal dScale) +{ + m_dScale = dScale; + UpdateRectangle(); + UpdateBox(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::mousePressEvent handles left button mouse press events + * @param pME pointer to QGraphicsSceneMouseEvent object + */ +void VGrainlineItem::mousePressEvent(QGraphicsSceneMouseEvent* pME) +{ + if (pME->button() == Qt::LeftButton) + { + m_ptStartPos = pos(); + m_ptStartMove = pME->scenePos(); + m_dStartLength = m_dLength; + m_dStartRotation = m_dRotation; + m_dAngle = GetAngle(mapToParent(pME->pos())); + m_ptRotCenter = m_ptCenter; + + if (m_eMode != mRotate) + { + if (m_polyResize.containsPoint(pME->pos(), Qt::OddEvenFill) == true) + { + m_eMode = mResize; + SetOverrideCursor(Qt::SizeFDiagCursor); + } + else + { + m_eMode = mMove; + SetOverrideCursor(cursorArrowCloseHand, 1, 1); + } + } + else + { + SetOverrideCursor(cursorArrowCloseHand, 1, 1); + } + setZValue(ACTIVE_Z); + UpdateBox(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::mouseMoveEvent handles mouse move events, making sure that the item is moved properly + * @param pME pointer to QGraphicsSceneMouseEvent object + */ +void VGrainlineItem::mouseMoveEvent(QGraphicsSceneMouseEvent* pME) +{ + QPointF ptDiff = pME->scenePos() - m_ptStartMove; + qreal dX; + qreal dY; + if (m_eMode == mMove) + { + QPointF pt = m_ptStartPos + ptDiff; + if (IsContained(pt, m_dRotation, dX, dY) == false) + { + pt.setX(pt.x() + dX); + pt.setY(pt.y() + dY); + } + setPos(pt); + UpdateBox(); + } + else if (m_eMode == mResize) + { + qreal dLen = qSqrt(ptDiff.x()*ptDiff.x() + ptDiff.y()*ptDiff.y()); + qreal dAng = qAtan2(-ptDiff.y(), ptDiff.x()); + dLen = dLen*qCos(dAng - m_dRotation); + qreal dPrevLen = m_dLength; + // try with new length + m_dLength = m_dStartLength + dLen; + qreal dX; + qreal dY; + if (IsContained(m_ptStartPos, m_dRotation, dX, dY) == false) + { + m_dLength = dPrevLen; + } + UpdateRectangle(); + UpdateBox(); + } + else if (m_eMode == mRotate) + { + // prevent strange angle changes due to singularities + qreal dLen = qSqrt(ptDiff.x()*ptDiff.x() + ptDiff.y()*ptDiff.y()); + if (dLen < 2) + { + return; + } + + if (fabs(m_dAngle) < 0.01) + { + m_dAngle = GetAngle(mapToParent(pME->pos())); + return; + } + + qreal dAng = GetAngle(mapToParent(pME->pos())) - m_dAngle; + QPointF ptNewPos = Rotate(m_ptStartPos, m_ptRotCenter, dAng); + if (IsContained(ptNewPos, m_dStartRotation + dAng, dX, dY) == true) + { + setPos(ptNewPos); + m_dRotation = m_dStartRotation + dAng; + UpdateRectangle(); + UpdateBox(); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::mouseReleaseEvent handles mouse release events and emits the proper signal if the item was + * moved + * @param pME pointer to QGraphicsSceneMouseEvent object + */ +void VGrainlineItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* pME) +{ + if (pME->button() == Qt::LeftButton) + { + if (m_eMode == mMove || m_eMode == mRotate) + { + RestoreOverrideCursor(cursorArrowCloseHand); + } + else if (m_eMode == mResize) + { + RestoreOverrideCursor(Qt::SizeFDiagCursor); + } + + QPointF ptDiff = pME->scenePos() - m_ptStartMove; + qreal dLen = qSqrt(ptDiff.x()*ptDiff.x() + ptDiff.y()*ptDiff.y()); + bool bShort = (dLen < 2); + + if (m_eMode == mMove || m_eMode == mResize) + { + if (bShort == true) + { + if (m_bReleased == true) + { + m_eMode = mRotate; + UpdateBox(); + } + } + else + { + if (m_eMode == mMove) + { + emit SignalMoved(pos()); + } + else + { + emit SignalResized(m_dLength); + } + UpdateBox(); + } + } + else + { + if (bShort == true) + { + m_eMode = mMove; + } + else + { + emit SignalRotated(m_dRotation, m_ptStart); + } + UpdateBox(); + } + m_bReleased = true; + } +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::UpdateBox updates the item + */ +void VGrainlineItem::UpdateBox() +{ + update(m_rectBoundingBox); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::UpdateRectangle updates the polygon for the box around active item + * and the bounding rectangle + */ +void VGrainlineItem::UpdateRectangle() +{ + m_polyBound.clear(); + QPointF pt1(0, 0); + QPointF pt2; + + pt2.setX(pt1.x() + m_dLength * cos(m_dRotation)); + pt2.setY(pt1.y() - m_dLength * sin(m_dRotation)); + + m_ptStart = mapToParent(pt1); + m_ptFinish = mapToParent(pt2); + m_ptCenter = (m_ptStart + m_ptFinish)/2; + + QPointF ptA; + ptA.setX(pt1.x() + RECT_WIDTH*cos(m_dRotation + M_PI/2)); + ptA.setY(pt1.y() - RECT_WIDTH*sin(m_dRotation + M_PI/2)); + m_polyBound << ptA; + ptA.setX(pt1.x() + RECT_WIDTH*cos(m_dRotation - M_PI/2)); + ptA.setY(pt1.y() - RECT_WIDTH*sin(m_dRotation - M_PI/2)); + m_polyBound << ptA; + ptA.setX(pt2.x() + RECT_WIDTH*cos(m_dRotation - M_PI/2)); + ptA.setY(pt2.y() - RECT_WIDTH*sin(m_dRotation - M_PI/2)); + m_polyBound << ptA; + ptA.setX(pt2.x() + RECT_WIDTH*cos(m_dRotation + M_PI/2)); + ptA.setY(pt2.y() - RECT_WIDTH*sin(m_dRotation + M_PI/2)); + m_polyBound << ptA; + m_rectBoundingBox = m_polyBound.boundingRect(); + setTransformOriginPoint(m_rectBoundingBox.center()); + + m_polyResize.clear(); + ptA = m_polyBound.at(2); + m_polyResize << ptA; + double dSize = m_dScale * RESIZE_RECT_SIZE; + + ptA.setX(ptA.x() + dSize*cos(m_dRotation + M_PI/2)); + ptA.setY(ptA.y() - dSize*sin(m_dRotation + M_PI/2)); + m_polyResize << ptA; + + ptA.setX(ptA.x() - dSize*cos(m_dRotation)); + ptA.setY(ptA.y() + dSize*sin(m_dRotation)); + m_polyResize << ptA; + + ptA.setX(ptA.x() + dSize*cos(m_dRotation - M_PI/2)); + ptA.setY(ptA.y() - dSize*sin(m_dRotation - M_PI/2)); + m_polyResize << ptA; + + prepareGeometryChange(); +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::GetAngle calculates the angle between the line, which goes from + * rotation center to pt and x axis + * @param pt point of interest + * @return the angle between line from rotation center and point of interest and x axis + */ +qreal VGrainlineItem::GetAngle(const QPointF& pt) const +{ + double dX = pt.x() - m_ptRotCenter.x(); + double dY = pt.y() - m_ptRotCenter.y(); + + if (fabs(dX) < 1 && fabs(dY) < 1) + { + return 0; + } + else + { + return qAtan2(-dY, dX); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::Rotate rotates point pt around ptCenter by angle dAng [rad] + * and returns the resulting point + * @param pt point to rotate + * @param ptCenter center of rotation + * @param dAng angle of rotation + * @return point, which is a result of rotating pt around ptCenter by angle dAng + */ +QPointF VGrainlineItem::Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const +{ + QPointF ptRel = pt - ptCenter; + QPointF ptFinal; + ptFinal.setX(ptRel.x()*qCos(dAng) + ptRel.y()*qSin(dAng)); + ptFinal.setY(-ptRel.x()*qSin(dAng) + ptRel.y()*qCos(dAng)); + ptFinal += ptCenter; + return ptFinal; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VGrainlineItem::GetInsideCorner calculates a point inside the bounding polygon, + * dDist away of i-th point in each direction + * @param i index of corner + * @param dDist distance + * @return resulting point + */ +QPointF VGrainlineItem::GetInsideCorner(int i, qreal dDist) const +{ + QPointF pt1 = m_polyBound.at((i + 1) % m_polyBound.count()) - m_polyBound.at(i); + QPointF pt2 = m_polyBound.at((i + m_polyBound.count() - 1) % m_polyBound.count()) - m_polyBound.at(i); + + pt1 = dDist*pt1/qSqrt(pt1.x()*pt1.x() + pt1.y()*pt1.y()); + pt2 = dDist*pt2/qSqrt(pt2.x()*pt2.x() + pt2.y()*pt2.y()); + + return m_polyBound.at(i) + pt1 + pt2; +} diff --git a/src/libs/vtools/tools/vgrainlineitem.h b/src/libs/vtools/tools/vgrainlineitem.h new file mode 100644 index 000000000..30b4f36c6 --- /dev/null +++ b/src/libs/vtools/tools/vgrainlineitem.h @@ -0,0 +1,101 @@ +/************************************************************************ + ** + ** @file vgrainlineitem.h + ** @author Bojan Kverh + ** @date September 10, 2016 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2013-2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VGRAINLINEITEM_H +#define VGRAINLINEITEM_H + +#include + +#include "../vpatterndb/vgrainlinegeometry.h" + +class QGraphicsObject; +class QPainter; +class QStyleOptionGraphicsItem; +class QWidget; + +class VGrainlineItem : public QGraphicsObject +{ + Q_OBJECT + + enum Mode { + mNormal, + mMove, + mResize, + mRotate + }; + +public: + explicit VGrainlineItem(QGraphicsItem* pParent = nullptr); + virtual ~VGrainlineItem(); + + void paint(QPainter* pP, const QStyleOptionGraphicsItem* pOption, QWidget* pWidget); + void UpdateGeometry(const QPointF& ptPos, qreal dRotation, qreal dLength); + + QRectF boundingRect() const; + void Reset(); + bool IsIdle() const; + bool IsContained(const QPointF &pt, qreal dRot, qreal &dX, qreal &dY) const; + void SetScale(qreal dScale); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent* pME); + void mouseMoveEvent(QGraphicsSceneMouseEvent* pME); + void mouseReleaseEvent(QGraphicsSceneMouseEvent* pME); + void UpdateBox(); + void UpdateRectangle(); + + qreal GetAngle(const QPointF& pt) const; + QPointF Rotate(const QPointF& pt, const QPointF& ptCenter, qreal dAng) const; + QPointF GetInsideCorner(int i, qreal dDist) const; + +signals: + void SignalMoved(const QPointF& ptPos); + void SignalResized(qreal dLength); + void SignalRotated(qreal dRot, const QPointF& ptNewPos); + +private: + Mode m_eMode; + bool m_bReleased; + qreal m_dRotation; + qreal m_dStartRotation; + qreal m_dLength; + QRectF m_rectBoundingBox; + QPolygonF m_polyBound; + QPointF m_ptStartPos; + QPointF m_ptStartMove; + qreal m_dScale; + QPolygonF m_polyResize; + qreal m_dStartLength; + QPointF m_ptStart; + QPointF m_ptFinish; + QPointF m_ptCenter; + QPointF m_ptRotCenter; + qreal m_dAngle; +}; + +#endif // VGRAINLINEITEM_H diff --git a/src/libs/vtools/tools/vtextgraphicsitem.cpp b/src/libs/vtools/tools/vtextgraphicsitem.cpp index 7a491b4e6..4fb029650 100644 --- a/src/libs/vtools/tools/vtextgraphicsitem.cpp +++ b/src/libs/vtools/tools/vtextgraphicsitem.cpp @@ -1,6 +1,6 @@ /************************************************************************ ** - ** @file vtextgraphicsitem.h + ** @file vtextgraphicsitem.cpp ** @author Bojan Kverh ** @date June 16, 2016 ** @@ -55,7 +55,8 @@ class VPatternPieceData; #define ROTATE_ARC 50 #define MIN_W 120 #define MIN_H 60 -#define TOP_Z 2 +#define INACTIVE_Z 2 +#define ACTIVE_Z 10 //--------------------------------------------------------------------------------------------------------------------- /** @@ -69,7 +70,7 @@ VTextGraphicsItem::VTextGraphicsItem(QGraphicsItem* pParent) { m_rectBoundingBox.setTopLeft(QPointF(0, 0)); SetSize(MIN_W, m_iMinH); - setZValue(TOP_Z); + setZValue(INACTIVE_Z); setAcceptHoverEvents(true); } @@ -173,7 +174,7 @@ void VTextGraphicsItem::Reset() m_eMode = mNormal; m_bReleased = false; Update(); - setZValue(TOP_Z); + setZValue(INACTIVE_Z); } //--------------------------------------------------------------------------------------------------------------------- @@ -195,13 +196,21 @@ bool VTextGraphicsItem::IsIdle() const void VTextGraphicsItem::AddLine(const TextLine& tl) { m_tm.AddLine(tl); - while (m_tm.IsBigEnough(MIN_W, m_iMinH, MIN_FONT_SIZE) == false) + qreal fW = MIN_W; + qreal fH = m_iMinH; + qreal fMinW; + qreal fMinH; + while (m_tm.IsBigEnough(fW, fH, MIN_FONT_SIZE, fMinW, fMinH) == false) { - m_iMinH += 5; + SetSize(fMinW, fMinH); + fW = m_rectBoundingBox.width(); + fH = m_rectBoundingBox.height(); } - if (m_rectBoundingBox.height() < m_iMinH) + qreal dX; + qreal dY; + if (IsContained(m_rectBoundingBox, rotation(), dX, dY) == false) { - SetSize(m_rectBoundingBox.width(), m_iMinH); + setPos(m_rectBoundingBox.left() + dX, m_rectBoundingBox.top() + dY); } } @@ -258,11 +267,11 @@ void VTextGraphicsItem::SetSize(qreal fW, qreal fH) //--------------------------------------------------------------------------------------------------------------------- /** - * @brief VTextGraphicsItem::Update sets the correct font size and redraws the label + * @brief VTextGraphicsItem::Update sets the correct size and font size and redraws the label */ void VTextGraphicsItem::Update() { - UpdateFont(); + CorrectLabel(); UpdateBox(); } @@ -399,7 +408,7 @@ void VTextGraphicsItem::mousePressEvent(QGraphicsSceneMouseEvent *pME) SetOverrideCursor(cursorArrowCloseHand, 1, 1); } // raise the label and redraw it - setZValue(TOP_Z + 1); + setZValue(ACTIVE_Z); UpdateBox(); } } @@ -576,19 +585,41 @@ void VTextGraphicsItem::UpdateBox() * @brief VTextGraphicsItem::UpdateFont sets the text font size, so that the entire text will * just fit into the label bounding box */ -void VTextGraphicsItem::UpdateFont() +void VTextGraphicsItem::CorrectLabel() { int iFS = m_tm.GetFont().pixelSize(); + qreal fMinW; + qreal fMinH; // increase the font size until the bounding rect is not big enough - while (iFS < MAX_FONT_SIZE && m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == true) + while ( + iFS < MAX_FONT_SIZE && + m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS, fMinW, fMinH) == true + ) { ++iFS; } // decrease the font size until the bounding rect is big enough - while (iFS >= MIN_FONT_SIZE && m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS) == false) + while (m_tm.IsBigEnough(m_rectBoundingBox.width(), m_rectBoundingBox.height(), iFS, fMinW, fMinH) == false) { - --iFS; + if (iFS > MIN_FONT_SIZE) + { + --iFS; + } + else + { + SetSize(fMinW, fMinH); + } + } + qreal dX; + qreal dY; + QRectF rectBB; + rectBB.setTopLeft(pos()); + rectBB.setSize(m_rectBoundingBox.size()); + if (IsContained(rectBB, rotation(), dX, dY) == false) + { + // put the label inside the pattern + setPos(pos().x() + dX, pos().y() + dY); } m_tm.SetFontSize(iFS); UpdateBox(); diff --git a/src/libs/vtools/tools/vtextgraphicsitem.h b/src/libs/vtools/tools/vtextgraphicsitem.h index fdd451820..88e0eb460 100644 --- a/src/libs/vtools/tools/vtextgraphicsitem.h +++ b/src/libs/vtools/tools/vtextgraphicsitem.h @@ -98,7 +98,7 @@ protected: void hoverMoveEvent(QGraphicsSceneHoverEvent* pHE); void hoverLeaveEvent(QGraphicsSceneHoverEvent* pHE); void UpdateBox(); - void UpdateFont(); + void CorrectLabel(); double GetAngle(QPointF pt) const; diff --git a/src/libs/vtools/tools/vtooldetail.cpp b/src/libs/vtools/tools/vtooldetail.cpp index ccfbf855f..7694f92cf 100644 --- a/src/libs/vtools/tools/vtooldetail.cpp +++ b/src/libs/vtools/tools/vtooldetail.cpp @@ -90,6 +90,7 @@ #include "../vpatterndb/vdetail.h" #include "../vpatterndb/vpatterninfogeometry.h" #include "../vpatterndb/vpatternpiecedata.h" +#include "../vpatterndb/calculator.h" #include "../vmisc/def.h" #include "../vwidgets/vmaingraphicsscene.h" #include "../vwidgets/vmaingraphicsview.h" @@ -147,7 +148,7 @@ VToolDetail::VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 VMainGraphicsScene *scene, const QString &drawName, QGraphicsItem *parent) :VAbstractTool(doc, data, id), VNoBrushScalePathItem(parent), dialog(nullptr), sceneDetails(scene), drawName(drawName), seamAllowance(new VNoBrushScalePathItem(this)), dataLabel(new VTextGraphicsItem(this)), - patternInfo(new VTextGraphicsItem(this)) + patternInfo(new VTextGraphicsItem(this)), grainLine(new VGrainlineItem(this)) { VDetail detail = data->GetDetail(id); for (int i = 0; i< detail.CountNode(); ++i) @@ -204,9 +205,14 @@ VToolDetail::VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 connect(patternInfo, &VTextGraphicsItem::SignalResized, this, &VToolDetail::SaveResizePattern); connect(patternInfo, &VTextGraphicsItem::SignalRotated, this, &VToolDetail::SaveRotationPattern); + connect(grainLine, &VGrainlineItem::SignalMoved, this, &VToolDetail::SaveMoveGrainline); + connect(grainLine, &VGrainlineItem::SignalResized, this, &VToolDetail::SaveResizeGrainline); + connect(grainLine, &VGrainlineItem::SignalRotated, this, &VToolDetail::SaveRotateGrainline); + connect(doc, &VAbstractPattern::patternChanged, this, &VToolDetail::UpdatePatternInfo); connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdateLabel); connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdatePatternInfo); + connect(doc, &VAbstractPattern::CheckLayout, this, &VToolDetail::UpdateGrainline); connect(sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolDetail::UpdateLabel); connect(sceneDetails, &VMainGraphicsScene::DimensionsChanged, this, &VToolDetail::UpdatePatternInfo); @@ -214,6 +220,7 @@ VToolDetail::VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 UpdateLabel(); UpdatePatternInfo(); + UpdateGrainline(); } //--------------------------------------------------------------------------------------------------------------------- @@ -407,11 +414,20 @@ void VToolDetail::FullUpdateFromGuiOk(int result) //--------------------------------------------------------------------------------------------------------------------- /** - * @brief VToolDetail::paint draws a bounding box around detail, if one of its text items is not idle. + * @brief VToolDetail::paint draws a bounding box around detail, if one of its text or grainline items is not idle. */ void VToolDetail::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - if (dataLabel->IsIdle() == false || patternInfo->IsIdle() == false) + if (scene()->views().count() > 0) + { + QPoint pt0 = scene()->views().at(0)->mapFromScene(0, 0); + QPoint pt = scene()->views().at(0)->mapFromScene(0, 100); + qreal dScale = qSqrt(QPoint::dotProduct(pt - pt0, pt - pt0)); + grainLine->SetScale(100/dScale); + //qDebug() << "SCALE" << dScale << 10/dScale; + } + + if (dataLabel->IsIdle() == false || patternInfo->IsIdle() == false || grainLine->IsIdle() == false) { painter->save(); painter->setPen(QPen(Qt::black, 3, Qt::DashLine)); @@ -439,6 +455,7 @@ void VToolDetail::AddToFile() doc->SetAttribute(domElement, AttrWidth, detail.getWidth()); doc->SetAttribute(domElement, AttrForbidFlipping, static_cast(detail.getForbidFlipping())); + // detail data QDomElement domData = doc->createElement(VAbstractPattern::TagData); const VPatternPieceData& data = detail.GetPatternPieceData(); doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter()); @@ -465,6 +482,7 @@ void VToolDetail::AddToFile() } domElement.appendChild(domData); + // pattern info domData = doc->createElement(VAbstractPattern::TagPatternInfo); const VPatternInfoGeometry& geom = detail.GetPatternInfo(); doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true? trueStr : falseStr); @@ -476,6 +494,16 @@ void VToolDetail::AddToFile() doc->SetAttribute(domData, AttrRotation, geom.GetRotation()); domElement.appendChild(domData); + // grainline + domData = doc->createElement(VAbstractPattern::TagGrainline); + const VGrainlineGeometry& glGeom = detail.GetGrainlineGeometry(); + doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr); + doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x()); + doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y()); + doc->SetAttribute(domData, AttrLength, glGeom.GetLength()); + doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation()); + + // nodes for (int i = 0; i < detail.CountNode(); ++i) { AddNode(doc, domElement, detail.at(i)); @@ -502,6 +530,7 @@ void VToolDetail::RefreshDataInFile() doc->SetAttribute(domElement, AttrWidth, QString().setNum(det.getWidth())); doc->RemoveAllChildren(domElement); + // detail data QDomElement domData = doc->createElement(VAbstractPattern::TagData); const VPatternPieceData& data = det.GetPatternPieceData(); doc->SetAttribute(domData, VAbstractPattern::AttrLetter, data.GetLetter()); @@ -532,6 +561,7 @@ void VToolDetail::RefreshDataInFile() } domElement.appendChild(domData); + // pattern info domData = doc->createElement(VAbstractPattern::TagPatternInfo); const VPatternInfoGeometry& geom = det.GetPatternInfo(); doc->SetAttribute(domData, VAbstractPattern::AttrVisible, geom.IsVisible() == true? trueStr : falseStr); @@ -542,6 +572,16 @@ void VToolDetail::RefreshDataInFile() doc->SetAttribute(domData, AttrFont, geom.GetFontSize()); doc->SetAttribute(domData, AttrRotation, geom.GetRotation()); + // grainline + domData = doc->createElement(VAbstractPattern::TagGrainline); + const VGrainlineGeometry& glGeom = det.GetGrainlineGeometry(); + doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr); + doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x()); + doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y()); + doc->SetAttribute(domData, AttrLength, glGeom.GetLength()); + doc->SetAttribute(domData, AttrRotation, glGeom.GetRotation()); + + // nodes for (int i = 0; i < det.CountNode(); ++i) { AddNode(doc, domElement, det.at(i)); @@ -869,7 +909,47 @@ void VToolDetail::UpdatePatternInfo() } //--------------------------------------------------------------------------------------------------------------------- +/** + * @brief VToolDetail::UpdateGrainline updates the grain line item + */ +void VToolDetail::UpdateGrainline() +{ + const VDetail detail = VAbstractTool::data.GetDetail(id); + const VGrainlineGeometry& geom = detail.GetGrainlineGeometry(); + if (geom.IsVisible() == true) + { + qreal dRotation; + qreal dLength; + try + { + QString qsFormula; + qsFormula = geom.GetRotation().replace("\n", " "); + qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator()); + Calculator cal1; + dRotation = cal1.EvalFormula(VDataTool::data.PlainVariables(), qsFormula); + + qsFormula = geom.GetLength().replace("\n", " "); + qsFormula = qApp->TrVars()->FormulaFromUser(qsFormula, qApp->Settings()->GetOsSeparator()); + Calculator cal2; + dLength = cal2.EvalFormula(VDataTool::data.PlainVariables(), qsFormula); + } + catch(...) + { + grainLine->hide(); + return; + } + + grainLine->UpdateGeometry(geom.GetPos(), dRotation, ToPixel(dLength, *VDataTool::data.GetPatternUnit())); + grainLine->show(); + } + else + { + grainLine->hide(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- /** * @brief SaveMoveDetail saves the move detail operation to the undo stack */ @@ -985,6 +1065,49 @@ void VToolDetail::SaveRotationPattern(qreal dRot) } +//--------------------------------------------------------------------------------------------------------------------- +void VToolDetail::SaveMoveGrainline(const QPointF& ptPos) +{ + VDetail oldDet = VAbstractTool::data.GetDetail(id); + VDetail newDet = oldDet; + newDet.GetGrainlineGeometry().SetPos(ptPos); + qDebug() << "******* new grainline pos" << ptPos; + + SaveDetailOptions* moveCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene()); + moveCommand->setText(tr("move grainline")); + connect(moveCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); + qApp->getUndoStack()->push(moveCommand); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolDetail::SaveResizeGrainline(qreal dLength) +{ + VDetail oldDet = VAbstractTool::data.GetDetail(id); + VDetail newDet = oldDet; + + dLength = FromPixel(dLength, *VDataTool::data.GetPatternUnit()); + newDet.GetGrainlineGeometry().SetLength(qApp->LocaleToString(dLength)); + SaveDetailOptions* resizeCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene()); + resizeCommand->setText(tr("resize grainline")); + connect(resizeCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); + qApp->getUndoStack()->push(resizeCommand); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolDetail::SaveRotateGrainline(qreal dRot, const QPointF& ptPos) +{ + VDetail oldDet = VAbstractTool::data.GetDetail(id); + VDetail newDet = oldDet; + + dRot = qRadiansToDegrees(dRot); + newDet.GetGrainlineGeometry().SetRotation(qApp->LocaleToString(dRot)); + newDet.GetGrainlineGeometry().SetPos(ptPos); + SaveDetailOptions* rotateCommand = new SaveDetailOptions(oldDet, newDet, doc, id, this->scene()); + rotateCommand->setText(tr("rotate grainline")); + connect(rotateCommand, &SaveDetailOptions::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); + qApp->getUndoStack()->push(rotateCommand); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief AddNode add node to the file. @@ -1145,6 +1268,11 @@ void VToolDetail::ResetChildren(QGraphicsItem *pItem) { patternInfo->Reset(); } + VGrainlineItem* pGLI = dynamic_cast(pItem); + if (pGLI != grainLine) + { + grainLine->Reset(); + } } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/tools/vtooldetail.h b/src/libs/vtools/tools/vtooldetail.h index 215e605b4..afefd8694 100644 --- a/src/libs/vtools/tools/vtooldetail.h +++ b/src/libs/vtools/tools/vtooldetail.h @@ -36,6 +36,7 @@ #include "../vwidgets/vnobrushscalepathitem.h" #include "vabstracttool.h" #include "vtextgraphicsitem.h" +#include "vgrainlineitem.h" class VMainGraphicsScene; class DialogTool; @@ -120,12 +121,16 @@ protected: protected slots: virtual void UpdateLabel(); virtual void UpdatePatternInfo(); + virtual void UpdateGrainline(); virtual void SaveMoveDetail(const QPointF &ptPos); virtual void SaveResizeDetail(qreal dLabelW, int iFontSize); virtual void SaveRotationDetail(qreal dRot); virtual void SaveMovePattern(const QPointF& ptPos); virtual void SaveResizePattern(qreal dLabelW, int iFontSize); virtual void SaveRotationPattern(qreal dRot); + virtual void SaveMoveGrainline(const QPointF& ptPos); + virtual void SaveResizeGrainline(qreal dLength); + virtual void SaveRotateGrainline(qreal dRot, const QPointF& ptPos); private: Q_DISABLE_COPY(VToolDetail) @@ -139,6 +144,7 @@ private: VNoBrushScalePathItem *seamAllowance; VTextGraphicsItem *dataLabel; VTextGraphicsItem *patternInfo; + VGrainlineItem *grainLine; VToolDetail(VAbstractPattern *doc, VContainer *data, const quint32 &id, const Source &typeCreation, VMainGraphicsScene *scene, const QString &drawName, QGraphicsItem * parent = nullptr); diff --git a/src/libs/vtools/undocommands/savedetailoptions.cpp b/src/libs/vtools/undocommands/savedetailoptions.cpp index 31458d809..5cc0c525d 100644 --- a/src/libs/vtools/undocommands/savedetailoptions.cpp +++ b/src/libs/vtools/undocommands/savedetailoptions.cpp @@ -39,6 +39,7 @@ #include "../vmisc/def.h" #include "../vpatterndb/vpatterninfogeometry.h" #include "../vpatterndb/vpatternpiecedata.h" +#include "../vpatterndb/vgrainlinegeometry.h" #include "../tools/vtooldetail.h" #include "vundocommand.h" @@ -70,6 +71,8 @@ void SaveDetailOptions::undo() doc->RemoveAllChildren(domElement); SavePatternPieceData(domElement, oldDet); SavePatternInfo(domElement, oldDet); + SaveGrainline(domElement, oldDet); + for (int i = 0; i < oldDet.CountNode(); ++i) { VToolDetail::AddNode(doc, domElement, oldDet.at(i)); @@ -96,6 +99,7 @@ void SaveDetailOptions::redo() doc->RemoveAllChildren(domElement); SavePatternPieceData(domElement, newDet); SavePatternInfo(domElement, newDet); + SaveGrainline(domElement, newDet); for (int i = 0; i < newDet.CountNode(); ++i) { @@ -195,3 +199,17 @@ void SaveDetailOptions::SavePatternInfo(QDomElement &domElement, const VDetail & domElement.appendChild(domData); } + +//--------------------------------------------------------------------------------------------------------------------- +void SaveDetailOptions::SaveGrainline(QDomElement &domElement, const VDetail &det) +{ + QDomElement domData = doc->createElement(VAbstractPattern::TagGrainline); + const VGrainlineGeometry& glGeom = det.GetGrainlineGeometry(); + doc->SetAttribute(domData, VAbstractPattern::AttrVisible, glGeom.IsVisible() == true? trueStr : falseStr); + doc->SetAttribute(domData, AttrMx, glGeom.GetPos().x()); + doc->SetAttribute(domData, AttrMy, glGeom.GetPos().y()); + doc->SetAttribute(domData, AttrLength, glGeom.GetLength()); + doc->SetAttribute(domData, VToolDetail::AttrRotation, glGeom.GetRotation()); + + domElement.appendChild(domData); +} diff --git a/src/libs/vtools/undocommands/savedetailoptions.h b/src/libs/vtools/undocommands/savedetailoptions.h index d1ff979d9..5b4cbc058 100644 --- a/src/libs/vtools/undocommands/savedetailoptions.h +++ b/src/libs/vtools/undocommands/savedetailoptions.h @@ -65,6 +65,7 @@ private: void SaveDet(QDomElement &domElement, const VDetail &det); void SavePatternPieceData(QDomElement &domElement, const VDetail &det); void SavePatternInfo(QDomElement &domElement, const VDetail &det); + void SaveGrainline(QDomElement &domElement, const VDetail &det); }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vtools/vtools.pri b/src/libs/vtools/vtools.pri index acae2d114..ba301cfc1 100644 --- a/src/libs/vtools/vtools.pri +++ b/src/libs/vtools/vtools.pri @@ -10,3 +10,4 @@ HEADERS += \ $$PWD/stable.h win32-msvc*:SOURCES += $$PWD/stable.cpp +