Seamly2D
Code documentation
history_dialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  ** @file historyDialog.cpp
3  ** @author Douglas S Caskey
4  ** @date Mar 11, 2023
5  **
6  ** @copyright
7  ** Copyright (C) 2015 - 2023 Seamly, LLC
8  ** https://github.com/fashionfreedom/seamly2d
9  **
10  ** @brief
11  ** Seamly2D is free software: you can redistribute it and/or modify
12  ** it under the terms of the GNU General Public License as published by
13  ** the Free Software Foundation, either version 3 of the License, or
14  ** (at your option) any later version.
15  **
16  ** Seamly2D is distributed in the hope that it will be useful,
17  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  ** GNU General Public License for more details.
20  **
21  ** You should have received a copy of the GNU General Public License
22  ** along with Seamly2D. If not, see <http://www.gnu.org/licenses/>.
23  **************************************************************************/
24 
25  /************************************************************************
26  **
27  ** @file dialoghistory.cpp
28  ** @author Roman Telezhynskyi <dismine(at)gmail.com>
29  ** @date November 15, 2013
30  **
31  ** @brief
32  ** @copyright
33  ** This source code is part of the Valentina project, a pattern making
34  ** program, whose allow create and modeling patterns of clothing.
35  ** Copyright (C) 2013-2015 Valentina project
36  ** <https://bitbucket.org/dismine/valentina> All Rights Reserved.
37  **
38  ** Valentina is free software: you can redistribute it and/or modify
39  ** it under the terms of the GNU General Public License as published by
40  ** the Free Software Foundation, either version 3 of the License, or
41  ** (at your option) any later version.
42  **
43  ** Valentina is distributed in the hope that it will be useful,
44  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
45  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46  ** GNU General Public License for more details.
47  **
48  ** You should have received a copy of the GNU General Public License
49  ** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
50  **
51  *************************************************************************/
52 
53 #include "history_dialog.h"
54 #include "ui_history_dialog.h"
55 
56 #include "../vgeometry/varc.h"
57 #include "../vgeometry/vellipticalarc.h"
58 #include "../vgeometry/vcubicbezier.h"
59 #include "../vgeometry/vsplinepath.h"
60 #include "../vgeometry/vcubicbezierpath.h"
61 #include "../vgeometry/vpointf.h"
62 #include "../vmisc/diagnostic.h"
63 #include "../vmisc/vabstractapplication.h"
64 #include "../vtools/tools/vabstracttool.h"
65 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.h"
66 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.h"
67 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutarc.h"
68 #include "../xml/vpattern.h"
69 
70 #include <QApplication>
71 #include <QClipboard>
72 #include <QCloseEvent>
73 #include <QDebug>
74 
75 //---------------------------------------------------------------------------------------------------------------------
76 /**
77  * @brief HistoryDialog create dialog
78  * @param data container with data
79  * @param doc dom document container
80  * @param parent parent widget
81  */
82 HistoryDialog::HistoryDialog(VContainer *data, VPattern *doc, QWidget *parent)
83  : DialogTool(data, 0, parent)
84  , ui(new Ui::HistoryDialog)
85  , m_doc(doc)
86  , m_cursorRow(0)
87  , m_cursorToolRecordRow(0)
88 {
89  ui->setupUi(this);
90  setWindowFlags(Qt::Window);
91  setWindowFlags((windowFlags() | Qt::WindowStaysOnTopHint | Qt::WindowMaximizeButtonHint) & ~Qt::WindowContextHelpButtonHint);
92 
93  ui->find_LineEdit->installEventFilter(this);
94 
95  qApp->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
96 
97  fillTable();
99 
100  ok_Button = ui->buttonBox->button(QDialogButtonBox::Ok);
101  connect(ok_Button, &QPushButton::clicked, this, &HistoryDialog::DialogAccepted);
102  connect(ui->clipboard_ToolButton, &QToolButton::clicked, this, &HistoryDialog::copyToClipboard);
103  connect(ui->tableWidget, &QTableWidget::cellClicked, this, &HistoryDialog::cellClicked);
106  connect(ui->find_LineEdit, &QLineEdit::textEdited, this, &HistoryDialog::findText);
107  connect(this, &HistoryDialog::showHistoryTool, m_doc, [doc](quint32 id, bool enable)
108  {
109  emit doc->ShowTool(id, enable);
110  });
111 
112  showTool();
113 }
114 
115 //---------------------------------------------------------------------------------------------------------------------
117 {
118  delete ui;
119 }
120 
121 //---------------------------------------------------------------------------------------------------------------------
122 /**
123  * @brief DialogAccepted save data and emit signal about closed dialog.
124  */
126 {
127  QTableWidgetItem *item = ui->tableWidget->item(m_cursorToolRecordRow, 0);
128  quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
129  emit showHistoryTool(id, false);
130  emit DialogClosed(QDialog::Accepted);
131 }
132 
133 //---------------------------------------------------------------------------------------------------------------------
134 /**
135  * @brief cellClicked changed history record
136  * @param row number row in table
137  * @param column number column in table
138  */
139 void HistoryDialog::cellClicked(int row, int column)
140 {
141  if (column == 0)
142  {
143  QTableWidgetItem *item = ui->tableWidget->item(m_cursorRow, 0);
144  item->setIcon(QIcon());
145 
146  item = ui->tableWidget->item(row, 0);
147  m_cursorRow = row;
148  item->setIcon(QIcon("://icon/24x24/left_to_right_arrow.png"));
149  const quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
150  m_doc->blockSignals(true);
151  row == ui->tableWidget->rowCount()-1 ? m_doc->setCursor(0) : m_doc->setCursor(id);
152  m_doc->blockSignals(false);
153  }
154  else
155  {
156  QTableWidgetItem *item = ui->tableWidget->item(m_cursorToolRecordRow, 0);
157  quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
158  emit showHistoryTool(id, false);
159 
160  m_cursorToolRecordRow = row;
161  item = ui->tableWidget->item(m_cursorToolRecordRow, 0);
162  id = qvariant_cast<quint32>(item->data(Qt::UserRole));
163  emit showHistoryTool(id, true);
164  }
165 }
166 
167 //---------------------------------------------------------------------------------------------------------------------
168 /**
169  * @brief changedCursor changed cursor of input. Cursor show after which record we will insert new object
170  * @param id id of object
171  */
173 {
174  for (qint32 i = 0; i< ui->tableWidget->rowCount(); ++i)
175  {
176  QTableWidgetItem *item = ui->tableWidget->item(i, 0);
177  quint32 rId = qvariant_cast<quint32>(item->data(Qt::UserRole));
178  if (rId == id)
179  {
180  QTableWidgetItem *oldCursorItem = ui->tableWidget->item(m_cursorRow, 0);
181  oldCursorItem->setIcon(QIcon());
182  m_cursorRow = i;
183  item->setIcon(QIcon("://icon/24x24/left_to_right_arrow.png"));
184  }
185  }
186 }
187 
188 //---------------------------------------------------------------------------------------------------------------------
189 /**
190  * @brief updateHistory update history table
191  */
193 {
194  fillTable();
195  initializeTable();
196 }
197 
198 //---------------------------------------------------------------------------------------------------------------------
199 /**
200  * @brief fillTable fill table
201  */
203 {
204  ui->tableWidget->clear();
206  qint32 currentRow = -1;
207  qint32 count = 0;
208  ui->tableWidget->setRowCount(history.size());//Set Row count to number of Tool history records
209 
210  for (qint32 i = 0; i< history.size(); ++i)
211  {
212  const VToolRecord tool = history.at(i);
213  const RowData rowData = record(tool);
214  if (!rowData.tool.isEmpty())
215  {
216  currentRow++;
217 
218  {
219  QTableWidgetItem *item = new QTableWidgetItem(QString().setNum(rowData.id));
220  item->setTextAlignment(Qt::AlignRight);
221  item->setSizeHint(QSize(80, 24));
222  item->setData(Qt::UserRole, rowData.id);
223  item->setFlags(item->flags() ^ Qt::ItemIsEditable);
224  ui->tableWidget->setItem(currentRow, 0, item);//2nd column is Tool id
225  }
226 
227  {
228  QTableWidgetItem *item = new QTableWidgetItem(QString(rowData.name));
229  item->setTextAlignment(Qt::AlignHCenter);
230  item->setSizeHint(QSize(100, 24));
231  item->setFlags(item->flags() ^ Qt::ItemIsEditable);
232  ui->tableWidget->setItem(currentRow, 1, item);//3rd column is Tool name
233  }
234 
235  QTableWidgetItem *item = new QTableWidgetItem(rowData.tool);
236  item->setTextAlignment(Qt::AlignLeft);
237  item->setFlags(item->flags() ^ Qt::ItemIsEditable);
238  item->setIcon(QIcon(rowData.icon));
239  ui->tableWidget->setItem(currentRow, 2, item);//4th column is Tool description
240  ++count;
241  }
242  }
243  ui->tableWidget->setRowCount(count);//Current history records count
244  if (count>0)
245  {
247  QTableWidgetItem *item = ui->tableWidget->item(m_cursorRow, 0);
248  SCASSERT(item != nullptr)
249  item->setIcon(QIcon("://icon/24x24/left_to_right_arrow.png"));//place arrow in 1st column of most recent history record
250  }
251 
252  ui->tableWidget->resizeColumnsToContents();
253  ui->tableWidget->resizeRowsToContents();
254  ui->tableWidget->verticalHeader()->setDefaultSectionSize(24);//Set all row heights to 20px
255 }
256 
257 //---------------------------------------------------------------------------------------------------------------------
258 QT_WARNING_PUSH
259 QT_WARNING_DISABLE_GCC("-Wswitch-default")
260 /**
261  * @brief Record return description for record
262  * @param tool record data
263  * @return RowData
264  */
265 RowData HistoryDialog::record(const VToolRecord &tool)
266 {
267  // This check helps to find missed tools in the switch
268  Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 53, "Not all tools were used in history.");
269 
270  RowData rowData;
271  const quint32 &toolId = tool.getId();
272  rowData.id = toolId;
273  const QDomElement domElement = m_doc->elementById(toolId);
274  if (domElement.isElement() == false)
275  {
276  qDebug()<<"Can't find element by id"<<Q_FUNC_INFO;
277  return rowData;
278  }
279  try
280  {
281  switch (tool.getTypeTool())
282  {
283  case Tool::Arrow:
284  case Tool::SinglePoint:
285  case Tool::DoublePoint:
286  case Tool::LinePoint:
288  case Tool::Cut:
289  case Tool::Midpoint:// Same as Tool::AlongLine, but tool will never has such type
290  case Tool::ArcIntersectAxis:// Same as Tool::CurveIntersectAxis, but tool will never has such type
292  Q_UNREACHABLE(); //-V501
293  break;
294 
295  case Tool::BasePoint:
296  rowData.icon = ":/toolicon/32x32/point_basepoint_icon.png";
297  rowData.name = tr("%1").arg(getPointName(toolId));
298  rowData.tool = tr("Base Point");
299  break;
300 
301  case Tool::EndLine:
302  rowData.icon = ":/toolicon/32x32/segment.png";
303  rowData.name = tr("%1").arg(getPointName(toolId));
304  rowData.tool = tr("Point Length and Angle from point %1")
305  .arg(getPointName(attrUInt(domElement, AttrBasePoint)));
306  break;
307 
308  case Tool::Line:
309  rowData.icon = ":/toolicon/32x32/line.png";
310  rowData.name = tr("Line_%1_%2")
311  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
312  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
313  rowData.tool = tr("Line from %1 to %2")
314  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
315  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
316  break;
317 
318  case Tool::AlongLine:
319  rowData.icon = ":/toolicon/32x32/along_line.png";
320  rowData.name = tr("%1").arg(getPointName(toolId));
321  rowData.tool = tr("Point On Line %1_%2")
322  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
323  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
324  break;
325 
326  case Tool::ShoulderPoint:
327  rowData.icon = ":/toolicon/32x32/shoulder.png";
328  rowData.name = tr("%1").arg(getPointName(toolId));
329  rowData.tool = tr("Point Length to Line");
330  break;
331 
332  case Tool::Normal:
333  rowData.icon = ":/toolicon/32x32/normal.png";
334  rowData.name = tr("%1").arg(getPointName(toolId));
335  rowData.tool = tr("Point On Perpendicular %1_%2")
336  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
337  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
338  break;
339 
340  case Tool::Bisector:
341  rowData.icon = ":/toolicon/32x32/bisector.png";
342  rowData.name = tr("%1").arg(getPointName(toolId));
343  rowData.tool = tr("Point On Bisector %1_%2_%3")
344  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
345  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)))
346  .arg(getPointName(attrUInt(domElement, AttrThirdPoint)));
347  break;
348 
349  case Tool::LineIntersect:
350  rowData.icon = ":/toolicon/32x32/intersect.png";
351  rowData.name = tr("%1").arg(getPointName(toolId));
352  rowData.tool = tr("Point Intersect Lines %1_%2 and %3_%4")
353  .arg(getPointName(attrUInt(domElement, AttrP1Line1)))
354  .arg(getPointName(attrUInt(domElement, AttrP2Line1)))
355  .arg(getPointName(attrUInt(domElement, AttrP1Line2)))
356  .arg(getPointName(attrUInt(domElement, AttrP2Line2)));
357  break;
358 
359  case Tool::Spline:
360  {
361  const QSharedPointer<VSpline> spl = data->GeometricObject<VSpline>(toolId);
362  SCASSERT(!spl.isNull())
363  rowData.icon = ":/toolicon/32x32/spline.png";
364  rowData.name = tr("%1").arg(spl->NameForHistory(tr("Spl_")));
365  rowData.tool = tr("Curve Interactive");
366  break;
367  }
368 
369  case Tool::CubicBezier:
370  {
371  const QSharedPointer<VCubicBezier> spl = data->GeometricObject<VCubicBezier>(toolId);
372  SCASSERT(!spl.isNull())
373  rowData.icon = ":/toolicon/32x32/cubic_bezier.png";
374  rowData.name = tr("%1").arg(spl->NameForHistory(tr("Spl_")));
375  rowData.tool = tr("Curve Fixed");
376  break;
377  }
378 
379  case Tool::Arc:
380  {
381  const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(toolId);
382  SCASSERT(!arc.isNull())
383  rowData.icon = ":/toolicon/32x32/arc.png";
384  rowData.name = tr("%1").arg(arc->NameForHistory(tr("Arc_")));
385  rowData.tool = tr("Arc Radius & Angles");
386  break;
387  }
388 
389  case Tool::ArcWithLength:
390  {
391  const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(toolId);
392  SCASSERT(!arc.isNull())
393  rowData.icon = ":/toolicon/32x32/arc_with_length.png";
394  rowData.name =tr("%1").arg(arc->NameForHistory(tr("Arc_")));
395  rowData.tool =tr("Arc Radius & Length %1") .arg(arc->NameForHistory(tr("Arc_")));
396  break;
397  }
398 
399  case Tool::SplinePath:
400  {
401  const QSharedPointer<VSplinePath> splPath = data->GeometricObject<VSplinePath>(toolId);
402  SCASSERT(!splPath.isNull())
403  rowData.icon = ":/toolicon/32x32/splinePath.png";
404  rowData.name = tr("%1").arg(splPath->NameForHistory(tr("SplPath_")));
405  rowData.tool = tr("Spline Interactive");
406  break;
407  }
408 
410  {
411  const QSharedPointer<VCubicBezierPath> splPath = data->GeometricObject<VCubicBezierPath>(toolId);
412  SCASSERT(!splPath.isNull())
413  rowData.icon = ":/toolicon/32x32/cubic_bezier_path.png";
414  rowData.name = tr("%1").arg(splPath->NameForHistory(tr("SplPath_")));
415  rowData.tool = tr("Spline Fixed");
416  break;
417  }
418 
420  rowData.icon = ":/toolicon/32x32/point_of_contact.png";
421  rowData.name = tr("%1").arg(getPointName(toolId));
422  rowData.tool = tr("Point Intersect Arc with center %1 & Line %2_%3")
423  .arg(getPointName(attrUInt(domElement, AttrCenter)))
424  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
425  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
426  break;
427 
428  case Tool::Height:
429  rowData.icon = ":/toolicon/32x32/height.png";
430  rowData.name = tr("%1").arg(getPointName(toolId));
431  rowData.tool = tr("Point Intersect Line %1_%2 & Perpendicular %3")
432  .arg(getPointName(attrUInt(domElement, AttrP1Line)))
433  .arg(getPointName(attrUInt(domElement, AttrP2Line)))
434  .arg(getPointName(attrUInt(domElement, AttrBasePoint)));
435  break;
436 
437  case Tool::Triangle:
438  rowData.icon = ":/toolicon/32x32/triangle.png";
439  rowData.name = tr("%1").arg(getPointName(toolId));
440  rowData.tool = tr("Point Intersect Axis %1_%2 & Triangle points %3 and %4")
441  .arg(getPointName(attrUInt(domElement, AttrAxisP1)))
442  .arg(getPointName(attrUInt(domElement, AttrAxisP2)))
443  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
444  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
445  break;
446 
448  rowData.icon = ":/toolicon/32x32/point_intersectxy_icon.png";
449  rowData.name = tr("%1").arg(getPointName(toolId));
450  rowData.tool = tr("Point Intersect XY of points %1 and %2")
451  .arg(getPointName(attrUInt(domElement, AttrFirstPoint)))
452  .arg(getPointName(attrUInt(domElement, AttrSecondPoint)));
453  break;
454 
455  case Tool::CutArc:
456  {
457  const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(attrUInt(domElement, AttrArc));
458  SCASSERT(!arc.isNull())
459  rowData.icon = ":/toolicon/32x32/arc_cut.png";
460  rowData.name = tr("%1").arg(getPointName(toolId));
461  rowData.tool = tr("Point On Arc");
462  break;
463  }
464 
465  case Tool::CutSpline:
466  {
467  const quint32 splineId = attrUInt(domElement, VToolCutSpline::AttrSpline);
468  const QSharedPointer<VAbstractCubicBezier> spl = data->GeometricObject<VAbstractCubicBezier>(splineId);
469  SCASSERT(!spl.isNull())
470  rowData.icon = ":/toolicon/32x32/spline_cut_point.png";
471  rowData.name = tr("%1").arg(getPointName(toolId));
472  rowData.tool = tr("Point On Curve");
473  break;
474  }
475 
476  case Tool::CutSplinePath:
477  {
478  const quint32 splinePathId = attrUInt(domElement, VToolCutSplinePath::AttrSplinePath);
480  data->GeometricObject<VAbstractCubicBezierPath>(splinePathId);
481  SCASSERT(!splPath.isNull())
482  rowData.icon = ":/toolicon/32x32/splinePath_cut_point.png";
483  rowData.name = tr("%1").arg(getPointName(toolId));
484  rowData.tool = tr("Point On Spline");
485  break;
486  }
487 
489  rowData.icon = ":/toolicon/32x32/line_intersect_axis.png";
490  rowData.name = tr("%1").arg(getPointName(toolId));
491  rowData.tool = tr("%Point Intersect Line & %1_%2 and Axis through point %3")
492  .arg(getPointName(attrUInt(domElement, AttrP1Line)))
493  .arg(getPointName(attrUInt(domElement, AttrP2Line)))
494  .arg(getPointName(attrUInt(domElement, AttrBasePoint)));
495  break;
496 
498  rowData.icon = ":/toolicon/32x32/arc_intersect_axis.png";
499  rowData.name = tr("%1").arg(getPointName(toolId));
500  rowData.tool = tr("Point Intersect Curve & Axis through point %1")
501  .arg(getPointName(attrUInt(domElement, AttrBasePoint)));
502  break;
503 
505  rowData.icon = ":/toolicon/32x32/point_of_intersection_arcs.png";
506  rowData.name = tr("%1").arg(getPointName(toolId));
507  rowData.tool = tr("Point Intersect Arcs");
508  break;
509 
511  rowData.icon = ":/toolicon/32x32/point_of_intersection_circles.png";
512  rowData.name = tr("%1").arg(getPointName(toolId));
513  rowData.tool = tr("%1 - Point Intersect Circles");
514  break;
515 
517  rowData.icon = ":/toolicon/32x32/intersection_curves.png";
518  rowData.name = tr("%1").arg(getPointName(toolId));
519  rowData.tool = tr("Point Intersect Curves");
520  break;
521 
523  rowData.icon = ":/toolicon/32x32/point_from_circle_and_tangent.png";
524  rowData.name = tr("%1").arg(getPointName(toolId));
525  rowData.tool = tr("Point Intersect Circle & Tangent");
526  break;
527 
529  rowData.icon = ":/toolicon/32x32/point_from_arc_and_tangent.png";
530  rowData.name = tr("%1").arg(getPointName(toolId));
531  rowData.tool = tr("Point Intersect Arc & Tangent");
532  break;
533 
534  case Tool::TrueDarts:
535  rowData.icon = ":/toolicon/32x32/true_darts.png";
536  rowData.name = tr("");
537  rowData.tool = tr("True Dart %1_%2_%3")
538  .arg(getPointName(attrUInt(domElement, AttrDartP1)))
539  .arg(getPointName(attrUInt(domElement, AttrDartP2)))
540  .arg(getPointName(attrUInt(domElement, AttrDartP2)));
541  break;
542 
543  case Tool::EllipticalArc:
544  {
545  const QSharedPointer<VEllipticalArc> elArc = data->GeometricObject<VEllipticalArc>(toolId);
546  SCASSERT(!elArc.isNull())
547  rowData.icon = ":/toolicon/32x32/el_arc.png";
548  rowData.name = tr("%1").arg(elArc->NameForHistory(tr("ElArc_")));
549  rowData.tool = tr("Arc Elliptical with length %1").arg(elArc->GetLength());
550  break;
551 
552  }
553  case Tool::Rotation:
554  rowData.icon = ":/toolicon/32x32/rotation.png";
555  rowData.name = tr("");
556  rowData.tool = tr("Rotation around point %1. Suffix %2")
557  .arg(getPointName(attrUInt(domElement, AttrCenter)),
558  m_doc->GetParametrString(domElement, AttrSuffix, QString()));
559  break;
560 
561  case Tool::MirrorByLine:
562  rowData.icon = ":/toolicon/32x32/mirror_by_line.png";
563  rowData.name = tr("");
564  rowData.tool = tr("Mirror by Line %1_%2. Suffix %3")
565  .arg(getPointName(attrUInt(domElement, AttrP1Line)))
566  .arg(getPointName(attrUInt(domElement, AttrP2Line)),
567  m_doc->GetParametrString(domElement, AttrSuffix, QString()));
568  break;
569 
570  case Tool::MirrorByAxis:
571  rowData.icon = ":/toolicon/32x32/mirror_by_axis.png";
572  rowData.name = tr("");
573  rowData.tool = tr("Mirror by Axis through %1 point. Suffix %2")
574  .arg(getPointName(attrUInt(domElement, AttrCenter)),
575  m_doc->GetParametrString(domElement, AttrSuffix, QString()));
576  break;
577 
578  case Tool::Move:
579  rowData.icon = ":/toolicon/32x32/move.png";
580  rowData.name = tr("");
581  rowData.tool = tr("Move - rotate around point %1. Suffix %2")
582  .arg(getPointName(attrUInt(domElement, AttrCenter)),
583  m_doc->GetParametrString(domElement, AttrSuffix, QString()));
584  break;
585 
586  //Because "history" not only shows history of pattern, but helps restore current data for each pattern's
587  //piece, we need add record about details and nodes, but don't show them.
588  case Tool::Piece:
589  case Tool::Union:
590  case Tool::NodeArc:
591  case Tool::NodeElArc:
592  case Tool::NodePoint:
593  case Tool::NodeSpline:
595  case Tool::Group:
596  case Tool::InternalPath:
597  case Tool::AnchorPoint:
598  case Tool::InsertNodes:
599  break;
600  }
601  return rowData;
602  }
603  catch (const VExceptionBadId &e)
604  {
605  qDebug()<<e.ErrorMessage()<<Q_FUNC_INFO;
606  return rowData;
607  }
608  qDebug()<<"Can't create history record for the tool.";
609  return rowData;
610 }
611 
613 
614 //---------------------------------------------------------------------------------------------------------------------
615 /**
616  * @brief initializeTable set initial option of table
617  */
619 {
620  ui->tableWidget->setSortingEnabled(false);
621  ui->tableWidget->verticalHeader()->setDefaultAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
622  ui->tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
623  ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Id"));
624  ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Name")));
625  ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(tr("Description")));
626 }
627 
628 //---------------------------------------------------------------------------------------------------------------------
629 /**
630  * @brief showTool show selected point
631  */
633 {
634  const QVector<VToolRecord> *history = m_doc->getHistory();
635  if (!history->empty())
636  {
637  QTableWidgetItem *item = ui->tableWidget->item(0, 1);
638  item->setSelected(true);
640  item = ui->tableWidget->item(0, 0);
641  quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
642  emit showHistoryTool(id, true);
643  }
644 }
645 
646 //---------------------------------------------------------------------------------------------------------------------
647 /**
648  * @brief HistoryDialog::PointName return point name by id.
649  *
650  * Refacoring what hide ugly string getting point name by id.
651  * @param pointId point if in data.
652  * @return point name.
653  */
654 QString HistoryDialog::getPointName(quint32 pointId)
655 {
656  return data->GeometricObject<VPointF>(pointId)->name();
657 }
658 
659 //---------------------------------------------------------------------------------------------------------------------
660 quint32 HistoryDialog::attrUInt(const QDomElement &domElement, const QString &name)
661 {
662  return m_doc->GetParametrUInt(domElement, name, "0");
663 }
664 
665 //---------------------------------------------------------------------------------------------------------------------
666 /**
667  * @brief closeEvent handle when windows is closing
668  * @param event event
669  */
670 void HistoryDialog::closeEvent(QCloseEvent *event)
671 {
672  QTableWidgetItem *item = ui->tableWidget->item(m_cursorToolRecordRow,1);
673  quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
674  emit showHistoryTool(id, false);
675  DialogTool::closeEvent(event);
676 }
677 
678 //---------------------------------------------------------------------------------------------------------------------
679 void HistoryDialog::changeEvent(QEvent *event)
680 {
681  if (event->type() == QEvent::LanguageChange)
682  {
683  // retranslate Creator form (single inheritance approach)
684  ui->retranslateUi(this);
685  retranslateUi();
686  }
687 
688  // remember to call base class implementation
689  QDialog::changeEvent(event);
690 }
691 
692 //---------------------------------------------------------------------------------------------------------------------
693 bool HistoryDialog::eventFilter(QObject *object, QEvent *event)
694 {
695  if (QLineEdit *textEdit = qobject_cast<QLineEdit *>(object))
696  {
697  if (event->type() == QEvent::KeyPress)
698  {
699  QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
700  if ((keyEvent->key() == Qt::Key_Period) && (keyEvent->modifiers() & Qt::KeypadModifier))
701  {
702  if (qApp->Settings()->GetOsSeparator())
703  {
704  textEdit->insert(QLocale().decimalPoint());
705  }
706  else
707  {
708  textEdit->insert(QLocale::c().decimalPoint());
709  }
710  return true;
711  }
712  }
713  }
714  else
715  {
716  // pass the event on to the parent class
717  return DialogTool::eventFilter(object, event);
718  }
719  return false;// pass the event to the widget
720 }
721 
722 //---------------------------------------------------------------------------------------------------------------------
724 {
725  qint32 currentRow = m_cursorRow;
726  updateHistory();
727 
728  QTableWidgetItem *item = ui->tableWidget->item(m_cursorRow, 0);
729  SCASSERT(item != nullptr)
730  item->setIcon(QIcon(""));
731 
732  m_cursorRow = currentRow;
734 }
735 
736 //---------------------------------------------------------------------------------------------------------------------
738 {
739  const quint32 cursor = m_doc->getCursor();
740  if (cursor == 0)
741  {
742  return ui->tableWidget->rowCount()-1;
743  }
744 
745  for (int i = 0; i < ui->tableWidget->rowCount(); ++i)
746  {
747  QTableWidgetItem *item = ui->tableWidget->item(i, 0);
748  const quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
749  if (cursor == id)
750  {
751  return i;
752  }
753  }
754  return ui->tableWidget->rowCount()-1;
755 }
756 
757 void HistoryDialog::findText(const QString &text)
758 {
759  updateHistory();
760  if (text.isEmpty())
761  {
762  return;
763  }
764 
765  QList<QTableWidgetItem *> items = ui->tableWidget->findItems(text, Qt::MatchContains);
766 
767  for (int i = 0; i < items.count(); ++i)
768  {
769  items.at(i)->setBackground(QColor("#b2cbe5"));
770  }
771 }
772 
773 //---------------------------------------------------------------------------------------------------------------------
774 /**
775  * @brief copyToClipboard copy dialog selection to clipboard as comma separated values.
776  */
778 {
779  QItemSelectionModel *model = ui->tableWidget->selectionModel();
780  QModelIndexList selectedIndexes = model->selectedIndexes();
781 
782  QString clipboardString;
783 
784  for (int i = 0; i < selectedIndexes.count(); ++i)
785  {
786  QModelIndex current = selectedIndexes[i];
787  QString displayText = current.data(Qt::DisplayRole).toString();
788 
789  // Check if another column exists beyond this one.
790  if (i + 1 < selectedIndexes.count())
791  {
792  QModelIndex next = selectedIndexes[i+1];
793 
794  // If the column is on different row, the clipboard should take note.
795  if (next.row() != current.row())
796  {
797  displayText.append("\n");
798  }
799  else
800  {
801  // Otherwise append a comma separator.
802  displayText.append(" , ");
803  }
804  }
805  clipboardString.append(displayText);
806  }
807 
808  QClipboard *clipboard = QApplication::clipboard();
809  clipboard->setText(clipboardString);
810 }
The DialogTool class parent for all dialog of tools.
Definition: dialogtool.h:107
void DialogClosed(int result)
DialogClosed signal dialog closed.
QPushButton * ok_Button
ok_Button button ok
Definition: dialogtool.h:199
virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE
closeEvent handle when dialog cloded
Definition: dialogtool.cpp:192
QString getPointName() const
const VContainer * data
data container with data
Definition: dialogtool.h:177
virtual bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE
Definition: dialogtool.cpp:441
The HistoryDialog class show dialog history.
VPattern * m_doc
ui keeps information about user interface
void updateHistory()
updateHistory update history table
void showTool()
showTool show selected point
void changedCursor(quint32 id)
changedCursor changed cursor of input. Cursor show after which record we will insert new object
void findText(const QString &text)
qint32 m_cursorRow
doc dom document container
qint32 m_cursorToolRecordRow
cursorRow save number of row where is cursor
virtual void DialogAccepted() Q_DECL_OVERRIDE
DialogAccepted save data and emit signal about closed dialog.
Ui::HistoryDialog * ui
virtual ~HistoryDialog() Q_DECL_OVERRIDE
virtual void changeEvent(QEvent *event) Q_DECL_OVERRIDE
void initializeTable()
initializeTable set initial option of table
virtual bool eventFilter(QObject *object, QEvent *event) Q_DECL_OVERRIDE
void cellClicked(int row, int column)
cellClicked changed history record
quint32 attrUInt(const QDomElement &domElement, const QString &name)
int cursorRow() const
RowData record(const VToolRecord &tool)
Record return description for record.
HistoryDialog(VContainer *data, VPattern *doc, QWidget *parent=nullptr)
HistoryDialog create dialog.
virtual void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE
closeEvent handle when windows is closing
void showHistoryTool(quint32 id, bool enable)
showHistoryTool signal change color of selected in records tool
void fillTable()
cursorToolRecordRow save number of row selected record
void copyToClipboard()
copyToClipboard copy dialog selection to clipboard as comma separated values.
void ChangedCursor(quint32 id)
ChangedCursor change cursor position.
void ShowTool(quint32 id, bool enable)
ShowTool highlight tool.
void patternChanged(bool saved)
patternChanged emit if we have unsaved change.
QVector< VToolRecord > getBlockHistory() const
void setCursor(const quint32 &value)
quint32 getCursor() const
QVector< VToolRecord > * getHistory()
getHistory return list with list of history records.
VArc class for anticlockwise arc.
Definition: varc.h:74
The VContainer class container of all variables.
Definition: vcontainer.h:141
const QSharedPointer< T > GeometricObject(const quint32 &id) const
Definition: vcontainer.h:266
static quint32 GetParametrUInt(const QDomElement &domElement, const QString &name, const QString &defValue)
Returns the long long value of the given attribute. RENAME: GetParameterLongLong?
The VExceptionBadId class for exception bad id.
virtual QString ErrorMessage() const Q_DECL_OVERRIDE
ErrorMessage return main error message.
The VPattern class working with pattern file.
Definition: vpattern.h:68
The VPointF class keep data of point.
Definition: vpointf.h:75
The VSplinePath class keep information about splinePath.
Definition: vsplinepath.h:72
VSpline class that implements the spline.
Definition: vspline.h:75
static const QString AttrSplinePath
static const QString AttrSpline
The VToolRecord class record about tool in history.
Definition: vtoolrecord.h:64
#define SCASSERT(cond)
Definition: def.h:317
@ CubicBezierPath
@ PointOfIntersectionCurves
@ PointOfIntersectionCircles
@ LineIntersectAxis
@ ArcWithLength
@ AlongLine
@ EndLine
@ SinglePoint
@ PointFromCircleAndTangent
@ InternalPath
@ MirrorByLine
@ ShoulderPoint
@ Spline
@ Bisector
@ NodeSplinePath
@ NodeSpline
@ NodeElArc
@ TrueDarts
@ Triangle
@ SplinePath
@ CurveIntersectAxis
@ LineIntersect
@ LinePoint
@ NodeArc
@ BasePoint
@ Midpoint
@ CutArc
@ ArcIntersectAxis
@ Normal
@ DoublePoint
@ EllipticalArc
@ PointOfContact
@ CutSplinePath
@ PointFromArcAndTangent
@ AbstractSpline
@ PointOfIntersection
@ NodePoint
@ CubicBezier
@ LAST_ONE_DO_NOT_USE
@ MirrorByAxis
@ PointOfIntersectionArcs
@ InsertNodes
@ Height
@ Rotation
@ CutSpline
@ AnchorPoint
const QString AttrBasePoint
Definition: ifcdef.cpp:95
const QString splPath
Definition: ifcdef.cpp:419
const QString AttrSecondPoint
Definition: ifcdef.cpp:97
const QString AttrFirstPoint
Definition: ifcdef.cpp:96
const QString AttrP1Line1
Definition: ifcdef.cpp:110
const QString AttrP1Line
Definition: ifcdef.cpp:108
const QString AttrP2Line
Definition: ifcdef.cpp:109
const QString AttrDartP2
Definition: ifcdef.cpp:86
const QString AttrAxisP2
Definition: ifcdef.cpp:126
const QString AttrDartP1
Definition: ifcdef.cpp:85
const QString AttrThirdPoint
Definition: ifcdef.cpp:98
const QString AttrAxisP1
Definition: ifcdef.cpp:125
const QString AttrP2Line2
Definition: ifcdef.cpp:113
const QString AttrP1Line2
Definition: ifcdef.cpp:112
const QString AttrSuffix
Definition: ifcdef.cpp:147
const QString AttrP2Line1
Definition: ifcdef.cpp:111
const QString AttrArc
Definition: ifcdef.cpp:146
const QString AttrCenter
Definition: ifcdef.cpp:99
quint32 id
QString name
QString tool
QString icon
#define qApp
Definition: vapplication.h:67