Seamly2D
Code documentation
dialogvariables.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2017 Seamly, LLC *
4  * *
5  * https://github.com/fashionfreedom/seamly2d *
6  * *
7  ***************************************************************************
8  **
9  ** Seamly2D is free software: you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation, either version 3 of the License, or
12  ** (at your option) any later version.
13  **
14  ** Seamly2D is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** You should have received a copy of the GNU General Public License
20  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
21  **
22  **************************************************************************
23 
24  ************************************************************************
25  **
26  ** @file dialogvariables.cpp
27  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
28  ** @date November 15, 2013
29  **
30  ** @brief
31  ** @copyright
32  ** This source code is part of the Valentine project, a pattern making
33  ** program, whose allow create and modeling patterns of clothing.
34  ** Copyright (C) 2013-2015 Seamly2D project
35  ** <https://github.com/fashionfreedom/seamly2d> All Rights Reserved.
36  **
37  ** Seamly2D is free software: you can redistribute it and/or modify
38  ** it under the terms of the GNU General Public License as published by
39  ** the Free Software Foundation, either version 3 of the License, or
40  ** (at your option) any later version.
41  **
42  ** Seamly2D is distributed in the hope that it will be useful,
43  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
44  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45  ** GNU General Public License for more details.
46  **
47  ** You should have received a copy of the GNU General Public License
48  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
49  **
50  *************************************************************************/
51 
52 #include "dialogvariables.h"
53 #include "ui_dialogvariables.h"
54 #include "../vwidgets/vwidgetpopup.h"
55 #include "../vmisc/vsettings.h"
56 #include "../qmuparser/qmudef.h"
57 #include "../qmuparser/qmutokenparser.h"
58 #include "../vpatterndb/vtranslatevars.h"
59 #include "../vpatterndb/calculator.h"
60 #include "../vtools/dialogs/support/edit_formula_dialog.h"
61 
62 #include <QFileDialog>
63 #include <QDir>
64 #include <QMessageBox>
65 #include <QCloseEvent>
66 #include <QTableWidget>
67 #include <QSettings>
68 #include <QTableWidgetItem>
69 #include <QtNumeric>
70 
71 #define DIALOG_MAX_FORMULA_HEIGHT 64
72 
73 //---------------------------------------------------------------------------------------------------------------------
74 /**
75  * @brief DialogVariables create dialog
76  * @param data container with data
77  * @param doc dom document container
78  * @param parent parent widget
79  */
81  : DialogTool(data, NULL_ID, parent)
82  , ui(new Ui::DialogVariables)
83  , data(data)
84  , doc(doc)
85  , formulaBaseHeight(0)
86  , hasChanges(false)
87  , renameList()
88  , tableList()
89  , isSorted(false)
90  , isFiltered(false)
91 {
92  ui->setupUi(this);
93 
94  setWindowFlags(Qt::Window);
95  setWindowFlags((windowFlags() | Qt::WindowStaysOnTopHint) & ~Qt::WindowContextHelpButtonHint);
96 
97  ui->name_LineEdit->setClearButtonEnabled(true);
98  ui->filter_LineEdit->installEventFilter(this);
99 
100  formulaBaseHeight = ui->formula_PlainTextEdit->height();
101  ui->formula_PlainTextEdit->installEventFilter(this);
102 
103  qApp->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
104 
105  qCDebug(vDialog, "Showing variables.");
106  showUnits();
107 
108  const bool freshCall = true;
109  fillCustomVariables(freshCall);
110  fillLineLengths();
111  fillLineAngles();
115  fillCurveAngles();
116 
117 
118  tableList.append(QSharedPointer<QTableWidget>(ui->variables_TableWidget));
119  tableList.append(QSharedPointer<QTableWidget>(ui->lineLengths_TableWidget));
120  tableList.append(QSharedPointer<QTableWidget>(ui->lineAngles_TableWidget));
121  tableList.append(QSharedPointer<QTableWidget>(ui->curveLengths_TableWidget));
122  tableList.append(QSharedPointer<QTableWidget>(ui->curveAngles_TableWidget));
123  tableList.append(QSharedPointer<QTableWidget>(ui->controlPointLengths_TableWidget));
124  tableList.append(QSharedPointer<QTableWidget>(ui->arcRadiuses_TableWidget));
125 
127 
128  ui->tabWidget->setCurrentIndex(0);
129  ui->name_LineEdit->setValidator( new QRegularExpressionValidator(QRegularExpression(
130  QLatin1String("^$|")+NameRegExp()), this));
131 
132  connect(ui->variables_TableWidget, &QTableWidget::itemSelectionChanged, this,
134 
135  connect(ui->addCustomVariable_ToolButton, &QPushButton::clicked, this, &DialogVariables::addCustomVariable);
136  connect(ui->removeCustomVariable_ToolButton, &QToolButton::clicked, this, &DialogVariables::removeCustomVariable);
137  connect(ui->toolButtonUp, &QToolButton::clicked, this, &DialogVariables::moveUp);
138  connect(ui->toolButtonDown, &QToolButton::clicked, this, &DialogVariables::moveDown);
139  connect(ui->formula_ToolButton, &QToolButton::clicked, this, &DialogVariables::Fx);
140  connect(ui->name_LineEdit, &QLineEdit::textEdited, this, &DialogVariables::saveCustomVariableName);
141  connect(ui->description_PlainTextEdit, &QPlainTextEdit::textChanged, this, &DialogVariables::saveCustomVariableDescription);
142  connect(ui->formula_PlainTextEdit, &QPlainTextEdit::textChanged, this, &DialogVariables::saveCustomVariableFormula);
143 
144  connect(ui->filter_LineEdit, &QLineEdit::textChanged, this, &DialogVariables::filterVariables);
145 
146  connect(ui->refresh_PushButton, &QPushButton::clicked, this, &DialogVariables::refreshPattern);
147 
148  connect(ui->variables_TableWidget->horizontalHeader(), &QHeaderView::sectionClicked, [this]()
149  {
150  isSorted = true;
151  setMoveControls();
152  });
153 
154  if (ui->variables_TableWidget->rowCount() > 0)
155  {
156  ui->variables_TableWidget->selectRow(0);
157  }
158 
159  // clear text filter string every time a new tab is selected
160  auto clearFilterString = [this] ()
161  {
162  ui->filter_LineEdit->clear();
163  isFiltered = false;
164 
165  if (ui->tabWidget->currentIndex() == 0)
166  {
167  filterVariables("");
168  ui->variables_TableWidget->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder);
169  isSorted = false;
170  setMoveControls();
171  }
172  };
173  connect(ui->tabWidget, &QTabWidget::currentChanged, this, clearFilterString);
174 }
175 
176 //---------------------------------------------------------------------------------------------------------------------
178 {
179  delete ui;
180 }
181 
182 //---------------------------------------------------------------------------------------------------------------------
183 /**
184  * @brief fillCustomVariables fill data for variables table
185  */
187 {
188  ui->variables_TableWidget->blockSignals(true);
189  ui->variables_TableWidget->clearContents();
190 
192  QMap<QString, QSharedPointer<VIncrement> >::const_iterator i;
194  //Sorting QHash by id
195  for (i = variables.constBegin(); i != variables.constEnd(); ++i)
196  {
197  QSharedPointer<VIncrement> variable = i.value();
198  map.insert(variable->getIndex(), i.key());
199  }
200 
201  qint32 currentRow = -1;
202  QMapIterator<quint32, QString> iMap(map);
203  ui->variables_TableWidget->setRowCount ( variables.size() );
204  while (iMap.hasNext())
205  {
206  iMap.next();
207  QSharedPointer<VIncrement> variable = variables.value(iMap.value());
208  currentRow++;
209 
210  addCell(ui->variables_TableWidget, variable->GetName(), currentRow, 0, Qt::AlignVCenter); // name
211  addCell(ui->variables_TableWidget, qApp->LocaleToString(*variable->GetValue()), currentRow, 1,
212  Qt::AlignHCenter | Qt::AlignVCenter, variable->IsFormulaOk()); // calculated value
213 
214  QString formula;
215  try
216  {
217  formula = qApp->TrVars()->FormulaToUser(variable->GetFormula(), qApp->Settings()->GetOsSeparator());
218  }
219  catch (qmu::QmuParserError &e)
220  {
221  Q_UNUSED(e)
222  formula = variable->GetFormula();
223  }
224 
225  addCell(ui->variables_TableWidget, formula, currentRow, 2, Qt::AlignVCenter); // formula
226  }
227 
228  if (freshCall)
229  {
230  ui->variables_TableWidget->resizeColumnsToContents();
231  ui->variables_TableWidget->resizeRowsToContents();
232  }
233 
234  ui->variables_TableWidget->setColumnWidth(0, 350);
235  ui->variables_TableWidget->horizontalHeader()->setStretchLastSection(true);
236  ui->variables_TableWidget->blockSignals(false);
237 }
238 
239 //---------------------------------------------------------------------------------------------------------------------
240 template <typename T>
241 void DialogVariables::fillTable(const QMap<QString, T> &varTable, QTableWidget *table)
242 {
243  SCASSERT(table != nullptr)
244 
245  qint32 currentRow = -1;
246  QMapIterator<QString, T> i(varTable);
247  while (i.hasNext())
248  {
249  i.next();
250  qreal length = *i.value()->GetValue();
251  currentRow++;
252  table->setRowCount ( varTable.size() );
253 
254  QTableWidgetItem *item = new QTableWidgetItem(i.key());
255  item->setTextAlignment(Qt::AlignLeft);
256  table->setItem(currentRow, 0, item);
257 
258  item = new QTableWidgetItem(qApp->LocaleToString(length));
259  item->setTextAlignment(Qt::AlignHCenter);
260  table->setItem(currentRow, 1, item);
261  }
262  table->resizeColumnsToContents();
263  table->resizeRowsToContents();
264  table->verticalHeader()->setDefaultSectionSize(20);
265 }
266 
267 //---------------------------------------------------------------------------------------------------------------------
268 /**
269  * @brief FillLengthLines fill data for table of lines lengths
270  */
272 {
273  fillTable(data->lineLengthsData(), ui->lineLengths_TableWidget);
274 }
275 
276 //---------------------------------------------------------------------------------------------------------------------
278 {
279  fillTable(data->lineAnglesData(), ui->lineAngles_TableWidget);
280 }
281 
282 //---------------------------------------------------------------------------------------------------------------------
283 /**
284  * @brief FillLengthSplines fill data for table of splines lengths
285  */
287 {
288  fillTable(data->curveLengthsData(), ui->curveLengths_TableWidget);
289 }
290 
291 //---------------------------------------------------------------------------------------------------------------------
293 {
294  fillTable(data->controlPointLengthsData(), ui->controlPointLengths_TableWidget);
295 }
296 
297 //---------------------------------------------------------------------------------------------------------------------
299 {
300  fillTable(data->arcRadiusesData(), ui->arcRadiuses_TableWidget);
301 }
302 
303 //---------------------------------------------------------------------------------------------------------------------
305 {
306  fillTable(data->curveAnglesData(), ui->curveAngles_TableWidget);
307 }
308 
309 //---------------------------------------------------------------------------------------------------------------------
311 {
312  const QString unit = UnitsToStr(qApp->patternUnit());
313 
314  showHeaderUnits(ui->variables_TableWidget, 1, unit);// calculated value
315  showHeaderUnits(ui->variables_TableWidget, 2, unit);// formula
316 
317  showHeaderUnits(ui->lineLengths_TableWidget, 1, unit);// lengths
318  showHeaderUnits(ui->curveLengths_TableWidget, 1, unit);// lengths
319  showHeaderUnits(ui->controlPointLengths_TableWidget, 1, unit);// lengths
320  showHeaderUnits(ui->lineAngles_TableWidget, 1, degreeSymbol);// angle
321  showHeaderUnits(ui->arcRadiuses_TableWidget, 1, unit);// radius
322  showHeaderUnits(ui->curveAngles_TableWidget, 1, degreeSymbol);// angle
323 }
324 
325 //---------------------------------------------------------------------------------------------------------------------
326 void DialogVariables::showHeaderUnits(QTableWidget *table, int column, const QString &unit)
327 {
328  SCASSERT(table != nullptr)
329 
330  const QString header = table->horizontalHeaderItem(column)->text();
331  const QString unitHeader = QString("%1 (%2)").arg(header).arg(unit);
332  table->horizontalHeaderItem(column)->setText(unitHeader);
333 }
334 
335 //---------------------------------------------------------------------------------------------------------------------
336 void DialogVariables::addCell(QTableWidget *table, const QString &text, int row, int column, int aligment, bool ok)
337 {
338  SCASSERT(table != nullptr)
339 
340  QTableWidgetItem *item = new QTableWidgetItem(text);
341  item->setTextAlignment(aligment);
342 
343  // set the item non-editable (view only), and non-selectable
344  Qt::ItemFlags flags = item->flags();
345  flags &= ~(Qt::ItemIsEditable); // reset/clear the flag
346  item->setFlags(flags);
347 
348  if (not ok)
349  {
350  QBrush brush = item->foreground();
351  brush.setColor(Qt::red);
352  item->setForeground(brush);
353  }
354 
355  table->setItem(row, column, item);
356 }
357 
358 //---------------------------------------------------------------------------------------------------------------------
360 {
361  qint32 num = 1;
362  QString name;
363  do
364  {
365  name = CustomIncrSign + qApp->TrVars()->InternalVarToUser(variable_) + QString().number(num);
366  num++;
367  } while (not data->IsUnique(name));
368  return name;
369 }
370 
371 //---------------------------------------------------------------------------------------------------------------------
372 QString DialogVariables::clearCustomVariableName(const QString &name) const
373 {
374  QString clear = name;
375  const int index = clear.indexOf(CustomIncrSign);
376  if (index == 0)
377  {
378  clear.remove(0, 1);
379  }
380  return clear;
381 }
382 
383 //---------------------------------------------------------------------------------------------------------------------
384 bool DialogVariables::evalVariableFormula(const QString &formula, bool fromUser, VContainer *data, QLabel *label)
385 {
386  const QString postfix = UnitsToStr(qApp->patternUnit());//Show unit in dialog label (cm, mm or inch)
387  if (formula.isEmpty())
388  {
389  label->setText(tr("Error") + " (" + postfix + "). " + tr("Empty field."));
390  label->setToolTip(tr("Empty field"));
391  return false;
392  }
393  else
394  {
395  try
396  {
397  QString f;
398  // Replace line return character with spaces for calc if exist
399  if (fromUser)
400  {
401  f = qApp->TrVars()->FormulaFromUser(formula, qApp->Settings()->GetOsSeparator());
402  }
403  else
404  {
405  f = formula;
406  }
407  f.replace("\n", " ");
408  QScopedPointer<Calculator> cal(new Calculator());
409  const qreal result = cal->EvalFormula(data->DataVariables(), f);
410 
411  if (qIsInf(result) || qIsNaN(result))
412  {
413  label->setText(tr("Error") + " (" + postfix + ").");
414  label->setToolTip(tr("Invalid result. Value is infinite or NaN. Please, check your calculations."));
415  return false;
416  }
417 
418  label->setText(qApp->LocaleToString(result) + " " + postfix);
419  label->setToolTip(tr("Value"));
420  return true;
421  }
422  catch (qmu::QmuParserError &e)
423  {
424  label->setText(tr("Error") + " (" + postfix + "). " + tr("Parser error: %1").arg(e.GetMsg()));
425  label->setToolTip(tr("Parser error: %1").arg(e.GetMsg()));
426  return false;
427  }
428  }
429 }
430 
431 //---------------------------------------------------------------------------------------------------------------------
433 {
434  if (isSorted || isFiltered)
435  {
436  ui->toolButtonUp->setEnabled(false);
437  ui->toolButtonDown->setEnabled(false);
438  return;
439  }
440 
441  if (ui->variables_TableWidget->rowCount() > 0)
442  {
443  const QTableWidgetItem *name = ui->variables_TableWidget->item(ui->variables_TableWidget->currentRow(), 0);
444  SCASSERT(name != nullptr)
445 
446  ui->removeCustomVariable_ToolButton->setEnabled(not variableUsed(name->text()));
447  }
448  else
449  {
450  ui->removeCustomVariable_ToolButton->setEnabled(false);
451  }
452 
453  if (ui->variables_TableWidget->rowCount() >= 2)
454  {
455  if (ui->variables_TableWidget->currentRow() == 0)
456  {
457  ui->toolButtonUp->setEnabled(false);
458  ui->toolButtonDown->setEnabled(true);
459  }
460  else if (ui->variables_TableWidget->currentRow() == ui->variables_TableWidget->rowCount()-1)
461  {
462  ui->toolButtonUp->setEnabled(true);
463  ui->toolButtonDown->setEnabled(false);
464  }
465  else
466  {
467  ui->toolButtonUp->setEnabled(true);
468  ui->toolButtonDown->setEnabled(true);
469  }
470  }
471  else
472  {
473  ui->toolButtonUp->setEnabled(false);
474  ui->toolButtonDown->setEnabled(false);
475  }
476 }
477 
478 //---------------------------------------------------------------------------------------------------------------------
480 {
481  if (enabled)
482  {
483  setMoveControls();
484  }
485  else
486  {
487  ui->removeCustomVariable_ToolButton->setEnabled(enabled);
488 
489  ui->toolButtonUp->setEnabled(enabled);
490  ui->toolButtonDown->setEnabled(enabled);
491  }
492 
493  if (not enabled)
494  { // Clear
495  ui->name_LineEdit->blockSignals(true);
496  ui->name_LineEdit->clear();
497  ui->name_LineEdit->blockSignals(false);
498 
499  ui->description_PlainTextEdit->blockSignals(true);
500  ui->description_PlainTextEdit->clear();
501  ui->description_PlainTextEdit->blockSignals(false);
502 
503  ui->calculatedValue_Label->blockSignals(true);
504  ui->calculatedValue_Label->clear();
505  ui->calculatedValue_Label->blockSignals(false);
506 
507  ui->formula_PlainTextEdit->blockSignals(true);
508  ui->formula_PlainTextEdit->clear();
509  ui->formula_PlainTextEdit->blockSignals(false);
510  }
511 
512  ui->formula_ToolButton->setEnabled(enabled);
513  ui->name_LineEdit->setEnabled(enabled);
514  ui->description_PlainTextEdit->setEnabled(enabled);
515  ui->formula_PlainTextEdit->setEnabled(enabled);
516 }
517 
518 //---------------------------------------------------------------------------------------------------------------------
520 {
523 }
524 
525 //---------------------------------------------------------------------------------------------------------------------
526 bool DialogVariables::variableUsed(const QString &name) const
527 {
528  const QVector<VFormulaField> expressions = doc->ListExpressions();
529 
530  for(int i = 0; i < expressions.size(); ++i)
531  {
532  if (expressions.at(i).expression.indexOf(name) != -1)
533  {
534  // Eval formula
535  try
536  {
537  QScopedPointer<qmu::QmuTokenParser> cal(new qmu::QmuTokenParser(expressions.at(i).expression, false,
538  false));
539 
540  // Tokens (variables, measurements)
541  if (cal->GetTokens().values().contains(name))
542  {
543  return true;
544  }
545  }
546  catch (const qmu::QmuParserError &)
547  {
548  // Do nothing. Because we not sure if used. A formula is broken.
549  }
550  }
551  }
552  return false;
553 }
554 
555 //---------------------------------------------------------------------------------------------------------------------
556 void DialogVariables::renameCache(const QString &name, const QString &newName)
557 {
558  for (int i = 0; i < renameList.size(); ++i)
559  {
560  if (renameList.at(i).second == name)
561  {
562  renameList[i].second = newName;
563  return;
564  }
565  }
566 
567  renameList.append(qMakePair(name, newName));
568 }
569 
570 //---------------------------------------------------------------------------------------------------------------------
571 /**
572  * @brief FullUpdateFromFile update information in tables form file
573  */
575 {
576  hasChanges = false;
577 
578  ui->lineLengths_TableWidget->clearContents();
579  ui->curveLengths_TableWidget->clearContents();
580  ui->curveAngles_TableWidget->clearContents();
581  ui->lineAngles_TableWidget->clearContents();
582  ui->arcRadiuses_TableWidget->clearContents();
583 
585  fillLineLengths();
586  fillLineAngles();
590  fillCurveAngles();
591 }
592 
593 //---------------------------------------------------------------------------------------------------------------------
595 {
596  if (hasChanges)
597  {
598  QVector<VFormulaField> expressions = doc->ListExpressions();
599  for (int i = 0; i < renameList.size(); ++i)
600  {
601  doc->replaceNameInFormula(expressions, renameList.at(i).first, renameList.at(i).second);
602  }
603  renameList.clear();
604 
605  const int row = ui->variables_TableWidget->currentRow();
606 
608 
609  ui->variables_TableWidget->blockSignals(true);
610  ui->variables_TableWidget->selectRow(row);
611  ui->variables_TableWidget->blockSignals(false);
612 
613  hasChanges = false;
614  }
615 }
616 
617 //---------------------------------------------------------------------------------------------------------------------
618 /**
619  * @brief clickedToolButtonAdd create new row in table
620  */
622 {
623  qCDebug(vDialog, "Add a new custom variable");
624 
625  const QString name = getCustomVariableName();
626  qint32 currentRow = -1;
627 
628  if (ui->variables_TableWidget->currentRow() == -1)
629  {
630  currentRow = ui->variables_TableWidget->rowCount();
632  }
633  else
634  {
635  currentRow = ui->variables_TableWidget->currentRow()+1;
636  const QTableWidgetItem *item = ui->variables_TableWidget->item(ui->variables_TableWidget->currentRow(), 0);
637  doc->addEmptyCustomVariableAfter(item->text(), name);
638  }
639 
640  hasChanges = true;
641  localUpdateTree();
642 
643  ui->variables_TableWidget->selectRow(currentRow);
644 }
645 
646 //---------------------------------------------------------------------------------------------------------------------
647 /**
648  * @brief clickedToolButtonRemove remove one row from table
649  */
651 {
652  const int row = ui->variables_TableWidget->currentRow();
653 
654  if (row == -1)
655  {
656  return;
657  }
658 
659  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
660  doc->removeCustomVariable(name->text());
661 
662  hasChanges = true;
663  localUpdateTree();
664 
665  if (ui->variables_TableWidget->rowCount() > 0)
666  {
667  ui->variables_TableWidget->selectRow(0);
668  }
669  else
670  {
671  enablePieces(false);
672  }
673 }
674 
675 //---------------------------------------------------------------------------------------------------------------------
677 {
678  const int row = ui->variables_TableWidget->currentRow();
679 
680  if (row == -1)
681  {
682  return;
683  }
684 
685  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
686  doc->MoveUpIncrement(name->text());
687 
688  hasChanges = true;
689  localUpdateTree();
690 
691  ui->variables_TableWidget->selectRow(row-1);
692 }
693 
694 //---------------------------------------------------------------------------------------------------------------------
696 {
697  const int row = ui->variables_TableWidget->currentRow();
698 
699  if (row == -1)
700  {
701  return;
702  }
703 
704  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
705  doc->MoveDownIncrement(name->text());
706 
707  hasChanges = true;
708  localUpdateTree();
709 
710  ui->variables_TableWidget->selectRow(row+1);
711 }
712 
713 //---------------------------------------------------------------------------------------------------------------------
715 {
716  const int row = ui->variables_TableWidget->currentRow();
717 
718  if (row == -1)
719  {
720  return;
721  }
722 
723  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
724 
725  QString newName = text.isEmpty() ? getCustomVariableName() : CustomIncrSign + text;
726 
727  if (not data->IsUnique(newName))
728  {
729  qint32 num = 2;
730  QString tempName = newName;
731  do
732  {
733  tempName = tempName + QLatin1String("_") + QString().number(num);
734  num++;
735  } while (not data->IsUnique(tempName));
736  newName = tempName;
737  }
738 
739  doc->setIncrementName(name->text(), newName);
741  doc->replaceNameInFormula(expressions, name->text(), newName);
742  renameCache(name->text(), newName);
743 
744  hasChanges = true;
745  localUpdateTree();
746 
747  ui->variables_TableWidget->blockSignals(true);
748  ui->variables_TableWidget->selectRow(row);
749  ui->variables_TableWidget->blockSignals(false);
750 }
751 
752 //---------------------------------------------------------------------------------------------------------------------
754 {
755  const int row = ui->variables_TableWidget->currentRow();
756 
757  if (row == -1)
758  {
759  return;
760  }
761 
762  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
763  doc->setIncrementDescription(name->text(), ui->description_PlainTextEdit->toPlainText());
764 
765  localUpdateTree();
766 
767  const QTextCursor cursor = ui->description_PlainTextEdit->textCursor();
768  ui->variables_TableWidget->blockSignals(true);
769  ui->variables_TableWidget->selectRow(row);
770  ui->variables_TableWidget->blockSignals(false);
771  ui->description_PlainTextEdit->setTextCursor(cursor);
772 }
773 
774 //---------------------------------------------------------------------------------------------------------------------
776 {
777  const int row = ui->variables_TableWidget->currentRow();
778 
779  if (row == -1)
780  {
781  return;
782  }
783 
784  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
785 
786  // Replace line return character with spaces for calc if exist
787  QString text = ui->formula_PlainTextEdit->toPlainText();
788  text.replace("\n", " ");
789 
790  QTableWidgetItem *formula = ui->variables_TableWidget->item(row, 2);
791  if (formula->text() == text)
792  {
793  QTableWidgetItem *result = ui->variables_TableWidget->item(row, 1);
794  //Show unit in dialog label (cm, mm or inch)
795  const QString postfix = UnitsToStr(qApp->patternUnit());
796  ui->calculatedValue_Label->setText(result->text() + " " +postfix);
797  return;
798  }
799 
800  if (text.isEmpty())
801  {
802  //Show unit in dialog label (cm, mm or inch)
803  const QString postfix = UnitsToStr(qApp->patternUnit());
804  ui->calculatedValue_Label->setText(tr("Error") + " (" + postfix + "). " + tr("Empty field."));
805  return;
806  }
807 
808  QSharedPointer<VIncrement> variable = data->GetVariable<VIncrement>(name->text());
809  if (not evalVariableFormula(text, true, variable->GetData(), ui->calculatedValue_Label))
810  {
811  return;
812  }
813 
814  try
815  {
816  const QString formula = qApp->TrVars()->FormulaFromUser(text, qApp->Settings()->GetOsSeparator());
817  doc->SetIncrementFormula(name->text(), formula);
818  }
819  catch (qmu::QmuParserError &e) // Just in case something bad will happen
820  {
821  Q_UNUSED(e)
822  return;
823  }
824 
825  hasChanges = true;
826  localUpdateTree();
827 
828  const QTextCursor cursor = ui->formula_PlainTextEdit->textCursor();
829  ui->variables_TableWidget->blockSignals(true);
830  ui->variables_TableWidget->selectRow(row);
831  ui->variables_TableWidget->blockSignals(false);
832  ui->formula_PlainTextEdit->setTextCursor(cursor);
833 }
834 
835 //---------------------------------------------------------------------------------------------------------------------
837 {
838  const int row = ui->variables_TableWidget->currentRow();
839 
840  if (row == -1)
841  {
842  return;
843  }
844 
845  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
846  QSharedPointer<VIncrement> variable = data->GetVariable<VIncrement>(name->text());
847 
848  EditFormulaDialog *dialog = new EditFormulaDialog(variable->GetData(), NULL_ID, this);
849  dialog->setWindowTitle(tr("Edit variable"));
850  dialog->SetFormula(qApp->TrVars()->TryFormulaFromUser(ui->formula_PlainTextEdit->toPlainText().replace("\n", " "),
851  qApp->Settings()->GetOsSeparator()));
852  const QString postfix = UnitsToStr(qApp->patternUnit(), true);
853  dialog->setPostfix(postfix);//Show unit in dialog label (cm, mm or inch)
854 
855  if (dialog->exec() == QDialog::Accepted)
856  {
857  // Because of the bug need to take QTableWidgetItem twice time. Previous update "killed" the pointer.
858  const QTableWidgetItem *name = ui->variables_TableWidget->item(row, 0);
859  doc->SetIncrementFormula(name->text(), dialog->GetFormula());
860 
861  hasChanges = true;
862  localUpdateTree();
863 
864  ui->variables_TableWidget->selectRow(row);
865  }
866  delete dialog;
867 }
868 
869 //---------------------------------------------------------------------------------------------------------------------
870 void DialogVariables::closeEvent(QCloseEvent *event)
871 {
872  refreshPattern();
873 
874  ui->formula_PlainTextEdit->blockSignals(true);
875  ui->name_LineEdit->blockSignals(true);
876  ui->description_PlainTextEdit->blockSignals(true);
877 
878  emit updateProperties();
879  emit DialogClosed(QDialog::Accepted);
880  event->accept();
881 }
882 
883 //---------------------------------------------------------------------------------------------------------------------
884 void DialogVariables::changeEvent(QEvent *event)
885 {
886  if (event->type() == QEvent::LanguageChange)
887  {
888  // retranslate designer form (single inheritance approach)
889  ui->retranslateUi(this);
891  }
892  // remember to call base class implementation
893  QWidget::changeEvent(event);
894 }
895 
896 //---------------------------------------------------------------------------------------------------------------------
897 bool DialogVariables::eventFilter(QObject *object, QEvent *event)
898 {
899  if (QLineEdit *textEdit = qobject_cast<QLineEdit *>(object))
900  {
901  if (event->type() == QEvent::KeyPress)
902  {
903  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
904  if ((keyEvent->key() == Qt::Key_Period) && (keyEvent->modifiers() & Qt::KeypadModifier))
905  {
906  if (qApp->Settings()->GetOsSeparator())
907  {
908  textEdit->insert(QLocale().decimalPoint());
909  }
910  else
911  {
912  textEdit->insert(QLocale::c().decimalPoint());
913  }
914  return true;
915  }
916  }
917  }
918  else
919  {
920  // pass the event on to the parent class
921  return DialogTool::eventFilter(object, event);
922  }
923  return false;// pass the event to the widget
924 }
925 
926 //---------------------------------------------------------------------------------------------------------------------
927 void DialogVariables::showEvent(QShowEvent *event)
928 {
929  // Skip DialogTool implementation
930  QDialog::showEvent(event);
931  if ( event->spontaneous() )
932  {
933  return;
934  }
935 
936  if (isInitialized)
937  {
938  return;
939  }
940  // do your init stuff here
941 
942  const QSize sz = qApp->Settings()->GetIncrementsDialogSize();
943  if (not sz.isEmpty())
944  {
945  resize(sz);
946  }
947 
948  isInitialized = true;//first show windows are held
949 }
950 
951 //---------------------------------------------------------------------------------------------------------------------
952 void DialogVariables::resizeEvent(QResizeEvent *event)
953 {
954  // remember the size for the next time this dialog is opened, but only
955  // if widget was already initialized, which rules out the resize at
956  // dialog creating, which would
957  if (isInitialized)
958  {
959  qApp->Settings()->SetIncrementsDialogSize(size());
960  }
961  DialogTool::resizeEvent(event);
962 }
963 
964 //---------------------------------------------------------------------------------------------------------------------
966 {
967  if (ui->variables_TableWidget->rowCount() > 0)
968  {
969  enablePieces(true);
970 
971  // name
972  const QTableWidgetItem *name = ui->variables_TableWidget->item(ui->variables_TableWidget->currentRow(), 0);
974 
975  try
976  {
977  variable = data->GetVariable<VIncrement>(name->text());
978  }
979  catch(const VExceptionBadId &e)
980  {
981  Q_UNUSED(e)
982  enablePieces(false);
983  return;
984  }
985 
986  ui->name_LineEdit->blockSignals(true);
987  ui->name_LineEdit->setText(clearCustomVariableName(variable->GetName()));
988  ui->name_LineEdit->blockSignals(false);
989 
990  ui->description_PlainTextEdit->blockSignals(true);
991  ui->description_PlainTextEdit->setPlainText(variable->GetDescription());
992  ui->description_PlainTextEdit->blockSignals(false);
993 
994  evalVariableFormula(variable->GetFormula(), false, variable->GetData(), ui->calculatedValue_Label);
995  ui->formula_PlainTextEdit->blockSignals(true);
996 
997  QString formula;
998  try
999  {
1000  formula = qApp->TrVars()->FormulaToUser(variable->GetFormula(), qApp->Settings()->GetOsSeparator());
1001  }
1002  catch (qmu::QmuParserError &e)
1003  {
1004  Q_UNUSED(e)
1005  formula = variable->GetFormula();
1006  }
1007 
1008  ui->formula_PlainTextEdit->setPlainText(formula);
1009  ui->formula_PlainTextEdit->blockSignals(false);
1010  }
1011  else
1012  {
1013  enablePieces(false);
1014  }
1015 }
1016 
1017 //---------------------------------------------------------------------------------------------------------------------
1018 void DialogVariables::filterVariables(const QString &filterString)
1019 {
1020  QSharedPointer<QTableWidget> currentTable = tableList.value(ui->tabWidget->currentIndex());
1021  currentTable->blockSignals(true);
1022 
1023  if (filterString.isEmpty())
1024  {
1025  isFiltered = false;
1026  for (auto i = 0; i < currentTable->rowCount(); ++i)
1027  {
1028  currentTable->showRow(i);
1029  }
1030  ui->variables_TableWidget->horizontalHeader()->setSortIndicator(-1, Qt::AscendingOrder);
1031  }
1032  else
1033  {
1034  isFiltered = true;
1035  ui->toolButtonUp->setEnabled(false);
1036  ui->toolButtonDown->setEnabled(false);
1037  for (auto i = 0; i < currentTable->rowCount(); i++)
1038  {
1039  currentTable->hideRow(i);
1040  }
1041 
1042  for (auto item : currentTable->findItems(filterString, Qt::MatchContains))
1043  {
1044  if (item)
1045  {
1046  currentTable->showRow(item->row());
1047  }
1048  }
1049  }
1050 
1051  currentTable->blockSignals(false);
1052 }
The Calculator class for calculation formula.
Definition: calculator.h:84
The DialogTool class parent for all dialog of tools.
Definition: dialogtool.h:107
void DialogClosed(int result)
DialogClosed signal dialog closed.
bool isInitialized
isInitialized true if window is initialized
Definition: dialogtool.h:180
virtual bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE
Definition: dialogtool.cpp:441
The DialogVariables class show dialog increments. Tables of all variables in program will be here.
void saveCustomVariableName(const QString &text)
QList< QSharedPointer< QTableWidget > > tableList
void addCustomVariable()
clickedToolButtonAdd create new row in table
QString clearCustomVariableName(const QString &name) const
void fillControlPointLengths()
QString getCustomVariableName() const
void fillCustomVariables(bool freshCall=false)
fillCustomVariables fill data for variables table
virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE
closeEvent handle when dialog cloded
VPattern * doc
doc dom document container
void saveCustomVariableDescription()
void enablePieces(bool enabled)
virtual void changeEvent(QEvent *event) Q_DECL_OVERRIDE
void saveCustomVariableFormula()
void fillTable(const QMap< QString, T > &varTable, QTableWidget *table)
void showHeaderUnits(QTableWidget *table, int column, const QString &unit)
DialogVariables(VContainer *data, VPattern *doc, QWidget *parent=nullptr)
DialogVariables create dialog.
virtual ~DialogVariables() Q_DECL_OVERRIDE
QVector< QPair< QString, QString > > renameList
void removeCustomVariable()
clickedToolButtonRemove remove one row from table
void fillLineLengths()
FillLengthLines fill data for table of lines lengths.
Ui::DialogVariables * ui
ui keeps information about user interface
void renameCache(const QString &name, const QString &newName)
void FullUpdateFromFile()
FullUpdateFromFile update information in tables form file.
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE
VContainer * data
data container with data
void fillCurveLengths()
FillLengthSplines fill data for table of splines lengths.
bool variableUsed(const QString &name) const
void showCustomVariableDetails()
virtual bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE
void addCell(QTableWidget *table, const QString &text, int row, int column, int aligment, bool ok=true)
void filterVariables(const QString &filterString)
bool evalVariableFormula(const QString &formula, bool fromUser, VContainer *data, QLabel *label)
void updateProperties()
virtual void showEvent(QShowEvent *event) Q_DECL_OVERRIDE
showEvent handle when window show
The EditFormulaDialog class dialog for editing wrong formula.
void FullUpdateFromFile()
FullUpdateFromFile update tool data form file.
QVector< VFormulaField > ListExpressions() const
QVector< VFormulaField > ListIncrementExpressions() const
The VContainer class container of all variables.
Definition: vcontainer.h:141
const QMap< QString, QSharedPointer< VArcRadius > > arcRadiusesData() const
Definition: vcontainer.cpp:573
const QMap< QString, QSharedPointer< VLineAngle > > lineAnglesData() const
Definition: vcontainer.cpp:567
const QMap< QString, QSharedPointer< VCurveAngle > > curveAnglesData() const
Definition: vcontainer.cpp:579
const QMap< QString, QSharedPointer< VCurveCLength > > controlPointLengthsData() const
Definition: vcontainer.cpp:561
static bool IsUnique(const QString &name)
Definition: vcontainer.cpp:585
const QMap< QString, QSharedPointer< VCurveLength > > curveLengthsData() const
Definition: vcontainer.cpp:555
const QMap< QString, QSharedPointer< VLengthLine > > lineLengthsData() const
Definition: vcontainer.cpp:549
const QHash< QString, QSharedPointer< VInternalVariable > > * DataVariables() const
Definition: vcontainer.cpp:718
const QMap< QString, QSharedPointer< VIncrement > > variablesData() const
Definition: vcontainer.cpp:543
QSharedPointer< T > GetVariable(QString name) const
GetVariable return varible by name.
Definition: vcontainer.h:303
The VExceptionBadId class for exception bad id.
The VIncrement class keep data row of increment table.
Definition: vincrement.h:70
The VPattern class working with pattern file.
Definition: vpattern.h:68
void MoveDownIncrement(const QString &name)
Definition: vpattern.cpp:3518
void replaceNameInFormula(QVector< VFormulaField > &expressions, const QString &name, const QString &newName)
Definition: vpattern.cpp:3567
void setIncrementDescription(const QString &name, const QString &text)
Definition: vpattern.cpp:3556
void LiteParseIncrements()
Definition: vpattern.cpp:441
void addEmptyCustomVariable(const QString &name)
Definition: vpattern.cpp:3465
void SetIncrementFormula(const QString &name, const QString &text)
Definition: vpattern.cpp:3545
void MoveUpIncrement(const QString &name)
Definition: vpattern.cpp:3502
void setIncrementName(const QString &name, const QString &text)
Definition: vpattern.cpp:3534
void removeCustomVariable(const QString &name)
Definition: vpattern.cpp:3494
virtual void LiteParseTree(const Document &parse) Q_DECL_OVERRIDE
LiteParseTree lite parse file.
Definition: vpattern.cpp:515
void addEmptyCustomVariableAfter(const QString &after, const QString &name)
Definition: vpattern.cpp:3475
Error class of the parser.
const QString & GetMsg() const
Returns the message string for this error.
const QString degreeSymbol
Definition: def.cpp:196
QString UnitsToStr(const Unit &unit, const bool translate)
UnitsToStr translate unit to string.
Definition: def.cpp:702
#define SCASSERT(cond)
Definition: def.h:317
const QString CustomIncrSign
Definition: ifcdef.cpp:71
const QString variable_
Definition: ifcdef.cpp:413
#define NULL_ID
Definition: ifcdef.h:76
QString NameRegExp()
Definition: qmudef.cpp:281
#define qApp
Definition: vapplication.h:67