1 /************************************************************************
2  **
3  **  @file   vtoolarcwithlength.cpp
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   9 6, 2015
6  **
7  **  @brief
8  **  @copyright
9  **  This source code is part of the Valentina project, a pattern making
10  **  program, whose allow create and modeling patterns of clothing.
11  **  Copyright (C) 2015 Valentina project
12  **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13  **
14  **  Valentina is free software: you can redistribute it and/or modify
15  **  it under the terms of the GNU General Public License as published by
16  **  the Free Software Foundation, either version 3 of the License, or
17  **  (at your option) any later version.
18  **
19  **  Valentina is distributed in the hope that it will be useful,
20  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  **  GNU General Public License for more details.
23  **
24  **  You should have received a copy of the GNU General Public License
25  **  along with Valentina.  If not, see <http://www.gnu.org/licenses/>.
26  **
27  *************************************************************************/
28 
29 #include "vtoolarcwithlength.h"
30 
31 #include <QPen>
32 #include <QSharedPointer>
33 #include <QStaticStringData>
34 #include <QStringData>
35 #include <QStringDataPtr>
36 #include <Qt>
37 #include <new>
38 
39 #include "../../../dialogs/tools/dialogtool.h"
40 #include "../../../dialogs/tools/dialogarcwithlength.h"
41 #include "../../../visualization/visualization.h"
42 #include "../../../visualization/path/vistoolarcwithlength.h"
43 #include "../ifc/exception/vexception.h"
44 #include "../ifc/xml/vdomdocument.h"
45 #include "../ifc/ifcdef.h"
46 #include "../vgeometry/varc.h"
47 #include "../vgeometry/vgobject.h"
48 #include "../vgeometry/vpointf.h"
49 #include "../vmisc/vabstractapplication.h"
50 #include "../vmisc/vcommonsettings.h"
51 #include "../vpatterndb/vcontainer.h"
52 #include "../vpatterndb/vformula.h"
53 #include "../vpatterndb/vtranslatevars.h"
54 #include "../vwidgets/vmaingraphicsscene.h"
55 #include "../../vabstracttool.h"
56 #include "../vdrawtool.h"
57 #include "vabstractspline.h"
58 
59 const QString VToolArcWithLength::ToolType = QStringLiteral("arcWithLength");
60 
61 //---------------------------------------------------------------------------------------------------------------------
VToolArcWithLength(const VToolArcWithLengthInitData & initData,QGraphicsItem * parent)62 VToolArcWithLength::VToolArcWithLength(const VToolArcWithLengthInitData &initData, QGraphicsItem *parent)
63     :VToolAbstractArc(initData.doc, initData.data, initData.id, initData.notes, parent)
64 {
65     sceneType = SceneObject::Arc;
66 
67     this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
68 
69     ToolCreation(initData.typeCreation);
70 }
71 
72 //---------------------------------------------------------------------------------------------------------------------
setDialog()73 void VToolArcWithLength::setDialog()
74 {
75     SCASSERT(not m_dialog.isNull())
76     const QPointer<DialogArcWithLength> dialogTool = qobject_cast<DialogArcWithLength *>(m_dialog);
77     SCASSERT(not dialogTool.isNull())
78     const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
79     dialogTool->SetCenter(arc->GetCenter().id());
80     dialogTool->SetF1(arc->GetFormulaF1());
81     dialogTool->SetLength(arc->GetFormulaLength());
82     dialogTool->SetRadius(arc->GetFormulaRadius());
83     dialogTool->SetColor(arc->GetColor());
84     dialogTool->SetPenStyle(arc->GetPenStyle());
85     dialogTool->SetApproximationScale(arc->GetApproximationScale());
86     dialogTool->SetNotes(m_notes);
87     dialogTool->SetAliasSuffix(arc->GetAliasSuffix());
88 }
89 
90 //---------------------------------------------------------------------------------------------------------------------
Create(const QPointer<DialogTool> & dialog,VMainGraphicsScene * scene,VAbstractPattern * doc,VContainer * data)91 VToolArcWithLength *VToolArcWithLength::Create(const QPointer<DialogTool> &dialog, VMainGraphicsScene *scene,
92                                                VAbstractPattern *doc, VContainer *data)
93 {
94     SCASSERT(not dialog.isNull())
95     const QPointer<DialogArcWithLength> dialogTool = qobject_cast<DialogArcWithLength *>(dialog);
96     SCASSERT(not dialogTool.isNull())
97 
98     VToolArcWithLengthInitData initData;
99     initData.center = dialogTool->GetCenter();
100     initData.radius = dialogTool->GetRadius();
101     initData.f1 = dialogTool->GetF1();
102     initData.length = dialogTool->GetLength();
103     initData.color = dialogTool->GetColor();
104     initData.penStyle = dialogTool->GetPenStyle();
105     initData.approximationScale = dialogTool->GetApproximationScale();
106     initData.scene = scene;
107     initData.doc = doc;
108     initData.data = data;
109     initData.parse = Document::FullParse;
110     initData.typeCreation = Source::FromGui;
111     initData.notes = dialogTool->GetNotes();
112     initData.aliasSuffix = dialogTool->GetAliasSuffix();
113 
114     VToolArcWithLength* point = Create(initData);
115     if (point != nullptr)
116     {
117         point->m_dialog = dialog;
118     }
119     return point;
120 }
121 
122 //---------------------------------------------------------------------------------------------------------------------
Create(VToolArcWithLengthInitData & initData)123 VToolArcWithLength *VToolArcWithLength::Create(VToolArcWithLengthInitData &initData)
124 {
125     qreal calcRadius = 0, calcF1 = 0, calcLength = 0;
126 
127     calcRadius = VAbstractValApplication::VApp()->toPixel(CheckFormula(initData.id, initData.radius, initData.data));
128     calcLength = VAbstractValApplication::VApp()->toPixel(CheckFormula(initData.id, initData.length, initData.data));
129     calcF1 = CheckFormula(initData.id, initData.f1, initData.data);
130 
131     const VPointF c = *initData.data->GeometricObject<VPointF>(initData.center);
132     VArc *arc = new VArc(calcLength, initData.length, c, calcRadius, initData.radius, calcF1, initData.f1);
133     arc->SetColor(initData.color);
134     arc->SetPenStyle(initData.penStyle);
135     arc->SetApproximationScale(initData.approximationScale);
136     arc->SetAliasSuffix(initData.aliasSuffix);
137 
138     if (initData.typeCreation == Source::FromGui)
139     {
140         initData.id = initData.data->AddGObject(arc);
141         initData.data->AddArc(initData.data->GeometricObject<VArc>(initData.id), initData.id);
142     }
143     else
144     {
145         initData.data->UpdateGObject(initData.id, arc);
146         initData.data->AddArc(initData.data->GeometricObject<VArc>(initData.id), initData.id);
147         if (initData.parse != Document::FullParse)
148         {
149             initData.doc->UpdateToolData(initData.id, initData.data);
150         }
151     }
152 
153     if (initData.parse == Document::FullParse)
154     {
155         VAbstractTool::AddRecord(initData.id, Tool::ArcWithLength, initData.doc);
156         VToolArcWithLength *toolArc = new VToolArcWithLength(initData);
157         initData.scene->addItem(toolArc);
158         InitArcToolConnections(initData.scene, toolArc);
159         VAbstractPattern::AddTool(initData.id, toolArc);
160         initData.doc->IncrementReferens(c.getIdTool());
161         return toolArc;
162     }
163     return nullptr;
164 }
165 
166 //---------------------------------------------------------------------------------------------------------------------
getTagName() const167 QString VToolArcWithLength::getTagName() const
168 {
169     return VAbstractPattern::TagArc;
170 }
171 
172 //---------------------------------------------------------------------------------------------------------------------
GetFormulaRadius() const173 VFormula VToolArcWithLength::GetFormulaRadius() const
174 {
175     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
176     SCASSERT(arc.isNull() == false)
177 
178     VFormula radius(arc->GetFormulaRadius(), getData());
179     radius.setCheckZero(true);
180     radius.setToolId(m_id);
181     radius.setPostfix(UnitsToStr(VAbstractValApplication::VApp()->patternUnits()));
182     radius.Eval();
183     return radius;
184 }
185 
186 //---------------------------------------------------------------------------------------------------------------------
SetFormulaRadius(const VFormula & value)187 void VToolArcWithLength::SetFormulaRadius(const VFormula &value)
188 {
189     if (value.error() == false)
190     {
191         if (value.getDoubleValue() > 0)// Formula don't check this, but radius can't be 0 or negative
192         {
193             QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
194             QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
195             arc->SetFormulaRadius(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
196             SaveOption(obj);
197         }
198     }
199 }
200 
201 //---------------------------------------------------------------------------------------------------------------------
GetFormulaF1() const202 VFormula VToolArcWithLength::GetFormulaF1() const
203 {
204     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
205     SCASSERT(arc.isNull() == false)
206 
207     VFormula f1(arc->GetFormulaF1(), getData());
208     f1.setCheckZero(false);
209     f1.setToolId(m_id);
210     f1.setPostfix(degreeSymbol);
211     f1.Eval();
212     return f1;
213 }
214 
215 //---------------------------------------------------------------------------------------------------------------------
SetFormulaF1(const VFormula & value)216 void VToolArcWithLength::SetFormulaF1(const VFormula &value)
217 {
218     if (value.error() == false)
219     {
220         QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
221         QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
222 
223         if (not VFuzzyComparePossibleNulls(value.getDoubleValue(), arc->GetEndAngle()))// Angles can't be equal
224         {
225             arc->SetFormulaF1(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
226             SaveOption(obj);
227         }
228     }
229 }
230 
231 //---------------------------------------------------------------------------------------------------------------------
GetFormulaLength() const232 VFormula VToolArcWithLength::GetFormulaLength() const
233 {
234     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
235     SCASSERT(arc.isNull() == false)
236 
237     VFormula radius(arc->GetFormulaLength(), getData());
238     radius.setCheckZero(true);
239     radius.setToolId(m_id);
240     radius.setPostfix(UnitsToStr(VAbstractValApplication::VApp()->patternUnits()));
241     radius.Eval();
242     return radius;
243 }
244 
245 //---------------------------------------------------------------------------------------------------------------------
SetFormulaLength(const VFormula & value)246 void VToolArcWithLength::SetFormulaLength(const VFormula &value)
247 {
248     if (value.error() == false)
249     {
250         QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
251         QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
252         arc->SetFormulaLength(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
253         SaveOption(obj);
254     }
255 }
256 
257 //---------------------------------------------------------------------------------------------------------------------
GetApproximationScale() const258 qreal VToolArcWithLength::GetApproximationScale() const
259 {
260     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
261     SCASSERT(arc.isNull() == false)
262 
263     return arc->GetApproximationScale();
264 }
265 
266 //---------------------------------------------------------------------------------------------------------------------
SetApproximationScale(qreal value)267 void VToolArcWithLength::SetApproximationScale(qreal value)
268 {
269     QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
270     QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
271     arc->SetApproximationScale(value);
272     SaveOption(obj);
273 }
274 
275 //---------------------------------------------------------------------------------------------------------------------
ShowVisualization(bool show)276 void VToolArcWithLength::ShowVisualization(bool show)
277 {
278     ShowToolVisualization<VisToolArcWithLength>(show);
279 }
280 
281 //---------------------------------------------------------------------------------------------------------------------
ShowContextMenu(QGraphicsSceneContextMenuEvent * event,quint32 id)282 void VToolArcWithLength::ShowContextMenu(QGraphicsSceneContextMenuEvent *event, quint32 id)
283 {
284     Q_UNUSED(id)
285     try
286     {
287         ContextMenu<DialogArcWithLength>(event);
288     }
289     catch(const VExceptionToolWasDeleted &e)
290     {
291         Q_UNUSED(e)
292         return;//Leave this method immediately!!!
293     }
294 }
295 
296 //---------------------------------------------------------------------------------------------------------------------
RemoveReferens()297 void VToolArcWithLength::RemoveReferens()
298 {
299     const auto arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
300     doc->DecrementReferens(arc->GetCenter().getIdTool());
301 }
302 
303 //---------------------------------------------------------------------------------------------------------------------
SaveDialog(QDomElement & domElement,QList<quint32> & oldDependencies,QList<quint32> & newDependencies)304 void VToolArcWithLength::SaveDialog(QDomElement &domElement, QList<quint32> &oldDependencies,
305                                     QList<quint32> &newDependencies)
306 {
307     SCASSERT(not m_dialog.isNull())
308     const QPointer<DialogArcWithLength> dialogTool = qobject_cast<DialogArcWithLength *>(m_dialog);
309     SCASSERT(not dialogTool.isNull())
310 
311     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
312     SCASSERT(arc.isNull() == false)
313     AddDependence(oldDependencies, arc->GetCenter().id());
314     AddDependence(newDependencies, dialogTool->GetCenter());
315 
316     doc->SetAttribute(domElement, AttrCenter, QString().setNum(dialogTool->GetCenter()));
317     doc->SetAttribute(domElement, AttrRadius, dialogTool->GetRadius());
318     doc->SetAttribute(domElement, AttrAngle1, dialogTool->GetF1());
319     doc->SetAttribute(domElement, AttrLength, dialogTool->GetLength());
320     doc->SetAttribute(domElement, AttrColor, dialogTool->GetColor());
321     doc->SetAttribute(domElement, AttrPenStyle, dialogTool->GetPenStyle());
322     doc->SetAttribute(domElement, AttrAScale, dialogTool->GetApproximationScale());
323     doc->SetAttributeOrRemoveIf(domElement, AttrAlias, dialogTool->GetAliasSuffix(),
324                                 dialogTool->GetAliasSuffix().isEmpty());
325 
326     const QString notes = dialogTool->GetNotes();
327     doc->SetAttributeOrRemoveIf(domElement, AttrNotes, notes, notes.isEmpty());
328 }
329 
330 //---------------------------------------------------------------------------------------------------------------------
SaveOptions(QDomElement & tag,QSharedPointer<VGObject> & obj)331 void VToolArcWithLength::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj)
332 {
333     VAbstractSpline::SaveOptions(tag, obj);
334 
335     QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
336     SCASSERT(arc.isNull() == false)
337 
338     doc->SetAttribute(tag, AttrType, ToolType);
339     doc->SetAttribute(tag, AttrCenter, arc->GetCenter().id());
340     doc->SetAttribute(tag, AttrRadius, arc->GetFormulaRadius());
341     doc->SetAttribute(tag, AttrAngle1, arc->GetFormulaF1());
342     doc->SetAttribute(tag, AttrLength, arc->GetFormulaLength());
343 }
344 
345 //---------------------------------------------------------------------------------------------------------------------
SetVisualization()346 void VToolArcWithLength::SetVisualization()
347 {
348     if (not vis.isNull())
349     {
350         const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
351         VisToolArcWithLength *visual = qobject_cast<VisToolArcWithLength *>(vis);
352         SCASSERT(visual != nullptr)
353 
354         const VTranslateVars *trVars = VAbstractApplication::VApp()->TrVars();
355         visual->setObject1Id(arc->GetCenter().id());
356         visual->setRadius(trVars->FormulaToUser(arc->GetFormulaRadius(),
357                                                 VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
358         visual->setF1(trVars->FormulaToUser(arc->GetFormulaF1(),
359                                             VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
360         visual->setLength(trVars->FormulaToUser(arc->GetFormulaLength(),
361                                                 VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
362         visual->setLineStyle(LineStyleToPenStyle(arc->GetPenStyle()));
363         visual->setApproximationScale(arc->GetApproximationScale());
364         visual->RefreshGeometry();
365     }
366 }
367 
368 //---------------------------------------------------------------------------------------------------------------------
MakeToolTip() const369 QString VToolArcWithLength::MakeToolTip() const
370 {
371     const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
372 
373     const QString toolTip = QString("<table>"
374                                     "<tr> <td><b>%10:</b> %11</td> </tr>"
375                                     "<tr> <td><b>%1:</b> %2 %3</td> </tr>"
376                                     "<tr> <td><b>%4:</b> %5 %3</td> </tr>"
377                                     "<tr> <td><b>%6:</b> %7°</td> </tr>"
378                                     "<tr> <td><b>%8:</b> %9°</td> </tr>"
379                                     "</table>")
380             .arg(tr("Length"))
381             .arg(VAbstractValApplication::VApp()->fromPixel(arc->GetLength()))
382             .arg(UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true), tr("Radius"))
383             .arg(VAbstractValApplication::VApp()->fromPixel(arc->GetRadius()))
384             .arg(tr("Start angle"))
385             .arg(arc->GetStartAngle())
386             .arg(tr("End angle"))
387             .arg(arc->GetEndAngle())
388             .arg(tr("Label"), arc->ObjectName());
389     return toolTip;
390 }
391