Seamly2D
Code documentation
intersect_circles_dialog.cpp
Go to the documentation of this file.
1 /**************************************************************************
2  **
3  ** @file intersect_circles_tool.cpp
4  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
5  ** @date 29 5, 2015
6  **
7  ** @author Douglas S. Caskey
8  ** @date 7.16.2022
9  **
10  ** @copyright
11  ** Copyright (C) 2013-2022 Seamly2D project.
12  ** This source code is part of the Seamly2D project, a pattern making
13  ** program, whose allow create and modeling patterns of clothing.
14  **
15  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
16  **
17  ** Seamly2D is free software: you can redistribute it and/or modify
18  ** it under the terms of the GNU General Public License as published
19  ** by the Free Software Foundation, either version 3 of the License,
20  ** or (at your option) any later version.
21  **
22  ** Seamly2D is distributed in the hope that it will be useful,
23  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
24  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  ** GNU General Public License for more details.
26  **
27  ** You should have received a copy of the GNU General Public License
28  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
29  **
30  *************************************************************************/
31 
33 #include "ui_intersect_circles_dialog.h"
34 
35 #include "../ifc/xml/vdomdocument.h"
36 #include "../support/edit_formula_dialog.h"
37 #include "../vmisc/vabstractapplication.h"
38 #include "../vmisc/vcommonsettings.h"
39 #include "../vpatterndb/vtranslatevars.h"
40 #include "../../visualization/visualization.h"
41 #include "../../visualization/line/intersect_circles_visual.h"
42 
43 #include <limits.h>
44 #include <QColor>
45 #include <QComboBox>
46 #include <QDialog>
47 #include <QLabel>
48 #include <QLineEdit>
49 #include <QPlainTextEdit>
50 #include <QPointer>
51 #include <QPushButton>
52 #include <QTimer>
53 #include <QToolButton>
54 #include <Qt>
55 
56 //---------------------------------------------------------------------------------------------------------------------
57 IntersectCirclesDialog::IntersectCirclesDialog(const VContainer *data, const quint32 &toolId, QWidget *parent)
58  : DialogTool(data, toolId, parent)
59  , ui(new Ui::IntersectCirclesDialog)
60  , flagCircle1Radius(false)
61  , flagCircle2Radius(false)
62  , timerCircle1Radius(nullptr)
63  , timerCircle2Radius(nullptr)
64  , circle1Radius()
65  , circle2Radius()
66  , formulaBaseHeightCircle1Radius(0)
67  , formulaBaseHeightCircle2Radius(0)
68 {
69  ui->setupUi(this);
70  setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
71  setWindowIcon(QIcon(":/toolicon/32x32/point_of_intersection_circles.png"));
72 
73  ui->lineEditNamePoint->setClearButtonEnabled(true);
74 
75  ui->lineEditNamePoint->setText(qApp->getCurrentDocument()->GenerateLabel(LabelType::NewLabel));
76  labelEditNamePoint = ui->labelEditNamePoint;
77 
78  plainTextEditFormula = ui->plainTextEditCircle1Radius;
79  this->formulaBaseHeightCircle1Radius = ui->plainTextEditCircle1Radius->height();
80  this->formulaBaseHeightCircle2Radius = ui->plainTextEditCircle2Radius->height();
81 
82  ui->plainTextEditCircle1Radius->installEventFilter(this);
83  ui->plainTextEditCircle2Radius->installEventFilter(this);
84 
85  timerCircle1Radius = new QTimer(this);
86  connect(timerCircle1Radius, &QTimer::timeout, this, &IntersectCirclesDialog::EvalCircle1Radius);
87 
88  timerCircle2Radius = new QTimer(this);
89  connect(timerCircle2Radius, &QTimer::timeout, this, &IntersectCirclesDialog::EvalCircle2Radius);
90 
92  CheckState();
93 
94  FillComboBoxPoints(ui->comboBoxCircle1Center);
95  FillComboBoxPoints(ui->comboBoxCircle2Center);
96  FillComboBoxCrossCirclesPoints(ui->comboBoxResult);
97 
98  connect(ui->lineEditNamePoint, &QLineEdit::textChanged,
100 
101  connect(ui->comboBoxCircle1Center, &QComboBox::currentTextChanged,
103 
104  connect(ui->comboBoxCircle2Center, &QComboBox::currentTextChanged,
106 
107  connect(ui->toolButtonExprCircle1Radius, &QPushButton::clicked, this,
109 
110  connect(ui->toolButtonExprCircle2Radius, &QPushButton::clicked, this,
112 
113  connect(ui->plainTextEditCircle1Radius, &QPlainTextEdit::textChanged, this,
115 
116  connect(ui->plainTextEditCircle2Radius, &QPlainTextEdit::textChanged, this,
118 
119  connect(ui->pushButtonGrowCircle1Radius, &QPushButton::clicked, this,
121 
122  connect(ui->pushButtonGrowCircle2Radius, &QPushButton::clicked, this,
124 
126 }
127 
128 //---------------------------------------------------------------------------------------------------------------------
130 {
131  delete ui;
132 }
133 
134 //---------------------------------------------------------------------------------------------------------------------
135 void IntersectCirclesDialog::SetPointName(const QString &value)
136 {
137  pointName = value;
138  ui->lineEditNamePoint->setText(pointName);
139 }
140 
141 //---------------------------------------------------------------------------------------------------------------------
143 {
144  return getCurrentObjectId(ui->comboBoxCircle1Center);
145 }
146 
147 //---------------------------------------------------------------------------------------------------------------------
149 {
150  setCurrentPointId(ui->comboBoxCircle1Center, value);
151 
152  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
153  SCASSERT(point != nullptr)
154  point->setObject1Id(value);
155 }
156 
157 //---------------------------------------------------------------------------------------------------------------------
159 {
160  return getCurrentObjectId(ui->comboBoxCircle2Center);
161 }
162 
163 //---------------------------------------------------------------------------------------------------------------------
165 {
166  setCurrentPointId(ui->comboBoxCircle2Center, value);
167 
168  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
169  SCASSERT(point != nullptr)
170  point->setObject2Id(value);
171 }
172 
173 //---------------------------------------------------------------------------------------------------------------------
175 {
176  return qApp->TrVars()->TryFormulaFromUser(ui->plainTextEditCircle1Radius->toPlainText(),
177  qApp->Settings()->GetOsSeparator());
178 }
179 
180 //---------------------------------------------------------------------------------------------------------------------
182 {
183  const QString formula = qApp->TrVars()->FormulaToUser(value, qApp->Settings()->GetOsSeparator());
184  // increase height if needed.
185  if (formula.length() > 80)
186  {
188  }
189  ui->plainTextEditCircle1Radius->setPlainText(formula);
190 
191  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
192  SCASSERT(point != nullptr)
193  point->setC1Radius(formula);
194 
195  MoveCursorToEnd(ui->plainTextEditCircle1Radius);
196 }
197 
198 //---------------------------------------------------------------------------------------------------------------------
200 {
201  return qApp->TrVars()->TryFormulaFromUser(ui->plainTextEditCircle2Radius->toPlainText(),
202  qApp->Settings()->GetOsSeparator());
203 }
204 
205 //---------------------------------------------------------------------------------------------------------------------
207 {
208  const QString formula = qApp->TrVars()->FormulaToUser(value, qApp->Settings()->GetOsSeparator());
209  // increase height if needed.
210  if (formula.length() > 80)
211  {
213  }
214  ui->plainTextEditCircle2Radius->setPlainText(formula);
215 
216  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
217  SCASSERT(point != nullptr)
218  point->setC2Radius(formula);
219 
220  MoveCursorToEnd(ui->plainTextEditCircle2Radius);
221 }
222 
223 //---------------------------------------------------------------------------------------------------------------------
225 {
226  return getCurrentCrossPoint<CrossCirclesPoint>(ui->comboBoxResult);
227 }
228 
229 //---------------------------------------------------------------------------------------------------------------------
231 {
232  const qint32 index = ui->comboBoxResult->findData(static_cast<int>(p));
233  if (index != -1)
234  {
235  ui->comboBoxResult->setCurrentIndex(index);
236 
237  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
238  SCASSERT(point != nullptr)
239  point->setCrossPoint(p);
240  }
241 }
242 
243 //---------------------------------------------------------------------------------------------------------------------
245 {
246  if (prepare == false)// After first choose we ignore all objects
247  {
248  if (type == SceneObject::Point)
249  {
250  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
251  SCASSERT(point != nullptr)
252 
253  switch (number)
254  {
255  case 0:
256  if (SetObject(id, ui->comboBoxCircle1Center, tr("Select second circle center")))
257  {
258  number++;
259  point->VisualMode(id);
260  }
261  break;
262  case 1:
263  if (getCurrentObjectId(ui->comboBoxCircle1Center) != id)
264  {
265  if (SetObject(id, ui->comboBoxCircle2Center, ""))
266  {
267  number = 0;
268  point->setObject2Id(id);
269  point->RefreshGeometry();
270  prepare = true;
271  this->setModal(true);
272  this->show();
273  }
274  }
275  break;
276  default:
277  break;
278  }
279  }
280  }
281 }
282 
283 //---------------------------------------------------------------------------------------------------------------------
285 {
286  QColor color = okColor;
287  if (getCurrentObjectId(ui->comboBoxCircle1Center) == getCurrentObjectId(ui->comboBoxCircle2Center))
288  {
289  flagError = false;
290  color = errorColor;
291  }
292  else
293  {
294  flagError = true;
295  color = okColor;
296  }
297  ChangeColor(ui->labelCircle1Center, color);
298  ChangeColor(ui->labelCircle1Center, color);
299  CheckState();
300 }
301 
302 //---------------------------------------------------------------------------------------------------------------------
304 {
305  DeployFormula(ui->plainTextEditCircle1Radius, ui->pushButtonGrowCircle1Radius, formulaBaseHeightCircle1Radius);
306 }
307 
308 //---------------------------------------------------------------------------------------------------------------------
310 {
311  DeployFormula(ui->plainTextEditCircle2Radius, ui->pushButtonGrowCircle2Radius, formulaBaseHeightCircle2Radius);
312 }
313 
314 //---------------------------------------------------------------------------------------------------------------------
316 {
317  labelEditFormula = ui->labelEditCircle1Radius;
318  labelResultCalculation = ui->labelResultCircle1Radius;
319  const QString postfix = UnitsToStr(qApp->patternUnit(), true);
320  ValFormulaChanged(flagCircle1Radius, ui->plainTextEditCircle1Radius, timerCircle1Radius, postfix);
321 }
322 
323 //---------------------------------------------------------------------------------------------------------------------
325 {
326  labelEditFormula = ui->labelEditCircle2Radius;
327  labelResultCalculation = ui->labelResultCircle2Radius;
328  const QString postfix = UnitsToStr(qApp->patternUnit(), true);
329  ValFormulaChanged(flagCircle2Radius, ui->plainTextEditCircle2Radius, timerCircle2Radius, postfix);
330 }
331 
332 //---------------------------------------------------------------------------------------------------------------------
334 {
335  EditFormulaDialog *dialog = new EditFormulaDialog(data, toolId, this);
336  dialog->setWindowTitle(tr("Edit first circle radius"));
337  dialog->SetFormula(GetFirstCircleRadius());
338  dialog->setPostfix(UnitsToStr(qApp->patternUnit(), true));
339  if (dialog->exec() == QDialog::Accepted)
340  {
341  SetFirstCircleRadius(dialog->GetFormula());
342  }
343  delete dialog;
344 }
345 
346 //---------------------------------------------------------------------------------------------------------------------
348 {
349  EditFormulaDialog *dialog = new EditFormulaDialog(data, toolId, this);
350  dialog->setWindowTitle(tr("Edit second circle radius"));
352  dialog->setPostfix(UnitsToStr(qApp->patternUnit(), true));
353  if (dialog->exec() == QDialog::Accepted)
354  {
356  }
357  delete dialog;
358 }
359 
360 //---------------------------------------------------------------------------------------------------------------------
362 {
363  labelEditFormula = ui->labelEditCircle1Radius;
364  const QString postfix = UnitsToStr(qApp->patternUnit(), true);
365  const qreal radius = Eval(ui->plainTextEditCircle1Radius->toPlainText(), flagCircle1Radius,
366  ui->labelResultCircle1Radius, postfix);
367 
368  if (radius < 0)
369  {
370  flagCircle2Radius = false;
371  ChangeColor(labelEditFormula, Qt::red);
372  ui->labelResultCircle1Radius->setText(tr("Error"));
373  ui->labelResultCircle1Radius->setToolTip(tr("Radius can't be negative"));
374 
376  }
377 }
378 
379 //---------------------------------------------------------------------------------------------------------------------
381 {
382  labelEditFormula = ui->labelEditCircle2Radius;
383  const QString postfix = UnitsToStr(qApp->patternUnit(), true);
384  const qreal radius = Eval(ui->plainTextEditCircle2Radius->toPlainText(), flagCircle2Radius,
385  ui->labelResultCircle2Radius, postfix);
386 
387  if (radius < 0)
388  {
389  flagCircle2Radius = false;
390  ChangeColor(labelEditFormula, Qt::red);
391  ui->labelResultCircle2Radius->setText(tr("Error"));
392  ui->labelResultCircle2Radius->setToolTip(tr("Radius can't be negative"));
393 
395  }
396 }
397 
398 //---------------------------------------------------------------------------------------------------------------------
400 {
401  AddVisualization<IntersectCirclesVisual>();
402 }
403 
404 //---------------------------------------------------------------------------------------------------------------------
406 {
407  pointName = ui->lineEditNamePoint->text();
408 
409  QString c1Radius = ui->plainTextEditCircle2Radius->toPlainText();
410  c1Radius.replace("\n", " ");
411 
412  QString c2Radius = ui->plainTextEditCircle2Radius->toPlainText();
413  c2Radius.replace("\n", " ");
414 
415  IntersectCirclesVisual *point = qobject_cast<IntersectCirclesVisual *>(vis);
416  SCASSERT(point != nullptr)
417 
420  point->setC1Radius(c1Radius);
421  point->setC2Radius(c2Radius);
423  point->RefreshGeometry();
424 }
425 
426 //---------------------------------------------------------------------------------------------------------------------
427 void IntersectCirclesDialog::closeEvent(QCloseEvent *event)
428 {
429  ui->plainTextEditCircle1Radius->blockSignals(true);
430  ui->plainTextEditCircle2Radius->blockSignals(true);
431  DialogTool::closeEvent(event);
432 }
433 
434 //---------------------------------------------------------------------------------------------------------------------
436 {
437  SCASSERT(ok_Button != nullptr)
439  // In case dialog hasn't apply button
440  if (apply_Button != nullptr)
441  {
442  apply_Button->setEnabled(ok_Button->isEnabled());
443  }
444 }
The DialogTool class parent for all dialog of tools.
Definition: dialogtool.h:107
void setCurrentPointId(QComboBox *box, const quint32 &value, FillComboBox rule=FillComboBox::NoChildren, const quint32 &ch1=NULL_ID, const quint32 &ch2=NULL_ID) const
Definition: dialogtool.cpp:896
const QColor okColor
Definition: dialogtool.h:219
void FillComboBoxPoints(QComboBox *box, FillComboBox rule=FillComboBox::Whole, const quint32 &ch1=NULL_ID, const quint32 &ch2=NULL_ID) const
FillComboBoxPoints fill comboBox list of points.
Definition: dialogtool.cpp:242
void NamePointChanged()
NamePointChanged check name of point.
bool flagName
flagName true if name is correct
Definition: dialogtool.h:183
void FillComboBoxCrossCirclesPoints(QComboBox *box) const
Definition: dialogtool.cpp:373
void MoveCursorToEnd(QPlainTextEdit *plainTextEdit) const
Definition: dialogtool.cpp:432
QPushButton * ok_Button
ok_Button button ok
Definition: dialogtool.h:199
bool flagFormula
flagFormula true if formula correct
Definition: dialogtool.h:186
QString pointName
pointName name of point
Definition: dialogtool.h:231
qreal Eval(const QString &text, bool &flag, QLabel *label, const QString &postfix, bool checkZero=true, bool checkLessThanZero=false)
Eval evaluate formula and show result.
Definition: dialogtool.cpp:805
const QColor errorColor
Definition: dialogtool.h:220
qint32 number
number number of handled objects
Definition: dialogtool.h:234
virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE
closeEvent handle when dialog cloded
Definition: dialogtool.cpp:192
void ValFormulaChanged(bool &flag, QLineEdit *edit, QTimer *timer, const QString &postfix=QString())
ValFormulaChanged handle change formula.
Definition: dialogtool.cpp:744
bool SetObject(const quint32 &id, QComboBox *box, const QString &toolTip)
Definition: dialogtool.cpp:974
QPushButton * apply_Button
apply_Button button apply
Definition: dialogtool.h:202
QLabel * labelEditNamePoint
labelEditNamePoint label used when need show wrong name of point
Definition: dialogtool.h:214
quint32 toolId
Definition: dialogtool.h:225
QLabel * labelEditFormula
labelEditFormula label used when need show wrong formula
Definition: dialogtool.h:217
void initializeOkCancelApply(T *ui)
initializeOkCancelApply initialize OK / Cancel and Apply buttons
Definition: dialogtool.h:365
bool flagError
flagError use this flag if for you do not enought
Definition: dialogtool.h:193
const VContainer * data
data container with data
Definition: dialogtool.h:177
QPlainTextEdit * plainTextEditFormula
plainTextEditFormula formula
Definition: dialogtool.h:208
bool prepare
prepare show if we prepare. Show dialog after finish working with visual part of tool
Definition: dialogtool.h:228
QLabel * labelResultCalculation
labelResultCalculation label with result of calculation
Definition: dialogtool.h:211
QPointer< Visualization > vis
Definition: dialogtool.h:236
void ChangeColor(QWidget *widget, const QColor &color)
void DeployFormula(QPlainTextEdit *formula, QPushButton *buttonGrowLength, int formulaBaseHeight)
Definition: dialogtool.cpp:992
quint32 getCurrentObjectId(QComboBox *box) const
getCurrentPointId return current point id stored in combobox
Definition: dialogtool.cpp:959
The EditFormulaDialog class dialog for editing wrong formula.
QString GetFormula() const
void SetFormula(const QString &value)
void setPostfix(const QString &value)
void SetFirstCircleRadius(const QString &value)
void SetSecondCircleRadius(const QString &value)
virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE
closeEvent handle when dialog cloded
virtual ~IntersectCirclesDialog() Q_DECL_OVERRIDE
void SetPointName(const QString &value)
virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE
virtual void ShowVisualization() Q_DECL_OVERRIDE
Ui::IntersectCirclesDialog * ui
virtual void SaveData() Q_DECL_OVERRIDE
SaveData Put dialog data in local variables.
CrossCirclesPoint GetCrossCirclesPoint() const
void SetFirstCircleCenterId(const quint32 &value)
void SetSecondCircleCenterId(const quint32 &value)
void setCirclesCrossPoint(const CrossCirclesPoint &p)
virtual void CheckState() Q_DECL_FINAL
CheckState enable, when all is correct, or disable, when something wrong, button ok.
IntersectCirclesDialog(const VContainer *data, const quint32 &toolId, QWidget *parent=nullptr)
void setC1Radius(const QString &value)
virtual void RefreshGeometry() Q_DECL_OVERRIDE
void setObject2Id(const quint32 &value)
void setCrossPoint(const CrossCirclesPoint &value)
virtual void VisualMode(const quint32 &id) Q_DECL_OVERRIDE
void setC2Radius(const QString &value)
The VContainer class container of all variables.
Definition: vcontainer.h:141
void setObject1Id(const quint32 &value)
QString UnitsToStr(const Unit &unit, const bool translate)
UnitsToStr translate unit to string.
Definition: def.cpp:702
#define SCASSERT(cond)
Definition: def.h:317
SceneObject
Definition: def.h:103
CrossCirclesPoint
#define qApp
Definition: vapplication.h:67