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