1 /**********************************************************************************************
2     Copyright (C) 2017 Oliver Eichler <oliver.eichler@gmx.de>
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 
17 **********************************************************************************************/
18 
19 #include "canvas/IDrawContext.h"
20 #include "helpers/CDraw.h"
21 #include "helpers/CSettings.h"
22 #include "items/CItemRefMap.h"
23 #include "overlay/COverlayRefMap.h"
24 #include "overlay/refmap/CDialogRefPoint.h"
25 #include "overlay/refmap/COverlayRefMapPoint.h"
26 #include "overlay/refmap/CProjWizard.h"
27 
28 #include <functional>
29 #include <QtWidgets>
30 using std::bind;
31 
COverlayRefMap(CItemRefMap * item,QStackedWidget * stackedWidget)32 COverlayRefMap::COverlayRefMap(CItemRefMap* item, QStackedWidget* stackedWidget)
33     : IOverlay(stackedWidget)
34     , context(item->getDrawContext())
35     , item(item)
36 {
37     setupUi(this);
38 
39     QFileInfo fi(item->getFilename());
40     gcpFilename = fi.completeBaseName() + ".gcp";
41 
42     labelHelp->setText(tr("If you used the Grid Tool you have to fine tune the reference points by placing them "
43                           "as much as possible on the grid crossing. Be aware that if you over scale you get "
44                           "jumping points by rounding effects. Be precise but do not make religion out "
45                           "of the task.\nIf your mouse focus is on the map you can use the N and B keys to "
46                           "jump forward an backward in the reference point list. "
47                           "\nThe is also the option to fine tune the reference points in auto-mode. In this "
48                           "mode the next reference point is selected automatically right after you placed the "
49                           "current one. This is very convenient for a large number of reference points."));
50 
51     labelHelp->setVisible(CMainWindow::self().showToolHelp()->isChecked());
52     connect(CMainWindow::self().showToolHelp(), &QAction::toggled, labelHelp, &QLabel::setVisible);
53 
54     treeWidget->addAction(actionDelRefPoint);
55 
56     connect(toolNone, &QToolButton::clicked, this, bind(&COverlayRefMap::slotSetMode, this, eModeNone, std::placeholders::_1));
57     connect(toolRefMove, &QToolButton::clicked, this, bind(&COverlayRefMap::slotSetMode, this, eModePointMove, std::placeholders::_1));
58     connect(toolRefAdd, &QToolButton::clicked, this, bind(&COverlayRefMap::slotSetMode, this, eModePointAdd, std::placeholders::_1));
59     connect(toolRefDel, &QToolButton::clicked, this, bind(&COverlayRefMap::slotSetMode, this, eModePointDel, std::placeholders::_1));
60     connect(toolRefMoveAuto, &QToolButton::clicked, this, bind(&COverlayRefMap::slotSetMode, this, eModePointMoveAuto, std::placeholders::_1));
61     connect(toolRefDelAll, &QToolButton::clicked, this, &COverlayRefMap::slotResetRef);
62     connect(toolLoadGcp, &QToolButton::clicked, this, &COverlayRefMap::slotLoadGcp);
63     connect(toolSaveGcp, &QToolButton::clicked, this, &COverlayRefMap::slotSaveGcp);
64     connect(toolProjection, &QToolButton::clicked, this, &COverlayRefMap::slotProjWizard);
65     connect(toolGridTool, &QToolButton::clicked, this, &COverlayRefMap::slotGridTool);
66     connect(toolSort, &QToolButton::clicked, this, &COverlayRefMap::slotSortRefPoints);
67     connect(treeWidget, &QTreeWidget::itemSelectionChanged, this, &COverlayRefMap::slotSelectionChanged);
68     connect(actionDelRefPoint, &QAction::triggered, this, &COverlayRefMap::slotDelRefPoints);
69 }
70 
saveSettings(QSettings & cfg)71 void COverlayRefMap::saveSettings(QSettings& cfg)
72 {
73     QByteArray buffer;
74     QDataStream stream(&buffer, QIODevice::WriteOnly);
75     stream.setByteOrder(QDataStream::LittleEndian);
76     stream.setVersion(QDataStream::Qt_5_4);
77 
78     const int N = treeWidget->topLevelItemCount();
79     stream << N;
80     for(int n = 0; n < N; n++)
81     {
82         COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
83         if(item != nullptr)
84         {
85             stream << item->getPtPtx() << item->getPtRef();
86         }
87     }
88 
89     cfg.beginGroup("grid");
90     cfg.setValue("points", buffer);
91     cfg.setValue("projection", lineProjection->text());
92     cfg.endGroup();
93 }
94 
loadSettings(QSettings & cfg)95 void COverlayRefMap::loadSettings(QSettings& cfg)
96 {
97     QByteArray buffer;
98     cfg.beginGroup("grid");
99     buffer = cfg.value("points", buffer).toByteArray();
100     lineProjection->setText(cfg.value("projection", "").toString());
101     lineProjection->setCursorPosition(0);
102     cfg.endGroup();
103 
104     QDataStream stream(&buffer, QIODevice::ReadOnly);
105     stream.setByteOrder(QDataStream::LittleEndian);
106     stream.setVersion(QDataStream::Qt_5_4);
107 
108 
109     int N;
110     stream >> N;
111     for(int n = 0; n < N; n++)
112     {
113         QPointF ptPtx;
114         QPointF ptRef;
115         stream >> ptPtx >> ptRef;
116         new COverlayRefMapPoint(n + 1, ptRef, ptPtx, treeWidget);
117     }
118 
119     updateGui();
120     slotSortRefPoints();
121     emit sigChanged();
122 }
123 
slotSortRefPoints()124 void COverlayRefMap::slotSortRefPoints()
125 {
126     treeWidget->sortItems(0, Qt::AscendingOrder);
127     const int N = treeWidget->topLevelItemCount();
128     for(int n = 0; n < N; n++)
129     {
130         COverlayRefMapPoint* point = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
131         if(point == nullptr)
132         {
133             continue;
134         }
135 
136         point->setIndex(n);
137     }
138 
139     treeWidget->header()->resizeSections(QHeaderView::ResizeToContents);
140 }
141 
addRefPoints(QList<COverlayRefMapPoint * > & points)142 void COverlayRefMap::addRefPoints(QList<COverlayRefMapPoint*>& points)
143 {
144     // it's faster to use a bulk add
145     QList<QTreeWidgetItem*> items;
146     for(QTreeWidgetItem* item : points)
147     {
148         items << item;
149     }
150     treeWidget->addTopLevelItems(items);
151 
152     // as the tree widget owns the items now, the list has to be cleared
153     points.clear();
154     // reflect changes on the GUI
155     updateGui();
156 
157     emit sigChanged();
158 }
159 
getMapProjection() const160 QString COverlayRefMap::getMapProjection() const
161 {
162     return lineProjection->text();
163 }
164 
getRefPoints() const165 const QList<COverlayRefMapPoint*> COverlayRefMap::getRefPoints() const
166 {
167     QList<COverlayRefMapPoint*> points;
168 
169     const int N = treeWidget->topLevelItemCount();
170     for(int n = 0; n < N; n++)
171     {
172         COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
173         if(item != nullptr)
174         {
175             points << item;
176         }
177     }
178 
179     return points;
180 }
181 
drawFx(QPainter & p,CCanvas::redraw_e needsRedraw)182 bool COverlayRefMap::drawFx(QPainter& p, CCanvas::redraw_e needsRedraw)
183 {
184     QRectF dot1(0, 0, 5, 5);
185     const int N = treeWidget->topLevelItemCount();
186     for(int n = 0; n < N; n++)
187     {
188         COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
189         if(item != nullptr)
190         {
191             if(item->isSelected())
192             {
193                 p.setPen(QPen(Qt::red, 1));
194                 p.setBrush(Qt::red);
195             }
196             else
197             {
198                 p.setPen(QPen(Qt::black, 1));
199                 p.setBrush(Qt::black);
200             }
201 
202             QPointF pt = item->getPtPtx();
203             if((pt - ptFocus1).manhattanLength() > 30)
204             {
205                 context->convertMap2Screen(pt);
206                 dot1.moveCenter(pt);
207                 p.drawRect(dot1);
208             }
209         }
210     }
211 
212     QPointF pt = NOPOINTF;
213     if(ptFocus2 != NOPOINTF)
214     {
215         pt = ptFocus2;
216     }
217     else if(ptFocus1 != NOPOINTF)
218     {
219         pt = ptFocus1;
220     }
221 
222 
223     if(pt != NOPOINTF)
224     {
225         context->convertMap2Screen(pt);
226 
227         if(movePoint)
228         {
229             QPointF pt1 = ptFocus1;
230             context->convertMap2Screen(pt1);
231 
232             p.setPen(QPen(Qt::red, 1));
233             p.setBrush(Qt::red);
234             p.drawLine(pt1, pt);
235             dot1.moveCenter(pt1);
236             p.drawRect(dot1);
237         }
238 
239         CDraw::drawCrossHairDot(p, pt);
240     }
241 
242 
243     return true;
244 }
245 
isCloseTo(QPointF pt)246 QPointF COverlayRefMap::isCloseTo(QPointF pt)
247 {
248     qint32 min = 30;
249     COverlayRefMapPoint* selItem = nullptr;
250 
251     context->convertMap2Screen(pt);
252 
253     const int N = treeWidget->topLevelItemCount();
254     for(int n = 0; n < N; n++)
255     {
256         COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
257         if(item == nullptr)
258         {
259             continue;
260         }
261 
262         QPointF ptx = item->getPtPtx();
263         context->convertMap2Screen(ptx);
264 
265         qint32 d = (pt - ptx).manhattanLength();
266         if(d < min)
267         {
268             min = d;
269             selItem = item;
270         }
271     }
272 
273     if(selItem != nullptr)
274     {
275         treeWidget->setCurrentItem(selItem);
276         return selItem->getPtPtx();
277     }
278     else
279     {
280         return NOPOINTF;
281     }
282 }
283 
284 
mouseMoveEventFx(QMouseEvent * e)285 void COverlayRefMap::mouseMoveEventFx(QMouseEvent* e)
286 {
287     QPointF pt = e->pos();
288     context->convertScreen2Map(pt);
289 
290     switch(mode)
291     {
292     case eModePointMove:
293     case eModePointMoveAuto:
294         mouseMovePointMove(pt);
295         break;
296 
297     case eModePointAdd:
298         mouseMovePointAdd(pt);
299         break;
300 
301     case eModePointDel:
302         mouseMovePointDel(pt);
303         break;
304     }
305 
306     updateGui();
307     context->triggerCompleteUpdate(CCanvas::eRedrawOverlay);
308 }
309 
mouseReleaseEventFx(QMouseEvent * e)310 void COverlayRefMap::mouseReleaseEventFx(QMouseEvent* e)
311 {
312     QPointF pt = e->pos();
313     context->convertScreen2Map(pt);
314 
315     Qt::MouseButton button = e->button();
316 
317     switch(mode)
318     {
319     case eModePointMove:
320     case eModePointMoveAuto:
321         mouseReleasePointMove(pt, button);
322         break;
323 
324     case eModePointAdd:
325         mouseReleasePointAdd(pt, button);
326         break;
327 
328     case eModePointDel:
329         mouseReleasePointDel(pt, button);
330         break;
331     }
332 
333     updateGui();
334     context->triggerCompleteUpdate(CCanvas::eRedrawOverlay);
335 }
336 
mouseMovePointAdd(const QPointF & pt)337 void COverlayRefMap::mouseMovePointAdd(const QPointF& pt)
338 {
339     ptFocus1 = pt;
340 }
341 
mouseMovePointDel(const QPointF & pt)342 void COverlayRefMap::mouseMovePointDel(const QPointF& pt)
343 {
344     ptFocus1 = isCloseTo(pt);
345 }
346 
mouseMovePointMove(const QPointF & pt)347 void COverlayRefMap::mouseMovePointMove(const QPointF& pt)
348 {
349     if(movePoint)
350     {
351         ptFocus2 = pt;
352     }
353     else
354     {
355         ptFocus1 = isCloseTo(pt);
356     }
357 }
358 
mouseReleasePointAdd(const QPointF & pt,Qt::MouseButton button)359 void COverlayRefMap::mouseReleasePointAdd(const QPointF& pt, Qt::MouseButton button)
360 {
361     if(button == Qt::LeftButton)
362     {
363         QPointF ptPtx = pt;
364         QPointF ptRef = NOPOINTF;
365         // ask for coordinate
366         CDialogRefPoint dlg(ptPtx, ptRef, this);
367         int res = dlg.exec();
368         if(res == QDialog::Accepted)
369         {
370             new COverlayRefMapPoint(treeWidget->topLevelItemCount() + 1, ptRef, ptPtx, treeWidget);
371             emit sigChanged();
372         }
373     }
374     else if(button == Qt::RightButton)
375     {
376         abortStep();
377         toolNone->click();
378         CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointAdd");
379     }
380 }
381 
mouseReleasePointDel(const QPointF & pt,Qt::MouseButton button)382 void COverlayRefMap::mouseReleasePointDel(const QPointF& pt, Qt::MouseButton button)
383 {
384     if(button == Qt::LeftButton)
385     {
386         if(ptFocus1 == NOPOINTF)
387         {
388             return;
389         }
390 
391         const int N = treeWidget->topLevelItemCount();
392         for(int n = 0; n < N; n++)
393         {
394             COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
395             if(item == nullptr)
396             {
397                 continue;
398             }
399 
400             if(item->getPtPtx() == ptFocus1)
401             {
402                 delete item;
403                 abortStep();
404                 emit sigChanged();
405                 return;
406             }
407         }
408     }
409     else if(button == Qt::RightButton)
410     {
411         CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointDel");
412         toolNone->click();
413         abortStep();
414     }
415 }
416 
mouseReleasePointMove(const QPointF & pt,Qt::MouseButton button)417 void COverlayRefMap::mouseReleasePointMove(const QPointF& pt, Qt::MouseButton button)
418 {
419     if(button == Qt::LeftButton)
420     {
421         if(movePoint)
422         {
423             const int N = treeWidget->topLevelItemCount();
424             for(int n = 0; n < N; n++)
425             {
426                 COverlayRefMapPoint* item = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
427                 if(item == nullptr)
428                 {
429                     continue;
430                 }
431 
432                 if(item->getPtPtx() == ptFocus1)
433                 {
434                     item->setPtPtx(pt);
435                     break;
436                 }
437             }
438 
439             switch(mode)
440             {
441             case eModePointMove:
442             {
443                 abortStep();
444                 CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointMove");
445                 break;
446             }
447 
448             case eModePointMoveAuto:
449             {
450                 int idx = treeWidget->indexOfTopLevelItem(treeWidget->currentItem()) + 1;
451                 if(idx >= treeWidget->topLevelItemCount())
452                 {
453                     abortStep();
454                     CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointMove");
455                 }
456                 else
457                 {
458                     COverlayRefMapPoint* point = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(idx));
459                     if(point == nullptr)
460                     {
461                         return;
462                     }
463                     treeWidget->setCurrentItem(point);
464                     treeWidget->scrollToItem(point);
465 
466                     QPointF pt1 = point->getPtPtx();
467                     ptFocus1 = pt1;
468                     ptFocus2 = pt;
469                     context->convertMap2Screen(pt1);
470 
471                     QPointF pt2 = context->getCanvas()->rect().center();
472                     context->move(pt2 - pt1);
473                     context->triggerCompleteUpdate(CCanvas::eRedrawAll);
474                 }
475                 break;
476             }
477             }
478         }
479         else
480         {
481             if(ptFocus1 != NOPOINTF)
482             {
483                 ptFocus2 = pt;
484                 movePoint = true;
485                 CCanvas::setOverrideCursor(Qt::BlankCursor, "CRefMapGrid::mouseReleasePointMove");
486             }
487         }
488     }
489     else if(button == Qt::RightButton)
490     {
491         if(!movePoint)
492         {
493             toolNone->click();
494         }
495         abortStep();
496         CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointMove");
497     }
498 }
499 
500 
keyPressEventFx(QKeyEvent * e)501 bool COverlayRefMap::keyPressEventFx(QKeyEvent* e)
502 {
503     QTreeWidgetItem* item = treeWidget->currentItem();
504     if(item == nullptr)
505     {
506         return false;
507     }
508 
509     int idx = treeWidget->indexOfTopLevelItem(item);
510 
511     switch(e->key())
512     {
513     case Qt::Key_N:
514     {
515         ++idx;
516         idx = qMin(idx, treeWidget->topLevelItemCount() - 1);
517         break;
518     }
519 
520     case Qt::Key_B:
521     {
522         --idx;
523         idx = qMax(idx, 0);
524         break;
525     }
526 
527     default:
528         return false;
529     }
530 
531 
532     if(movePoint)
533     {
534         switch(mode)
535         {
536         case eModePointMove:
537             return false;
538 
539         case eModePointMoveAuto:
540             abortStep();
541             CCanvas::restoreOverrideCursor("CRefMapGrid::mouseReleasePointMove");
542             break;
543         }
544     }
545 
546     COverlayRefMapPoint* point = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(idx));
547     if(point == nullptr)
548     {
549         return false;
550     }
551     treeWidget->setCurrentItem(point);
552     treeWidget->scrollToItem(point);
553 
554     QPointF pt1 = point->getPtPtx();
555     QPointF pt2 = context->getCanvas()->rect().center();
556     context->convertMap2Screen(pt1);
557     context->move(pt2 - pt1);
558 
559     context->triggerCompleteUpdate(CCanvas::eRedrawAll);
560 
561     return true;
562 }
563 
getCursorFx()564 QCursor COverlayRefMap::getCursorFx()
565 {
566     switch(mode)
567     {
568     case COverlayRefMap::eModePointAdd:
569         return Qt::BlankCursor;
570 
571     case COverlayRefMap::eModePointDel:
572         return QCursor(QPixmap(":/cursors/cursorPointDel.png"), 0, 0);
573 
574     case COverlayRefMap::eModePointMoveAuto:
575     case COverlayRefMap::eModePointMove:
576         return QCursor(QPixmap(":/cursors/cursorPointMove.png"), 0, 0);
577     }
578 
579     return Qt::ArrowCursor;
580 }
581 
updateGui()582 void COverlayRefMap::updateGui()
583 {
584     bool isEmpty = treeWidget->topLevelItemCount() == 0;
585     toolRefDel->setDisabled(isEmpty);
586     toolRefMove->setDisabled(isEmpty);
587     toolRefDelAll->setDisabled(isEmpty);
588     toolRefMoveAuto->setDisabled(isEmpty);
589     toolSaveGcp->setDisabled(isEmpty);
590 }
591 
abortStep()592 void COverlayRefMap::abortStep()
593 {
594     movePoint = false;
595     ptFocus1 = NOPOINTF;
596     ptFocus2 = NOPOINTF;
597 
598     context->triggerCompleteUpdate(CCanvas::eRedrawOverlay);
599 }
600 
slotSetMode(mode_e m,bool on)601 void COverlayRefMap::slotSetMode(mode_e m, bool on)
602 {
603     if(on)
604     {
605         mode = m;
606     }
607 }
608 
slotSaveGcp()609 void COverlayRefMap::slotSaveGcp()
610 {
611     SETTINGS;
612     QString path = cfg.value("Path/gcpInput", QDir::homePath()).toString();
613 
614     QString filename = QFileDialog::getSaveFileName(0, tr("Save reference points..."), path + "/" + gcpFilename, "Ref. points (*.gcp)");
615     if(filename.isEmpty())
616     {
617         return;
618     }
619     cfg.setValue("Path/gcpInput", QFileInfo(filename).absolutePath());
620 
621     gcpFilename = filename;
622 
623     QFile file(filename);
624     file.open(QIODevice::WriteOnly);
625     QTextStream out(&file);
626     out.setRealNumberPrecision(10);
627 
628     out << "#V1.0" << endl;
629     out << "#gcpproj: +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" << endl;
630 
631     const int N = treeWidget->topLevelItemCount();
632     for(int n = 0; n < N; n++)
633     {
634         COverlayRefMapPoint* pt = dynamic_cast<COverlayRefMapPoint*>(treeWidget->topLevelItem(n));
635         if(pt == nullptr)
636         {
637             continue;
638         }
639         const QPointF& ptx = pt->getPtPtx();
640         const QPointF& ref = pt->getPtRef();
641 
642         out << "-gcp " << ptx.x() << " " << ptx.y() << " " << ref.y() << " " << ref.x() << endl;
643     }
644 
645     file.close();
646 }
647 
slotLoadGcp()648 void COverlayRefMap::slotLoadGcp()
649 {
650     SETTINGS;
651     QString path = cfg.value("Path/gcpInput", QDir::homePath()).toString();
652 
653     QString filename = QFileDialog::getOpenFileName(0, tr("Load reference points..."), path, "Ref. points (*.gcp)");
654     if(filename.isEmpty())
655     {
656         return;
657     }
658     cfg.setValue("Path/gcpInput", QFileInfo(filename).absolutePath());
659 
660     QFile file(filename);
661     file.open(QIODevice::ReadOnly);
662     QString line = file.readLine();
663     if(line.trimmed() == "#V1.0")
664     {
665         QRegExp re1("^-gcp\\s(-{0,1}[0-9]+)\\s(-{0,1}[0-9]+)\\s(-{0,1}[0-9\\.]+)\\s(-{0,1}[0-9\\.]+).*$");
666 
667         qint32 cnt = 1;
668         while(1)
669         {
670             if(re1.exactMatch(line))
671             {
672                 QPointF ptPtx(re1.cap(1).toDouble(), re1.cap(2).toDouble());
673                 QPointF ptRef(re1.cap(4).toDouble(), re1.cap(3).toDouble());
674                 new COverlayRefMapPoint(cnt++, ptRef, ptPtx, treeWidget);
675             }
676 
677             if (file.atEnd())
678             {
679                 break;
680             }
681             line = file.readLine();
682         }
683     }
684 
685     updateGui();
686 
687     emit sigChanged();
688 }
689 
slotResetRef()690 void COverlayRefMap::slotResetRef()
691 {
692     int res = QMessageBox::question(this, tr("Delete all reference points..."), tr("Are you sure to delete all reference points in the list?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
693     if(res != QMessageBox::Yes)
694     {
695         return;
696     }
697     treeWidget->clear();
698     updateGui();
699 
700     emit sigChanged();
701 }
702 
slotProjWizard()703 void COverlayRefMap::slotProjWizard()
704 {
705     CProjWizard dlg(*lineProjection, this);
706     dlg.exec();
707     lineProjection->setCursorPosition(0);
708 
709     emit sigChanged();
710 }
711 
slotGridTool()712 void COverlayRefMap::slotGridTool()
713 {
714     CMainWindow::self().startGridTool(item);
715 }
716 
slotSelectionChanged()717 void COverlayRefMap::slotSelectionChanged()
718 {
719     context->triggerCompleteUpdate(CCanvas::eRedrawOverlay);
720 }
721 
slotDelRefPoints()722 void COverlayRefMap::slotDelRefPoints()
723 {
724     const QList<QTreeWidgetItem*>items = treeWidget->selectedItems();
725     if(items.count() > 1)
726     {
727         int res = QMessageBox::question(this, tr("Delete..."), tr("Delete all selected reference points?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
728         if(res != QMessageBox::Yes)
729         {
730             return;
731         }
732     }
733 
734     qDeleteAll(items);
735 
736     emit sigChanged();
737 }
738 
isOk() const739 bool COverlayRefMap::isOk() const
740 {
741     bool ok = true;
742     ok &= (treeWidget->topLevelItemCount() > 2);
743     ok &= CProjWizard::validProjStr(lineProjection->text());
744     return ok;
745 }
746