1 /************************************************************************
2  **
3  **  @file   vtoolarc.cpp
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   November 15, 2013
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) 2013-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 "vtoolarc.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/dialogarc.h"
41 #include "../../../visualization/path/vistoolarc.h"
42 #include "../../../visualization/visualization.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 VToolArc::ToolType = QStringLiteral("simple");
60 
61 //---------------------------------------------------------------------------------------------------------------------
62 /**
63  * @brief VToolArc constuctor.
64  * @param initData init data
65  */
VToolArc(const VToolArcInitData & initData,QGraphicsItem * parent)66 VToolArc::VToolArc(const VToolArcInitData &initData, QGraphicsItem *parent)
67     : VToolAbstractArc(initData.doc, initData.data, initData.id, initData.notes, parent)
68 {
69     sceneType = SceneObject::Arc;
70 
71     this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus
72 
73     ToolCreation(initData.typeCreation);
74 }
75 
76 //---------------------------------------------------------------------------------------------------------------------
77 /**
78  * @brief setDialog set dialog when user want change tool option.
79  */
setDialog()80 void VToolArc::setDialog()
81 {
82     SCASSERT(not m_dialog.isNull())
83     const QPointer<DialogArc> dialogTool = qobject_cast<DialogArc *>(m_dialog);
84     SCASSERT(not dialogTool.isNull())
85     const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
86     dialogTool->SetCenter(arc->GetCenter().id());
87     dialogTool->SetF1(arc->GetFormulaF1());
88     dialogTool->SetF2(arc->GetFormulaF2());
89     dialogTool->SetRadius(arc->GetFormulaRadius());
90     dialogTool->SetColor(arc->GetColor());
91     dialogTool->SetPenStyle(arc->GetPenStyle());
92     dialogTool->SetApproximationScale(arc->GetApproximationScale());
93     dialogTool->SetNotes(m_notes);
94     dialogTool->SetAliasSuffix(arc->GetAliasSuffix());
95 }
96 
97 //---------------------------------------------------------------------------------------------------------------------
98 /**
99  * @brief Create help create tool
100  * @param dialog dialog options.
101  * @param scene pointer to scene.
102  * @param doc dom document container
103  * @param data container with variables
104  */
Create(const QPointer<DialogTool> & dialog,VMainGraphicsScene * scene,VAbstractPattern * doc,VContainer * data)105 VToolArc* VToolArc::Create(const QPointer<DialogTool> &dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
106                            VContainer *data)
107 {
108     SCASSERT(not dialog.isNull())
109     const QPointer<DialogArc> dialogTool = qobject_cast<DialogArc *>(dialog);
110     SCASSERT(not dialogTool.isNull())
111 
112     VToolArcInitData initData;
113     initData.center = dialogTool->GetCenter();
114     initData.radius = dialogTool->GetRadius();
115     initData.f1 = dialogTool->GetF1();
116     initData.f2 = dialogTool->GetF2();
117     initData.color = dialogTool->GetColor();
118     initData.penStyle = dialogTool->GetPenStyle();
119     initData.scene = scene;
120     initData.doc = doc;
121     initData.data = data;
122     initData.parse = Document::FullParse;
123     initData.typeCreation = Source::FromGui;
124     initData.approximationScale = dialogTool->GetApproximationScale();
125     initData.notes = dialogTool->GetNotes();
126     initData.aliasSuffix = dialogTool->GetAliasSuffix();
127 
128     VToolArc* point = Create(initData);
129     if (point != nullptr)
130     {
131         point->m_dialog = dialog;
132     }
133     return point;
134 }
135 
136 //---------------------------------------------------------------------------------------------------------------------
137 /**
138  * @brief Create help create tool form GUI.
139  * @param initData init data.
140  */
Create(VToolArcInitData & initData)141 VToolArc* VToolArc::Create(VToolArcInitData &initData)
142 {
143     qreal calcRadius = 0, calcF1 = 0, calcF2 = 0;
144 
145     calcRadius = VAbstractValApplication::VApp()->toPixel(CheckFormula(initData.id, initData.radius, initData.data));
146 
147     calcF1 = CheckFormula(initData.id, initData.f1, initData.data);
148     calcF2 = CheckFormula(initData.id, initData.f2, initData.data);
149 
150     const VPointF c = *initData.data->GeometricObject<VPointF>(initData.center);
151     VArc *arc = new VArc(c, calcRadius, initData.radius, calcF1, initData.f1, calcF2, initData.f2 );
152     arc->SetColor(initData.color);
153     arc->SetPenStyle(initData.penStyle);
154     arc->SetApproximationScale(initData.approximationScale);
155     arc->SetAliasSuffix(initData.aliasSuffix);
156 
157     if (initData.typeCreation == Source::FromGui)
158     {
159         initData.id = initData.data->AddGObject(arc);
160         initData.data->AddArc(initData.data->GeometricObject<VArc>(initData.id), initData.id);
161     }
162     else
163     {
164         initData.data->UpdateGObject(initData.id, arc);
165         initData.data->AddArc(initData.data->GeometricObject<VArc>(initData.id), initData.id);
166         if (initData.parse != Document::FullParse)
167         {
168             initData.doc->UpdateToolData(initData.id, initData.data);
169         }
170     }
171 
172     if (initData.parse == Document::FullParse)
173     {
174         VAbstractTool::AddRecord(initData.id, Tool::Arc, initData.doc);
175         VToolArc *toolArc = new VToolArc(initData);
176         initData.scene->addItem(toolArc);
177         InitArcToolConnections(initData.scene, toolArc);
178         VAbstractPattern::AddTool(initData.id, toolArc);
179         initData.doc->IncrementReferens(c.getIdTool());
180         return toolArc;
181     }
182     return nullptr;
183 }
184 
185 //---------------------------------------------------------------------------------------------------------------------
getTagName() const186 QString VToolArc::getTagName() const
187 {
188     return VAbstractPattern::TagArc;
189 }
190 
191 //---------------------------------------------------------------------------------------------------------------------
GetFormulaRadius() const192 VFormula VToolArc::GetFormulaRadius() const
193 {
194     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
195     SCASSERT(arc.isNull() == false)
196 
197     VFormula radius(arc->GetFormulaRadius(), getData());
198     radius.setCheckZero(true);
199     radius.setToolId(m_id);
200     radius.setPostfix(UnitsToStr(VAbstractValApplication::VApp()->patternUnits()));
201     radius.Eval();
202     return radius;
203 }
204 
205 //---------------------------------------------------------------------------------------------------------------------
SetFormulaRadius(const VFormula & value)206 void VToolArc::SetFormulaRadius(const VFormula &value)
207 {
208     if (value.error() == false)
209     {
210         if (value.getDoubleValue() > 0)// Formula don't check this, but radius can't be 0 or negative
211         {
212             QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
213             QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
214             arc->SetFormulaRadius(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
215             SaveOption(obj);
216         }
217     }
218 }
219 
220 //---------------------------------------------------------------------------------------------------------------------
GetFormulaF1() const221 VFormula VToolArc::GetFormulaF1() const
222 {
223     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
224     SCASSERT(arc.isNull() == false)
225 
226     VFormula f1(arc->GetFormulaF1(), getData());
227     f1.setCheckZero(false);
228     f1.setToolId(m_id);
229     f1.setPostfix(degreeSymbol);
230     f1.Eval();
231     return f1;
232 }
233 
234 //---------------------------------------------------------------------------------------------------------------------
SetFormulaF1(const VFormula & value)235 void VToolArc::SetFormulaF1(const VFormula &value)
236 {
237     if (value.error() == false)
238     {
239         QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
240         QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
241 
242         arc->SetFormulaF1(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
243         SaveOption(obj);
244     }
245 }
246 
247 //---------------------------------------------------------------------------------------------------------------------
GetFormulaF2() const248 VFormula VToolArc::GetFormulaF2() const
249 {
250     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
251     SCASSERT(arc.isNull() == false)
252 
253     VFormula f2(arc->GetFormulaF2(), getData());
254     f2.setCheckZero(false);
255     f2.setToolId(m_id);
256     f2.setPostfix(degreeSymbol);
257     f2.Eval();
258     return f2;
259 }
260 
261 //---------------------------------------------------------------------------------------------------------------------
SetFormulaF2(const VFormula & value)262 void VToolArc::SetFormulaF2(const VFormula &value)
263 {
264     if (value.error() == false)
265     {
266         QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
267         QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
268         arc->SetFormulaF2(value.GetFormula(FormulaType::FromUser), value.getDoubleValue());
269         SaveOption(obj);
270     }
271 }
272 
273 //---------------------------------------------------------------------------------------------------------------------
GetApproximationScale() const274 qreal VToolArc::GetApproximationScale() const
275 {
276     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
277     SCASSERT(arc.isNull() == false)
278 
279     return arc->GetApproximationScale();
280 }
281 
282 //---------------------------------------------------------------------------------------------------------------------
SetApproximationScale(qreal value)283 void VToolArc::SetApproximationScale(qreal value)
284 {
285     QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(m_id);
286     QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
287     arc->SetApproximationScale(value);
288     SaveOption(obj);
289 }
290 
291 //---------------------------------------------------------------------------------------------------------------------
ShowVisualization(bool show)292 void VToolArc::ShowVisualization(bool show)
293 {
294     ShowToolVisualization<VisToolArc>(show);
295 }
296 
297 //---------------------------------------------------------------------------------------------------------------------
ShowContextMenu(QGraphicsSceneContextMenuEvent * event,quint32 id)298 void VToolArc::ShowContextMenu(QGraphicsSceneContextMenuEvent *event, quint32 id)
299 {
300     Q_UNUSED(id)
301     try
302     {
303         ContextMenu<DialogArc>(event);
304     }
305     catch(const VExceptionToolWasDeleted &e)
306     {
307         Q_UNUSED(e)
308         return;//Leave this method immediately!!!
309     }
310 }
311 
312 //---------------------------------------------------------------------------------------------------------------------
313 /**
314  * @brief RemoveReferens decrement value of reference.
315  */
RemoveReferens()316 void VToolArc::RemoveReferens()
317 {
318     const auto arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
319     doc->DecrementReferens(arc->GetCenter().getIdTool());
320 }
321 
322 //---------------------------------------------------------------------------------------------------------------------
323 /**
324  * @brief SaveDialog save options into file after change in dialog.
325  */
SaveDialog(QDomElement & domElement,QList<quint32> & oldDependencies,QList<quint32> & newDependencies)326 void VToolArc::SaveDialog(QDomElement &domElement, QList<quint32> &oldDependencies, QList<quint32> &newDependencies)
327 {
328     SCASSERT(not m_dialog.isNull())
329     QPointer<DialogArc> dialogTool = qobject_cast<DialogArc *>(m_dialog);
330     SCASSERT(not dialogTool.isNull())
331 
332     QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
333     SCASSERT(arc.isNull() == false)
334     AddDependence(oldDependencies, arc->GetCenter().id());
335     AddDependence(newDependencies, dialogTool->GetCenter());
336 
337     doc->SetAttribute(domElement, AttrCenter, QString().setNum(dialogTool->GetCenter()));
338     doc->SetAttribute(domElement, AttrRadius, dialogTool->GetRadius());
339     doc->SetAttribute(domElement, AttrAngle1, dialogTool->GetF1());
340     doc->SetAttribute(domElement, AttrAngle2, dialogTool->GetF2());
341     doc->SetAttribute(domElement, AttrColor, dialogTool->GetColor());
342     doc->SetAttribute(domElement, AttrPenStyle, dialogTool->GetPenStyle());
343     doc->SetAttribute(domElement, AttrAScale, dialogTool->GetApproximationScale());
344     doc->SetAttributeOrRemoveIf(domElement, AttrAlias, dialogTool->GetAliasSuffix(),
345                                 dialogTool->GetAliasSuffix().isEmpty());
346 
347     const QString notes = dialogTool->GetNotes();
348     doc->SetAttributeOrRemoveIf(domElement, AttrNotes, notes, notes.isEmpty());
349 }
350 
351 //---------------------------------------------------------------------------------------------------------------------
SaveOptions(QDomElement & tag,QSharedPointer<VGObject> & obj)352 void VToolArc::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj)
353 {
354     VAbstractSpline::SaveOptions(tag, obj);
355 
356     QSharedPointer<VArc> arc = qSharedPointerDynamicCast<VArc>(obj);
357     SCASSERT(arc.isNull() == false)
358 
359     doc->SetAttribute(tag, AttrType, ToolType);
360     doc->SetAttribute(tag, AttrCenter, arc->GetCenter().id());
361     doc->SetAttribute(tag, AttrRadius, arc->GetFormulaRadius());
362     doc->SetAttribute(tag, AttrAngle1, arc->GetFormulaF1());
363     doc->SetAttribute(tag, AttrAngle2, arc->GetFormulaF2());
364 }
365 
366 //---------------------------------------------------------------------------------------------------------------------
SetVisualization()367 void VToolArc::SetVisualization()
368 {
369     if (not vis.isNull())
370     {
371         const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
372         VisToolArc *visual = qobject_cast<VisToolArc *>(vis);
373         SCASSERT(visual != nullptr)
374 
375         const VTranslateVars *trVars = VAbstractApplication::VApp()->TrVars();
376         visual->setObject1Id(arc->GetCenter().id());
377         visual->setRadius(trVars->FormulaToUser(
378                               arc->GetFormulaRadius(), VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
379         visual->setF1(trVars->FormulaToUser(
380                           arc->GetFormulaF1(), VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
381         visual->setF2(trVars->FormulaToUser(
382                           arc->GetFormulaF2(), VAbstractApplication::VApp()->Settings()->GetOsSeparator()));
383         visual->setLineStyle(LineStyleToPenStyle(arc->GetPenStyle()));
384         visual->setApproximationScale(arc->GetApproximationScale());
385         visual->RefreshGeometry();
386     }
387 }
388 
389 //---------------------------------------------------------------------------------------------------------------------
MakeToolTip() const390 QString VToolArc::MakeToolTip() const
391 {
392     const QSharedPointer<VArc> arc = VAbstractTool::data.GeometricObject<VArc>(m_id);
393 
394     const QString toolTip = QString("<table>"
395                                     "<tr> <td><b>%10:</b> %11</td> </tr>"
396                                     "<tr> <td><b>%1:</b> %2 %3</td> </tr>"
397                                     "<tr> <td><b>%4:</b> %5 %3</td> </tr>"
398                                     "<tr> <td><b>%6:</b> %7°</td> </tr>"
399                                     "<tr> <td><b>%8:</b> %9°</td> </tr>"
400                                     "</table>")
401             .arg(tr("Length"))
402             .arg(VAbstractValApplication::VApp()->fromPixel(arc->GetLength()))
403             .arg(UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true), tr("Radius"))
404             .arg(VAbstractValApplication::VApp()->fromPixel(arc->GetRadius()))
405             .arg(tr("Start angle"))
406             .arg(arc->GetStartAngle())
407             .arg(tr("End angle"))
408             .arg(arc->GetEndAngle())
409             .arg(tr("Label"), arc->ObjectName());
410     return toolTip;
411 }
412