1 /************************************************************************
2  **
3  **  @file   dialoghistory.cpp
4  **  @author Roman Telezhynskyi <dismine(at)gmail.com>
5  **  @date   November 15, 2013
6  **
7  **  @brief
8  **  @copyright
9  **  This source code is part of the Valentina project, a pattern making
10  **  program, whose allow create and modeling patterns of clothing.
11  **  Copyright (C) 2013-2015 Valentina project
12  **  <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
13  **
14  **  Valentina is free software: you can redistribute it and/or modify
15  **  it under the terms of the GNU General Public License as published by
16  **  the Free Software Foundation, either version 3 of the License, or
17  **  (at your option) any later version.
18  **
19  **  Valentina is distributed in the hope that it will be useful,
20  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  **  GNU General Public License for more details.
23  **
24  **  You should have received a copy of the GNU General Public License
25  **  along with Valentina.  If not, see <http://www.gnu.org/licenses/>.
26  **
27  *************************************************************************/
28 
29 #include "dialoghistory.h"
30 #include "ui_dialoghistory.h"
31 #include "../vgeometry/varc.h"
32 #include "../vgeometry/vellipticalarc.h"
33 #include "../vgeometry/vcubicbezier.h"
34 #include "../vgeometry/vsplinepath.h"
35 #include "../vgeometry/vcubicbezierpath.h"
36 #include "../vgeometry/vpointf.h"
37 #include "../vtools/tools/vabstracttool.h"
38 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutspline.h"
39 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutsplinepath.h"
40 #include "../vtools/tools/drawTools/toolpoint/toolsinglepoint/toolcut/vtoolcutarc.h"
41 #include "../xml/vpattern.h"
42 #include "../vmisc/diagnostic.h"
43 
44 #include <QDebug>
45 #include <QtConcurrent>
46 #include <functional>
47 
48 //---------------------------------------------------------------------------------------------------------------------
49 /**
50  * @brief DialogHistory create dialog
51  * @param data container with data
52  * @param doc dom document container
53  * @param parent parent widget
54  */
DialogHistory(VContainer * data,VPattern * doc,QWidget * parent)55 DialogHistory::DialogHistory(VContainer *data, VPattern *doc, QWidget *parent)
56     :DialogTool(data, 0, parent), ui(new Ui::DialogHistory), doc(doc), cursorRow(0),
57     cursorToolRecordRow(0)
58 {
59     ui->setupUi(this);
60 
61     VAbstractApplication::VApp()->Settings()->GetOsSeparator() ? setLocale(QLocale()) : setLocale(QLocale::c());
62 
63     bOk = ui->buttonBox->button(QDialogButtonBox::Ok);
64     connect(bOk, &QPushButton::clicked, this, &DialogHistory::DialogAccepted);
65     FillTable();
66     InitialTable();
67     connect(ui->tableWidget, &QTableWidget::cellClicked, this, &DialogHistory::cellClicked);
68     connect(this, &DialogHistory::ShowHistoryTool, doc, [doc](quint32 id, bool enable)
69     {
70         emit doc->ShowTool(id, enable);
71     });
72     connect(doc, &VPattern::ChangedCursor, this, &DialogHistory::ChangedCursor);
73     connect(doc, &VPattern::patternChanged, this, &DialogHistory::UpdateHistory);
74     ShowPoint();
75 }
76 
77 //---------------------------------------------------------------------------------------------------------------------
~DialogHistory()78 DialogHistory::~DialogHistory()
79 {
80     delete ui;
81 }
82 
83 //---------------------------------------------------------------------------------------------------------------------
84 /**
85  * @brief DialogAccepted save data and emit signal about closed dialog.
86  */
DialogAccepted()87 void DialogHistory::DialogAccepted()
88 {
89     QTableWidgetItem *item = ui->tableWidget->item(cursorToolRecordRow, 0);
90     if (item != nullptr)
91     {
92         auto id = qvariant_cast<quint32>(item->data(Qt::UserRole));
93         emit ShowHistoryTool(id, false);
94     }
95     emit DialogClosed(QDialog::Accepted);
96 }
97 
98 //---------------------------------------------------------------------------------------------------------------------
99 /**
100  * @brief cellClicked changed history record
101  * @param row number row in table
102  * @param column number column in table
103  */
cellClicked(int row,int column)104 void DialogHistory::cellClicked(int row, int column)
105 {
106     if (column == 0)
107     {
108         QTableWidgetItem *item = ui->tableWidget->item(cursorRow, 0);
109         item->setIcon(QIcon());
110 
111         item = ui->tableWidget->item(row, 0);
112         cursorRow = row;
113         item->setIcon(QIcon("://icon/32x32/put_after.png"));
114         const quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
115         doc->blockSignals(true);
116         row == ui->tableWidget->rowCount()-1 ? doc->setCursor(0) : doc->setCursor(id);
117         doc->blockSignals(false);
118     }
119     else
120     {
121         QTableWidgetItem *item = ui->tableWidget->item(cursorToolRecordRow, 0);
122         quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
123         emit ShowHistoryTool(id, false);
124 
125         cursorToolRecordRow = row;
126         item = ui->tableWidget->item(cursorToolRecordRow, 0);
127         id = qvariant_cast<quint32>(item->data(Qt::UserRole));
128         emit ShowHistoryTool(id, true);
129     }
130 }
131 
132 //---------------------------------------------------------------------------------------------------------------------
133 /**
134  * @brief ChangedCursor changed cursor of input. Cursor show after which record we will insert new object
135  * @param id id of object
136  */
ChangedCursor(quint32 id)137 void DialogHistory::ChangedCursor(quint32 id)
138 {
139     for (qint32 i = 0; i< ui->tableWidget->rowCount(); ++i)
140     {
141         QTableWidgetItem *item = ui->tableWidget->item(i, 0);
142         quint32 rId = qvariant_cast<quint32>(item->data(Qt::UserRole));
143         if (rId == id)
144         {
145             QTableWidgetItem *oldCursorItem = ui->tableWidget->item(cursorRow, 0);
146             oldCursorItem->setIcon(QIcon());
147             cursorRow = i;
148             item->setIcon(QIcon("://icon/32x32/put_after.png"));
149         }
150     }
151 }
152 
153 //---------------------------------------------------------------------------------------------------------------------
154 /**
155  * @brief UpdateHistory update history table
156  */
UpdateHistory()157 void DialogHistory::UpdateHistory()
158 {
159     FillTable();
160     InitialTable();
161 }
162 
163 //---------------------------------------------------------------------------------------------------------------------
164 /**
165  * @brief FillTable fill table
166  */
FillTable()167 void DialogHistory::FillTable()
168 {
169     ui->tableWidget->clear();
170     QVector<VToolRecord> history = doc->getLocalHistory();
171     qint32 currentRow = -1;
172     qint32 count = 0;
173     ui->tableWidget->setRowCount(history.size());//Make row count max possible number
174 
175     std::function<HistoryRecord (const VToolRecord &tool)> CreateRecord = [this](const VToolRecord &tool)
176     {
177         return Record(tool);
178     };
179 
180     QVector<HistoryRecord> historyRecords = QtConcurrent::blockingMapped(history, CreateRecord);
181 
182     for (auto &record : historyRecords)
183     {
184         if (not record.description.isEmpty())
185         {
186             currentRow++;
187 
188             {
189                 QTableWidgetItem *item = new QTableWidgetItem(QString());
190                 item->setTextAlignment(Qt::AlignHCenter);
191                 item->setData(Qt::UserRole, record.id);
192                 item->setFlags(item->flags() ^ Qt::ItemIsEditable);
193                 ui->tableWidget->setItem(currentRow, 0, item);
194             }
195 
196             QTableWidgetItem *item = new QTableWidgetItem(record.description);
197             item->setFont(QFont("Times", 12, QFont::Bold));
198             item->setFlags(item->flags() ^ Qt::ItemIsEditable);
199             ui->tableWidget->setItem(currentRow, 1, item);
200             ++count;
201         }
202     }
203     ui->tableWidget->setRowCount(count);//Real row count
204     if (count>0)
205     {
206         cursorRow = CursorRow();
207         QTableWidgetItem *item = ui->tableWidget->item(cursorRow, 0);
208         SCASSERT(item != nullptr)
209         item->setIcon(QIcon("://icon/32x32/put_after.png"));
210     }
211     ui->tableWidget->resizeColumnsToContents();
212     ui->tableWidget->resizeRowsToContents();
213     ui->tableWidget->verticalHeader()->setDefaultSectionSize(20);
214 }
215 
216 //---------------------------------------------------------------------------------------------------------------------
217 QT_WARNING_PUSH
218 QT_WARNING_DISABLE_GCC("-Wswitch-default")
219 /**
220  * @brief Record return description for record
221  * @param tool record data
222  * @return description
223  */
Record(const VToolRecord & tool) const224 HistoryRecord DialogHistory::Record(const VToolRecord &tool) const
225 {
226     // This check helps to find missed tools in the switch
227     Q_STATIC_ASSERT_X(static_cast<int>(Tool::LAST_ONE_DO_NOT_USE) == 55, "Not all tools were used in history.");
228 
229     HistoryRecord record;
230     record.id = tool.getId();
231 
232     bool updateCache = false;
233     const QDomElement domElem = doc->elementById(tool.getId(), QString(), updateCache);
234     if (domElem.isElement() == false)
235     {
236         qDebug()<<"Can't find element by id" << record.id << Q_FUNC_INFO;
237         return record;
238     }
239     try
240     {
241         switch ( tool.getTypeTool() )
242         {
243             case Tool::Arrow:
244             case Tool::SinglePoint:
245             case Tool::DoublePoint:
246             case Tool::LinePoint:
247             case Tool::AbstractSpline:
248             case Tool::Cut:
249             case Tool::Midpoint:// Same as Tool::AlongLine, but tool will never has such type
250             case Tool::ArcIntersectAxis:// Same as Tool::CurveIntersectAxis, but tool will never has such type
251             case Tool::LAST_ONE_DO_NOT_USE:
252                 Q_UNREACHABLE(); //-V501
253                 break;
254             case Tool::BasePoint:
255                 record.description = tr("%1 - Base point").arg(PointName(tool.getId()));
256                 return record;
257             case Tool::EndLine:
258                 record.description = tr("%1_%2 - Line from point %1 to point %2")
259                                          .arg(PointName(AttrUInt(domElem, AttrBasePoint)), PointName(tool.getId()));
260                 return record;
261             case Tool::Line:
262                 record.description = tr("%1_%2 - Line from point %1 to point %2")
263                                          .arg(PointName(AttrUInt(domElem, AttrFirstPoint)),
264                                               PointName(AttrUInt(domElem, AttrSecondPoint)));
265                 return record;
266             case Tool::AlongLine:
267                 record.description = tr("%3 - Point along line %1_%2")
268                                          .arg(PointName(AttrUInt(domElem, AttrFirstPoint)),
269                                               PointName(AttrUInt(domElem, AttrSecondPoint)), PointName(tool.getId()));
270                 return record;
271             case Tool::ShoulderPoint:
272                 record.description = tr("%1 - Point of shoulder").arg(PointName(tool.getId()));
273                 return record;
274             case Tool::Normal:
275                 record.description = tr("%3 - normal to line %1_%2")
276                                          .arg(PointName(AttrUInt(domElem, AttrFirstPoint)),
277                                               PointName(AttrUInt(domElem, AttrSecondPoint)), PointName(tool.getId()));
278                 return record;
279             case Tool::Bisector:
280                 record.description = tr("%4 - bisector of angle %1_%2_%3")
281                                          .arg(PointName(AttrUInt(domElem, AttrFirstPoint)),
282                                               PointName(AttrUInt(domElem, AttrSecondPoint)),
283                                               PointName(AttrUInt(domElem, AttrThirdPoint)), PointName(tool.getId()));
284                 return record;
285             case Tool::LineIntersect:
286                 record.description = tr("%5 - intersection of lines %1_%2 and %3_%4")
287                                          .arg(PointName(AttrUInt(domElem, AttrP1Line1)),
288                                               PointName(AttrUInt(domElem, AttrP2Line1)),
289                                               PointName(AttrUInt(domElem, AttrP1Line2)),
290                                               PointName(AttrUInt(domElem, AttrP2Line2)),
291                                               PointName(tool.getId()));
292                 return record;
293             case Tool::Spline:
294             {
295                 const QSharedPointer<VSpline> spl = data->GeometricObject<VSpline>(tool.getId());
296                 SCASSERT(not spl.isNull())
297                 record.description = spl->NameForHistory(tr("Curve"));
298                 return record;
299             }
300             case Tool::CubicBezier:
301             {
302                 const QSharedPointer<VCubicBezier> spl = data->GeometricObject<VCubicBezier>(tool.getId());
303                 SCASSERT(not spl.isNull())
304                 record.description = spl->NameForHistory(tr("Cubic bezier curve"));
305                 return record;
306             }
307             case Tool::Arc:
308             {
309                 const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(tool.getId());
310                 SCASSERT(not arc.isNull())
311                 record.description = arc->NameForHistory(tr("Arc"));
312                 return record;
313             }
314             case Tool::ArcWithLength:
315             {
316                 const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(tool.getId());
317                 SCASSERT(not arc.isNull())
318                 record.description = tr("%1 with length %2")
319                                          .arg(arc->NameForHistory(tr("Arc")))
320                                          .arg(arc->GetLength());
321                 return record;
322             }
323             case Tool::SplinePath:
324             {
325                 const QSharedPointer<VSplinePath> splPath = data->GeometricObject<VSplinePath>(tool.getId());
326                 SCASSERT(not splPath.isNull())
327                 record.description = splPath->NameForHistory(tr("Spline path"));
328                 return record;
329             }
330             case Tool::CubicBezierPath:
331             {
332                 const QSharedPointer<VCubicBezierPath> splPath = data->GeometricObject<VCubicBezierPath>(tool.getId());
333                 SCASSERT(not splPath.isNull())
334                 record.description = splPath->NameForHistory(tr("Cubic bezier curve path"));
335                 return record;
336             }
337             case Tool::PointOfContact:
338                 record.description = tr("%4 - point of contact of arc with the center in point %1 and line %2_%3")
339                                          .arg(PointName(AttrUInt(domElem, AttrCenter)),
340                                               PointName(AttrUInt(domElem, AttrFirstPoint)),
341                                               PointName(AttrUInt(domElem, AttrSecondPoint)),
342                                               PointName(tool.getId()));
343                 return record;
344             case Tool::Height:
345                 record.description = tr("Point of perpendicular from point %1 to line %2_%3")
346                                          .arg(PointName(AttrUInt(domElem, AttrBasePoint)),
347                                               PointName(AttrUInt(domElem, AttrP1Line)),
348                                               PointName(AttrUInt(domElem, AttrP2Line)));
349                 return record;
350             case Tool::Triangle:
351                 record.description = tr("Triangle: axis %1_%2, points %3 and %4")
352                                          .arg(PointName(AttrUInt(domElem, AttrAxisP1)),
353                                               PointName(AttrUInt(domElem, AttrAxisP2)),
354                                               PointName(AttrUInt(domElem, AttrFirstPoint)),
355                                               PointName(AttrUInt(domElem, AttrSecondPoint)));
356                 return record;
357             case Tool::PointOfIntersection:
358                 record.description = tr("%1 - point of intersection %2 and %3")
359                                          .arg(PointName(tool.getId()),
360                                               PointName(AttrUInt(domElem, AttrFirstPoint)),
361                                               PointName(AttrUInt(domElem, AttrSecondPoint)));
362                 return record;
363             case Tool::CutArc:
364             {
365                 const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(AttrUInt(domElem, AttrArc));
366                 SCASSERT(not arc.isNull())
367                 record.description = tr("%1 - cut %2")
368                                          .arg(PointName(tool.getId()), arc->NameForHistory(tr("arc")));
369                 return record;
370             }
371             case Tool::CutSpline:
372             {
373                 const quint32 splineId = AttrUInt(domElem, VToolCutSpline::AttrSpline);
374                 const QSharedPointer<VAbstractCubicBezier> spl = data->GeometricObject<VAbstractCubicBezier>(splineId);
375                 SCASSERT(not spl.isNull())
376                 record.description = tr("%1 - cut %2")
377                                          .arg(PointName(tool.getId()), spl->NameForHistory(tr("curve")));
378                 return record;
379             }
380             case Tool::CutSplinePath:
381             {
382                 const quint32 splinePathId = AttrUInt(domElem, VToolCutSplinePath::AttrSplinePath);
383                 const QSharedPointer<VAbstractCubicBezierPath> splPath =
384                         data->GeometricObject<VAbstractCubicBezierPath>(splinePathId);
385                 SCASSERT(not splPath.isNull())
386                 record.description = tr("%1 - cut %2")
387                                          .arg(PointName(tool.getId()), splPath->NameForHistory(tr("curve path")));
388                 return record;
389             }
390             case Tool::LineIntersectAxis:
391                 record.description = tr("%1 - point of intersection line %2_%3 and axis through point %4")
392                                          .arg(PointName(tool.getId()),
393                                               PointName(AttrUInt(domElem, AttrP1Line)),
394                                               PointName(AttrUInt(domElem, AttrP2Line)),
395                                               PointName(AttrUInt(domElem, AttrBasePoint)));
396                 return record;
397             case Tool::CurveIntersectAxis:
398                 record.description = tr("%1 - point of intersection curve and axis through point %2")
399                                          .arg(PointName(tool.getId()), PointName(AttrUInt(domElem, AttrBasePoint)));
400                 return record;
401             case Tool::PointOfIntersectionArcs:
402                 record.description = tr("%1 - point of arcs intersection").arg(PointName(tool.getId()));
403                 return record;
404             case Tool::PointOfIntersectionCircles:
405                 record.description = tr("%1 - point of circles intersection").arg(PointName(tool.getId()));
406                 return record;
407             case Tool::PointOfIntersectionCurves:
408                 record.description = tr("%1 - point of curves intersection").arg(PointName(tool.getId()));
409                 return record;
410             case Tool::PointFromCircleAndTangent:
411                 record.description = tr("%1 - point from circle and tangent").arg(PointName(tool.getId()));
412                 return record;
413             case Tool::PointFromArcAndTangent:
414                 record.description = tr("%1 - point from arc and tangent").arg(PointName(tool.getId()));
415                 return record;
416             case Tool::TrueDarts:
417                 record.description = tr("Correction the dart %1_%2_%3")
418                                          .arg(PointName(AttrUInt(domElem, AttrDartP1)),
419                                               PointName(AttrUInt(domElem, AttrDartP2)),
420                                               PointName(AttrUInt(domElem, AttrDartP2)));
421                 return record;
422             case Tool::EllipticalArc:
423             {
424                 const QSharedPointer<VEllipticalArc> elArc = data->GeometricObject<VEllipticalArc>(tool.getId());
425                 SCASSERT(not elArc.isNull())
426                 record.description = tr("%1 with length %2")
427                                          .arg(elArc->NameForHistory(tr("Elliptical arc")))
428                                          .arg(elArc->GetLength());
429                 return record;
430             }
431             case Tool::Rotation:
432                 record.description = tr("Rotate objects around point %1. Suffix '%2'")
433                                          .arg(PointName(AttrUInt(domElem, AttrCenter)),
434                                               doc->GetParametrString(domElem, AttrSuffix, QString()));
435                 return record;
436             case Tool::FlippingByLine:
437                 record.description = tr("Flipping by line %1_%2. Suffix '%3'")
438                                          .arg(PointName(AttrUInt(domElem, AttrP1Line)),
439                                               PointName(AttrUInt(domElem, AttrP2Line)),
440                                               doc->GetParametrString(domElem, AttrSuffix, QString()));
441                 return record;
442             case Tool::FlippingByAxis:
443                 record.description = tr("Flipping by axis through %1 point. Suffix '%2'")
444                                          .arg(PointName(AttrUInt(domElem, AttrCenter)),
445                                          doc->GetParametrString(domElem, AttrSuffix, QString()));
446                 return record;
447             case Tool::Move:
448                 record.description = tr("Move objects. Suffix '%1'")
449                                          .arg(doc->GetParametrString(domElem, AttrSuffix, QString()));
450                 return record;
451             //Because "history" not only show history of pattern, but help restore current data for each pattern's
452             //piece, we need add record about details and nodes, but don't show them.
453             case Tool::Piece:
454             case Tool::UnionDetails:
455             case Tool::NodeArc:
456             case Tool::NodeElArc:
457             case Tool::NodePoint:
458             case Tool::NodeSpline:
459             case Tool::NodeSplinePath:
460             case Tool::Group:
461             case Tool::PiecePath:
462             case Tool::Pin:
463             case Tool::PlaceLabel:
464             case Tool::InsertNode:
465             case Tool::DuplicateDetail:
466                 return record;
467         }
468     }
469     catch (const VExceptionBadId &e)
470     {
471         qDebug()<<e.ErrorMessage()<<Q_FUNC_INFO;
472         return record;
473     }
474     qDebug()<<"Can't create history record for the tool" << record.id;
475     return record;
476 }
477 
478 QT_WARNING_POP
479 
480 //---------------------------------------------------------------------------------------------------------------------
481 /**
482  * @brief InitialTable set initial option of table
483  */
InitialTable()484 void DialogHistory::InitialTable()
485 {
486     ui->tableWidget->setSortingEnabled(false);
487     ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(QChar(QChar::Space)));
488     ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(tr("Tool")));
489 }
490 
491 //---------------------------------------------------------------------------------------------------------------------
492 /**
493  * @brief ShowPoint show selected point
494  */
ShowPoint()495 void DialogHistory::ShowPoint()
496 {
497     const QVector<VToolRecord> *history = doc->getHistory();
498     if (history->size()>0)
499     {
500         QTableWidgetItem *item = ui->tableWidget->item(0, 1);
501         item->setSelected(true);
502         cursorToolRecordRow = 0;
503         item = ui->tableWidget->item(0, 0);
504         quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
505         emit ShowHistoryTool(id, true);
506     }
507 }
508 
509 //---------------------------------------------------------------------------------------------------------------------
510 /**
511  * @brief DialogHistory::PointName return point name by id.
512  *
513  * Refacoring what hide ugly string getting point name by id.
514  * @param pointId point if in data.
515  * @return point name.
516  */
PointName(quint32 pointId) const517 QString DialogHistory::PointName(quint32 pointId) const
518 {
519     return data->GeometricObject<VPointF>(pointId)->name();
520 }
521 
522 //---------------------------------------------------------------------------------------------------------------------
AttrUInt(const QDomElement & domElement,const QString & name) const523 quint32 DialogHistory::AttrUInt(const QDomElement &domElement, const QString &name) const
524 {
525     return doc->GetParametrUInt(domElement, name, QChar('0'));
526 }
527 
528 //---------------------------------------------------------------------------------------------------------------------
529 /**
530  * @brief closeEvent handle when windows is closing
531  * @param event event
532  */
closeEvent(QCloseEvent * event)533 void DialogHistory::closeEvent(QCloseEvent *event)
534 {
535     QTableWidgetItem *item = ui->tableWidget->item(cursorToolRecordRow, 0);
536     quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
537     emit ShowHistoryTool(id, false);
538     DialogTool::closeEvent(event);
539 }
540 
541 //---------------------------------------------------------------------------------------------------------------------
changeEvent(QEvent * event)542 void DialogHistory::changeEvent(QEvent *event)
543 {
544     if (event->type() == QEvent::LanguageChange)
545     {
546         // retranslate designer form (single inheritance approach)
547         ui->retranslateUi(this);
548         RetranslateUi();
549     }
550 
551     // remember to call base class implementation
552     QDialog::changeEvent(event);
553 }
554 
555 //---------------------------------------------------------------------------------------------------------------------
showEvent(QShowEvent * event)556 void DialogHistory::showEvent(QShowEvent *event)
557 {
558     QDialog::showEvent( event ); // return default behavior
559 }
560 
561 //---------------------------------------------------------------------------------------------------------------------
RetranslateUi()562 void DialogHistory::RetranslateUi()
563 {
564     qint32 currentRow = cursorRow;
565     UpdateHistory();
566 
567     QTableWidgetItem *item = ui->tableWidget->item(cursorRow, 0);
568     SCASSERT(item != nullptr)
569     item->setIcon(QIcon(QString()));
570 
571     cursorRow = currentRow;
572     cellClicked(cursorRow, 0);
573 }
574 
575 //---------------------------------------------------------------------------------------------------------------------
CursorRow() const576 int DialogHistory::CursorRow() const
577 {
578     const quint32 cursor = doc->getCursor();
579     if (cursor == 0)
580     {
581         return ui->tableWidget->rowCount()-1;
582     }
583 
584     for (int i = 0; i < ui->tableWidget->rowCount(); ++i)
585     {
586         QTableWidgetItem *item = ui->tableWidget->item(i, 0);
587         const quint32 id = qvariant_cast<quint32>(item->data(Qt::UserRole));
588         if (cursor == id)
589         {
590             return i;
591         }
592     }
593     return ui->tableWidget->rowCount()-1;
594 }
595