Merged in BojanKverh/valentina-issue331/feature (pull request #142)

Draft implementation for issue New tool: Grainline in Detail mode. ref #331.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2016-10-23 16:14:36 +00:00
commit 0a83886f09
36 changed files with 2028 additions and 53 deletions

View File

@ -39,6 +39,7 @@
#include "../vlayout/vposter.h"
#include "../vpatterndb/vpatternpiecedata.h"
#include "../vpatterndb/vpatterninfogeometry.h"
#include "../vpatterndb/vgrainlinegeometry.h"
#include <QFileDialog>
#include <QFileInfo>
@ -496,6 +497,11 @@ void MainWindowsNoGUI::PrepareDetailsForLayout(const QHash<quint32, VDetail> *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());

View File

@ -51,6 +51,7 @@
#include "../vpatterndb/calculator.h"
#include "../vpatterndb/vpatternpiecedata.h"
#include "../vpatterndb/vpatterninfogeometry.h"
#include "../vpatterndb/vgrainlinegeometry.h"
#include <QMessageBox>
#include <QUndoStack>
@ -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);

View File

@ -578,4 +578,4 @@
<xs:enumeration value="1"/><!--Cut on Fold-->
</xs:restriction>
</xs:simpleType>
</xs:schema>
</xs:schema>

View File

@ -377,6 +377,15 @@
<xs:attribute name="rotation" type="xs:double"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="grainline" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="visible" type="xs:boolean"></xs:attribute>
<xs:attribute name="mx" type="xs:double"></xs:attribute>
<xs:attribute name="my" type="xs:double"></xs:attribute>
<xs:attribute name="length" type="xs:string"></xs:attribute>
<xs:attribute name="rotation" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="node" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="nodeType" type="xs:string"></xs:attribute>
@ -579,4 +588,4 @@
<xs:enumeration value="1"/><!--Cut on Fold-->
</xs:restriction>
</xs:simpleType>
</xs:schema>
</xs:schema>

View File

@ -377,6 +377,15 @@
<xs:attribute name="rotation" type="xs:double"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="grainline" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="visible" type="xs:boolean"></xs:attribute>
<xs:attribute name="mx" type="xs:double"></xs:attribute>
<xs:attribute name="my" type="xs:double"></xs:attribute>
<xs:attribute name="length" type="xs:string"></xs:attribute>
<xs:attribute name="rotation" type="xs:string"></xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="node" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="nodeType" type="xs:string"></xs:attribute>

View File

@ -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");

View File

@ -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;

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#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();
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VGRAPHICSFILLITEM_H
#define VGRAPHICSFILLITEM_H
#include <QGraphicsPathItem>
#include <QPainter>
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

View File

@ -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

View File

@ -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<QPointF> 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<QPointF> 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
{

View File

@ -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<VLayoutDetailData> d;

View File

@ -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<QPointF>()), seamAllowence(QVector<QPointF>()), layoutAllowence(QVector<QPointF>()),
matrix(QMatrix()), layoutWidth(0), mirror(false), detailLabel(QVector<QPointF>()),
patternInfo(QVector<QPointF>()), detailData(), patternGeom(), m_tmDetail(),
m_tmPattern(), m_liPP(QList<QPainterPath>())
patternInfo(QVector<QPointF>()), grainlinePoints(QVector<QPointF>()), detailData(), patternGeom(),
grainlineGeom(), m_tmDetail(), m_tmPattern(), m_liPP(QList<QPainterPath>())
{}
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<QPointF> contour;
QVector<QPointF> contour;
/** @brief seamAllowence list of seam allowence points. */
QVector<QPointF> seamAllowence;
QVector<QPointF> seamAllowence;
/** @brief layoutAllowence list of layout allowence points. */
QVector<QPointF> layoutAllowence;
QVector<QPointF> 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<QPointF> detailLabel;
QVector<QPointF> detailLabel;
/** @brief patternInfo pattern info rectangle */
QVector<QPointF> patternInfo;
QVector<QPointF> patternInfo;
/** @brief grainlineInfo line */
QVector<QPointF> 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 */

View File

@ -348,6 +348,12 @@ QList<QGraphicsItem *> 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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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<VDetailData> d;

View File

@ -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;

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include <QPointF>
#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;
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VGRAINLINEGEOMETRY_H
#define VGRAINLINEGEOMETRY_H
#include <QtGlobal>
#include <QString>
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

View File

@ -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

View File

@ -28,6 +28,7 @@
#include "dialogdetail.h"
#include <QtNumeric>
#include <QBuffer>
#include <QByteArray>
#include <QCheckBox>
@ -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);
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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();
};
//---------------------------------------------------------------------------------------------------------------------

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>581</width>
<height>468</height>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
@ -24,7 +24,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@ -318,7 +318,8 @@
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff>.</normaloff>.</iconset>
<normaloff/>
</iconset>
</property>
</widget>
</item>
@ -332,7 +333,8 @@
</property>
<property name="icon">
<iconset theme="go-up">
<normaloff>.</normaloff>.</iconset>
<normaloff/>
</iconset>
</property>
</widget>
</item>
@ -526,6 +528,445 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<attribute name="title">
<string>Grainline</string>
</attribute>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>541</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="checkBoxGrainline">
<property name="text">
<string>Grainline visible</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_2">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>541</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item alignment="Qt::AlignLeft">
<widget class="QLabel" name="labelEditRot">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>159</red>
<green>158</green>
<blue>158</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Rotation:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignRight">
<widget class="QToolButton" name="pushButtonRot">
<property name="toolTip">
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
<normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="labelEqual">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="labelRot">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>87</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Value</string>
</property>
<property name="text">
<string notr="true">_</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_3">
<property name="geometry">
<rect>
<x>10</x>
<y>110</y>
<width>541</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QPlainTextEdit" name="lineEditRotFormula">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
<property name="toolTip">
<string>Calculation</string>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<property name="plainText">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonShowRot">
<property name="maximumSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff/>
</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_4">
<property name="geometry">
<rect>
<x>10</x>
<y>160</y>
<width>541</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item alignment="Qt::AlignLeft">
<widget class="QLabel" name="labelEditLen">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>159</red>
<green>158</green>
<blue>158</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Length:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item alignment="Qt::AlignRight">
<widget class="QToolButton" name="pushButtonLen">
<property name="toolTip">
<string>Formula wizard</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
<normaloff>:/icon/24x24/fx.png</normaloff>:/icon/24x24/fx.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="labelEqual_2">
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../../../vmisc/share/resources/icon.qrc">:/icon/24x24/equal.png</pixmap>
</property>
</widget>
</item>
<item alignment="Qt::AlignRight">
<widget class="QLabel" name="labelLen">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>87</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Value</string>
</property>
<property name="text">
<string notr="true">_</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_5">
<property name="geometry">
<rect>
<x>10</x>
<y>210</y>
<width>541</width>
<height>41</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QPlainTextEdit" name="lineEditLenFormula">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>28</height>
</size>
</property>
<property name="toolTip">
<string>Calculation</string>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<property name="plainText">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButtonShowLen">
<property name="maximumSize">
<size>
<width>18</width>
<height>18</height>
</size>
</property>
<property name="sizeIncrement">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Show full calculation in message box&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="icon">
<iconset theme="go-down">
<normaloff/>
</iconset>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
@ -539,11 +980,8 @@
</widget>
</item>
</layout>
<zorder>buttonBox</zorder>
<zorder>tabWidget</zorder>
</widget>
<tabstops>
<tabstop>lineEditLetter</tabstop>
<tabstop>lineEditName</tabstop>
<tabstop>comboBoxMaterial</tabstop>
<tabstop>spinBoxCutNumber</tabstop>
@ -551,8 +989,6 @@
<tabstop>pushButtonAdd</tabstop>
<tabstop>pushButtonCancel</tabstop>
<tabstop>pushButtonRemove</tabstop>
<tabstop>listWidgetMCP</tabstop>
<tabstop>buttonBox</tabstop>
<tabstop>toolButtonUp</tabstop>
<tabstop>listWidget</tabstop>
<tabstop>checkBoxClosed</tabstop>
@ -563,6 +999,10 @@
<tabstop>checkBoxSeams</tabstop>
<tabstop>doubleSpinBoxSeams</tabstop>
<tabstop>toolButtonDown</tabstop>
<tabstop>checkBoxForbidFlipping</tabstop>
<tabstop>checkBoxDetail</tabstop>
<tabstop>checkBoxPattern</tabstop>
<tabstop>lineEditLetter</tabstop>
</tabstops>
<resources>
<include location="../../../vmisc/share/resources/icon.qrc"/>

View File

@ -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

View File

@ -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 \

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include <math.h>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <QDebug>
#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;
}

View File

@ -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
** <https://bitbucket.org/dismine/valentina> 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 <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VGRAINLINEITEM_H
#define VGRAINLINEITEM_H
#include <QGraphicsObject>
#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

View File

@ -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();

View File

@ -98,7 +98,7 @@ protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent* pHE);
void hoverLeaveEvent(QGraphicsSceneHoverEvent* pHE);
void UpdateBox();
void UpdateFont();
void CorrectLabel();
double GetAngle(QPointF pt) const;

View File

@ -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<quint8>(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<VGrainlineItem*>(pItem);
if (pGLI != grainLine)
{
grainLine->Reset();
}
}
//---------------------------------------------------------------------------------------------------------------------

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
};
//---------------------------------------------------------------------------------------------------------------------

View File

@ -10,3 +10,4 @@ HEADERS += \
$$PWD/stable.h
win32-msvc*:SOURCES += $$PWD/stable.cpp