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