1 /************************************************************************
2 **
3 ** @file dialogpointfromcircleandtangent.cpp
4 ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5 ** @date 3 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 "dialogpointfromcircleandtangent.h"
30
31 #include <climits>
32 #include <QColor>
33 #include <QComboBox>
34 #include <QDialog>
35 #include <QLabel>
36 #include <QLineEdit>
37 #include <QPlainTextEdit>
38 #include <QPointer>
39 #include <QPushButton>
40 #include <QTimer>
41 #include <QToolButton>
42 #include <Qt>
43
44 #include "../vpatterndb/vtranslatevars.h"
45 #include "../vpatterndb/vcontainer.h"
46 #include "../../visualization/visualization.h"
47 #include "../../visualization/line/vistoolpointfromcircleandtangent.h"
48 #include "../ifc/xml/vdomdocument.h"
49 #include "../support/dialogeditwrongformula.h"
50 #include "../vmisc/vabstractapplication.h"
51 #include "../vmisc/vcommonsettings.h"
52 #include "ui_dialogpointfromcircleandtangent.h"
53
54 //---------------------------------------------------------------------------------------------------------------------
DialogPointFromCircleAndTangent(const VContainer * data,quint32 toolId,QWidget * parent)55 DialogPointFromCircleAndTangent::DialogPointFromCircleAndTangent(const VContainer *data, quint32 toolId,
56 QWidget *parent)
57 : DialogTool(data, toolId, parent),
58 ui(new Ui::DialogPointFromCircleAndTangent),
59 timerCircleRadius(nullptr),
60 circleRadius(),
61 formulaBaseHeightCircleRadius(0),
62 pointName(),
63 flagCircleRadius(false),
64 flagName(true),
65 flagError(true)
66 {
67 ui->setupUi(this);
68
69 ui->lineEditNamePoint->setClearButtonEnabled(true);
70
71 ui->lineEditNamePoint->setText(
72 VAbstractValApplication::VApp()->getCurrentDocument()->GenerateLabel(LabelType::NewLabel));
73
74 this->formulaBaseHeightCircleRadius = ui->plainTextEditRadius->height();
75
76 ui->plainTextEditRadius->installEventFilter(this);
77
78 timerCircleRadius = new QTimer(this);
79 connect(timerCircleRadius, &QTimer::timeout, this, &DialogPointFromCircleAndTangent::EvalCircleRadius);
80
81 InitOkCancelApply(ui);
82
83 FillComboBoxPoints(ui->comboBoxCircleCenter);
84 FillComboBoxPoints(ui->comboBoxTangentPoint);
85 FillComboBoxCrossCirclesPoints(ui->comboBoxResult);
86
87 connect(ui->lineEditNamePoint, &QLineEdit::textChanged, this, [this]()
88 {
89 CheckPointLabel(this, ui->lineEditNamePoint, ui->labelEditNamePoint, pointName, this->data, flagName);
90 CheckState();
91 });
92 connect(ui->comboBoxCircleCenter, &QComboBox::currentTextChanged,
93 this, &DialogPointFromCircleAndTangent::PointChanged);
94
95 connect(ui->toolButtonExprRadius, &QPushButton::clicked, this,
96 &DialogPointFromCircleAndTangent::FXCircleRadius);
97
98 connect(ui->plainTextEditRadius, &QPlainTextEdit::textChanged, this, [this]()
99 {
100 timerCircleRadius->start(formulaTimerTimeout);
101 });
102
103 connect(ui->pushButtonGrowRadius, &QPushButton::clicked, this,
104 &DialogPointFromCircleAndTangent::DeployCircleRadiusTextEdit);
105
106 vis = new VisToolPointFromCircleAndTangent(data);
107
108 ui->tabWidget->setCurrentIndex(0);
109 SetTabStopDistance(ui->plainTextEditToolNotes);
110 }
111
112 //---------------------------------------------------------------------------------------------------------------------
~DialogPointFromCircleAndTangent()113 DialogPointFromCircleAndTangent::~DialogPointFromCircleAndTangent()
114 {
115 delete ui;
116 }
117
118 //---------------------------------------------------------------------------------------------------------------------
GetPointName() const119 QString DialogPointFromCircleAndTangent::GetPointName() const
120 {
121 return pointName;
122 }
123
124 //---------------------------------------------------------------------------------------------------------------------
SetPointName(const QString & value)125 void DialogPointFromCircleAndTangent::SetPointName(const QString &value)
126 {
127 pointName = value;
128 ui->lineEditNamePoint->setText(pointName);
129 }
130
131 //---------------------------------------------------------------------------------------------------------------------
GetCircleCenterId() const132 quint32 DialogPointFromCircleAndTangent::GetCircleCenterId() const
133 {
134 return getCurrentObjectId(ui->comboBoxCircleCenter);
135 }
136
137 //---------------------------------------------------------------------------------------------------------------------
SetCircleCenterId(const quint32 & value)138 void DialogPointFromCircleAndTangent::SetCircleCenterId(const quint32 &value)
139 {
140 setCurrentPointId(ui->comboBoxCircleCenter, value);
141
142 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
143 SCASSERT(point != nullptr)
144 point->setObject2Id(value);
145 }
146
147 //---------------------------------------------------------------------------------------------------------------------
GetCircleRadius() const148 QString DialogPointFromCircleAndTangent::GetCircleRadius() const
149 {
150 return VAbstractApplication::VApp()->TrVars()
151 ->TryFormulaFromUser(ui->plainTextEditRadius->toPlainText(),
152 VAbstractApplication::VApp()->Settings()->GetOsSeparator());
153 }
154
155 //---------------------------------------------------------------------------------------------------------------------
SetCircleRadius(const QString & value)156 void DialogPointFromCircleAndTangent::SetCircleRadius(const QString &value)
157 {
158 const QString formula = VAbstractApplication::VApp()->TrVars()
159 ->FormulaToUser(value, VAbstractApplication::VApp()->Settings()->GetOsSeparator());
160 // increase height if needed.
161 if (formula.length() > 80)
162 {
163 this->DeployCircleRadiusTextEdit();
164 }
165 ui->plainTextEditRadius->setPlainText(formula);
166
167 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
168 SCASSERT(point != nullptr)
169 point->setCRadius(formula);
170
171 MoveCursorToEnd(ui->plainTextEditRadius);
172 }
173
174 //---------------------------------------------------------------------------------------------------------------------
GetTangentPointId() const175 quint32 DialogPointFromCircleAndTangent::GetTangentPointId() const
176 {
177 return getCurrentObjectId(ui->comboBoxTangentPoint);
178 }
179
180 //---------------------------------------------------------------------------------------------------------------------
SetTangentPointId(const quint32 & value)181 void DialogPointFromCircleAndTangent::SetTangentPointId(const quint32 &value)
182 {
183 setCurrentPointId(ui->comboBoxTangentPoint, value);
184
185 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
186 SCASSERT(point != nullptr)
187 point->setObject1Id(value);
188 }
189
190 //---------------------------------------------------------------------------------------------------------------------
GetCrossCirclesPoint() const191 CrossCirclesPoint DialogPointFromCircleAndTangent::GetCrossCirclesPoint() const
192 {
193 return getCurrentCrossPoint<CrossCirclesPoint>(ui->comboBoxResult);
194 }
195
196 //---------------------------------------------------------------------------------------------------------------------
SetCrossCirclesPoint(const CrossCirclesPoint & p)197 void DialogPointFromCircleAndTangent::SetCrossCirclesPoint(const CrossCirclesPoint &p)
198 {
199 const qint32 index = ui->comboBoxResult->findData(static_cast<int>(p));
200 if (index != -1)
201 {
202 ui->comboBoxResult->setCurrentIndex(index);
203
204 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
205 SCASSERT(point != nullptr)
206 point->setCrossPoint(p);
207 }
208 }
209
210 //---------------------------------------------------------------------------------------------------------------------
ChosenObject(quint32 id,const SceneObject & type)211 void DialogPointFromCircleAndTangent::ChosenObject(quint32 id, const SceneObject &type)
212 {
213 if (prepare == false)// After first choose we ignore all objects
214 {
215 if (type == SceneObject::Point)
216 {
217 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
218 SCASSERT(point != nullptr)
219
220 switch (number)
221 {
222 case 0:
223 if (SetObject(id, ui->comboBoxTangentPoint, tr("Select a circle center")))
224 {
225 number++;
226 point->VisualMode(id);
227 }
228 break;
229 case 1:
230 if (getCurrentObjectId(ui->comboBoxTangentPoint) != id)
231 {
232 if (SetObject(id, ui->comboBoxCircleCenter, QString()))
233 {
234 number = 0;
235 point->setObject2Id(id);
236 point->RefreshGeometry();
237 prepare = true;
238 this->setModal(true);
239 this->show();
240 }
241 }
242 break;
243 default:
244 break;
245 }
246 }
247 }
248 }
249
250 //---------------------------------------------------------------------------------------------------------------------
PointChanged()251 void DialogPointFromCircleAndTangent::PointChanged()
252 {
253 QColor color;
254 if (getCurrentObjectId(ui->comboBoxCircleCenter) == getCurrentObjectId(ui->comboBoxTangentPoint))
255 {
256 flagError = false;
257 color = errorColor;
258 }
259 else
260 {
261 flagError = true;
262 color = OkColor(this);
263 }
264 ChangeColor(ui->labelCircleCenter, color);
265 ChangeColor(ui->labelTangentPoint, color);
266 CheckState();
267 }
268
269 //---------------------------------------------------------------------------------------------------------------------
DeployCircleRadiusTextEdit()270 void DialogPointFromCircleAndTangent::DeployCircleRadiusTextEdit()
271 {
272 DeployFormula(this, ui->plainTextEditRadius, ui->pushButtonGrowRadius, formulaBaseHeightCircleRadius);
273 }
274
275 //---------------------------------------------------------------------------------------------------------------------
FXCircleRadius()276 void DialogPointFromCircleAndTangent::FXCircleRadius()
277 {
278 DialogEditWrongFormula *dialog = new DialogEditWrongFormula(data, toolId, this);
279 dialog->setWindowTitle(tr("Edit radius"));
280 dialog->SetFormula(GetCircleRadius());
281 dialog->setPostfix(UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true));
282 if (dialog->exec() == QDialog::Accepted)
283 {
284 SetCircleRadius(dialog->GetFormula());
285 }
286 delete dialog;
287 }
288
289 //---------------------------------------------------------------------------------------------------------------------
EvalCircleRadius()290 void DialogPointFromCircleAndTangent::EvalCircleRadius()
291 {
292 FormulaData formulaData;
293 formulaData.formula = ui->plainTextEditRadius->toPlainText();
294 formulaData.variables = data->DataVariables();
295 formulaData.labelEditFormula = ui->labelEditRadius;
296 formulaData.labelResult = ui->labelResultCircleRadius;
297 formulaData.postfix = UnitsToStr(VAbstractValApplication::VApp()->patternUnits(), true);
298
299 const qreal radius = Eval(formulaData, flagCircleRadius);
300
301 if (radius < 0)
302 {
303 flagCircleRadius = false;
304 ChangeColor(ui->labelEditRadius, errorColor);
305 ui->labelResultCircleRadius->setText(tr("Error"));
306 ui->labelResultCircleRadius->setToolTip(tr("Radius can't be negative"));
307
308 DialogPointFromCircleAndTangent::CheckState();
309 }
310 }
311
312 //---------------------------------------------------------------------------------------------------------------------
ShowVisualization()313 void DialogPointFromCircleAndTangent::ShowVisualization()
314 {
315 AddVisualization<VisToolPointFromCircleAndTangent>();
316 }
317
318 //---------------------------------------------------------------------------------------------------------------------
SaveData()319 void DialogPointFromCircleAndTangent::SaveData()
320 {
321 pointName = ui->lineEditNamePoint->text();
322
323 VisToolPointFromCircleAndTangent *point = qobject_cast<VisToolPointFromCircleAndTangent *>(vis);
324 SCASSERT(point != nullptr)
325
326 point->setObject1Id(GetTangentPointId());
327 point->setObject2Id(GetCircleCenterId());
328 point->setCRadius(ui->plainTextEditRadius->toPlainText());
329 point->setCrossPoint(GetCrossCirclesPoint());
330 point->RefreshGeometry();
331 }
332
333 //---------------------------------------------------------------------------------------------------------------------
closeEvent(QCloseEvent * event)334 void DialogPointFromCircleAndTangent::closeEvent(QCloseEvent *event)
335 {
336 ui->plainTextEditRadius->blockSignals(true);
337 DialogTool::closeEvent(event);
338 }
339
340 //---------------------------------------------------------------------------------------------------------------------
SetNotes(const QString & notes)341 void DialogPointFromCircleAndTangent::SetNotes(const QString ¬es)
342 {
343 ui->plainTextEditToolNotes->setPlainText(notes);
344 }
345
346 //---------------------------------------------------------------------------------------------------------------------
GetNotes() const347 QString DialogPointFromCircleAndTangent::GetNotes() const
348 {
349 return ui->plainTextEditToolNotes->toPlainText();
350 }
351