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