Qt Virtual Chart Table (QVCT)
CChartTable.cpp
Go to the documentation of this file.
1 // INDENTING (emacs/vi): -*- mode:c++; tab-width:2; c-basic-offset:2; intent-tabs-mode:nil; -*- ex: set tabstop=2 expandtab:
2 
3 /*
4  * Qt Virtual Chart Table (QVCT)
5  * Copyright (C) 2012 Cedric Dufour <http://cedric.dufour.name>
6  * Author: Cedric Dufour <http://cedric.dufour.name>
7  *
8  * The Qt Virtual Chart Table (QVCT) is free software:
9  * you can redistribute it and/or modify it under the terms of the GNU General
10  * Public License as published by the Free Software Foundation, Version 3.
11  *
12  * The Qt Virtual Chart Table (QVCT) is distributed in the hope
13  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
14  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  *
16  * See the GNU General Public License for more details.
17  */
18 
19 // C/C++
20 #include <cmath>
21 
22 // QT
23 #include <QDialog>
24 #include <QDomDocument> // QtXml module
25 #include <QFileInfo>
26 #include <QGesture>
27 #include <QGestureEvent>
28 #include <QKeyEvent>
29 #include <QMessageBox>
30 #include <QMouseEvent>
31 #include <QPinchGesture>
32 #include <QPrinter>
33 #include <QPrintDialog>
34 #include <QRect>
35 #include <QTabBar>
36 #include <QTabWidget>
37 #include <QWheelEvent>
38 #include <QWidget>
39 #include <QXmlStreamWriter>
40 
41 // QVCT
42 #include "QVCTRuntime.hpp"
43 #include "charts/CChart.hpp"
44 #include "charts/CChartControl.hpp"
45 #include "charts/CChartTable.hpp"
51 
52 
53 //------------------------------------------------------------------------------
54 // CONSTRUCTORS / DESTRUCTOR
55 //------------------------------------------------------------------------------
56 
57 CChartTable::CChartTable( QWidget* _pqParent )
58  : QTabWidget( _pqParent )
59  , bProjectModified( false )
60  , oGeoPositionReference()
61  , fdScaleReference( -1.0 )
62  , iDpi( 96 )
63  , bIgnoreUpdate( true )
64  , bMousePressed( false )
65  , bMouseDrag( false )
66  , fdGestureTimeLast( 0.0 )
67  , fdGestureZoomReference( 0.0 )
68  , bPointerTarget( false )
69  , bPointerPath( false )
70  , bPointerPathSingle( false )
71  , poOverlayPointMove( 0 )
72  , poVesselPointSynchronize( 0 )
73 {
75  QWidget::setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
76  tabBar()->installEventFilter( this );
77 
79 }
80 
82 {
83  QTabWidget::setTabPosition( QTabWidget::South );
84  QTabWidget::setMovable( true );
85  QTabWidget::setTabsClosable( true );
86  QTabWidget::setUsesScrollButtons( true );
87  QTabWidget::setElideMode( Qt::ElideLeft );
88  connect( tabBar(), SIGNAL( tabCloseRequested(int) ), this, SLOT( slotCloseTab(int) ) );
89  connect( tabBar(), SIGNAL( currentChanged(int) ), this, SLOT( slotChangeTab(int) ) );
90 }
91 
92 
93 //------------------------------------------------------------------------------
94 // METHODS: QWidget (override)
95 //------------------------------------------------------------------------------
96 
97 QSize CChartTable::sizeHint() const
98 {
99  return QVCTRuntime::useMainWindow()->size();
100 }
101 
102 
103 //------------------------------------------------------------------------------
104 // METHODS: QTabWidget (override)
105 //------------------------------------------------------------------------------
106 
107 bool CChartTable::eventFilter( QObject* _pqObject, QEvent* _pqEvent )
108 {
109  //qDebug( "DEBUG[%s] %d", Q_FUNC_INFO, _pqEvent->type() );
110  switch( _pqEvent->type() )
111  {
112 
113  case QEvent::KeyPress:
114  return handlerKeyEvent( static_cast<QKeyEvent *>(_pqEvent) );
115 
116  case QEvent::Wheel:
117  if( _pqObject == tabBar() ) return false;
118  return handlerWheelEvent( static_cast<QWheelEvent *>(_pqEvent) );
119 
120  case QEvent::MouseButtonDblClick:
121  case QEvent::MouseButtonPress:
122  case QEvent::MouseButtonRelease:
123  case QEvent::MouseMove:
124  if( _pqObject != (QObject*)QTabWidget::currentWidget() ) return false;
125  if( microtime() - fdGestureTimeLast < 0.350 ) return false; // Ongoing gestures tend to send QMouseEvent artefacts; let's get rid of those
126  return handlerMouseEvent( static_cast<QMouseEvent *>(_pqEvent) );
127 
128  case QEvent::Gesture:
129  if( _pqObject != (QObject*)QTabWidget::currentWidget() ) return false;
131  return handlerGestureEvent( static_cast<QGestureEvent *>(_pqEvent) );
132 
133  default:; // Ignore other events
134 
135  }
136  return QTabWidget::eventFilter( _pqObject, _pqEvent );
137 }
138 
139 
140 //------------------------------------------------------------------------------
141 // METHODS
142 //------------------------------------------------------------------------------
143 
144 //
145 // SLOTS
146 //
147 
149 {
150  if( bProjectModified && !QVCTRuntime::useMainWindow()->deleteConfirm( tr("Unsaved project data") ) ) return;
151  QString __qsFilename = QVCTRuntime::useMainWindow()->fileDialog( QVCT::OPEN, tr("Load Project"), tr("QVCT Files")+" (*.qvct)" );
152  if( __qsFilename.isEmpty() ) return;
153  if( !QVCTRuntime::useMainWindow()->fileCheck( QVCT::OPEN, __qsFilename ) ) return;
154  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
155  __pqMutexDataChange->lock();
156  clear();
157  __pqMutexDataChange->unlock();
158  load( __qsFilename );
159  updateChart();
160  bProjectModified = false;
161 }
162 
164 {
165  QString __qsFilename = QVCTRuntime::useMainWindow()->fileDialog( QVCT::SAVE, tr("Save Project"), tr("QVCT Files")+" (*.qvct)" );
166  if( __qsFilename.isEmpty() ) return;
167  QFileInfo __qFileInfo( __qsFilename );
168  if( __qFileInfo.suffix().isEmpty() ) __qsFilename += ".qvct";
169  if( !QVCTRuntime::useMainWindow()->fileCheck( QVCT::SAVE, __qsFilename ) ) return;
170  save( __qsFilename );
171  bProjectModified = false;
172 }
173 
175 {
176  QString __qsFilename = QVCTRuntime::useMainWindow()->fileDialog( QVCT::OPEN, tr("Load Chart"), tr("GeoTIFF Files")+" (*.tif *.tiff)" );
177  if( __qsFilename.isEmpty() ) return;
178  if( !QVCTRuntime::useMainWindow()->fileCheck( QVCT::OPEN, __qsFilename ) ) return;
179  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
180  __pqMutexDataChange->lock();
181  CChart* __poChart = loadChart( __qsFilename );
182  __pqMutexDataChange->unlock();
183  if( !__poChart )
184  {
185  QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, __qsFilename );
186  return;
187  }
188  bProjectModified = true;
189 }
190 
192 {
193  if( QTabWidget::currentIndex() < 0 ) return;
194  bool __bPrintHighRes = QVCTRuntime::useSettings()->isPrintHighRes();
195  if( __bPrintHighRes
196  && QMessageBox::warning( 0, tr("WARNING"),
197  tr("High-resolution printing is enabled!\nPrinting may take several seconds, during which the application will appear frozen.\nDo you want to proceed?"),
198  QMessageBox::Cancel|QMessageBox::Ok, QMessageBox::Cancel ) != QMessageBox::Ok ) return;
199  QPrinter __qPrinter( __bPrintHighRes ? QPrinter::HighResolution : QPrinter::ScreenResolution );
200  // QPrinter __qPrinter;
201  QPrintDialog* __pqPrintDialog = new QPrintDialog( &__qPrinter );
202  __pqPrintDialog->addEnabledOption( QAbstractPrintDialog::PrintToFile );
203  int __iResult = __pqPrintDialog->exec();
204  delete __pqPrintDialog;
205  if( __iResult != QDialog::Accepted ) return;
206 
207  // Print
208  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
209  __pqMutexDataChange->lock();
210  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
211  // ... set draw area, zoom and DPI to printer's
212  double __fdZoomScreen = __poChart->getZoom();
213  CDataPosition oGeoPositionLower = __poChart->toGeoPosition( __poChart->getDrawArea().bottomLeft() );
214  CDataPosition oGeoPositionUpper = __poChart->toGeoPosition( __poChart->getDrawArea().topRight() );
215  iDpi = ( __qPrinter.paperRect( QPrinter::DevicePixel ).width() / __qPrinter.paperRect( QPrinter::Inch ).width() );
216  __poChart->setDrawArea( QRectF( 0, 0, __qPrinter.pageRect( QPrinter::DevicePixel ).width(), __qPrinter.pageRect( QPrinter::DevicePixel ).height() ) );
217  __poChart->setZoom( __poChart->getZoomArea( oGeoPositionLower, oGeoPositionUpper ) );
218  // ... print
219  __poChart->print( &__qPrinter );
220  // ... set draw area, zoom and DPI back to screen's
222  __poChart->resetDrawArea();
223  __poChart->setZoom( __fdZoomScreen );
224  __pqMutexDataChange->unlock();
225 }
226 
228 {
229  if( QTabWidget::currentIndex() < 0 ) return;
230  QString __qsFilename = QVCTRuntime::useMainWindow()->fileDialog( QVCT::OPEN, tr("Add Elevation Data"), tr("GeoTIFF Files")+" (*.tif *.tiff)" );
231  if( __qsFilename.isEmpty() ) return;
232  if( !QVCTRuntime::useMainWindow()->fileCheck( QVCT::OPEN, __qsFilename ) ) return;
233  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
234  __pqMutexDataChange->lock();
235  addElevation( __qsFilename );
236  __pqMutexDataChange->unlock();
237  if( !hasElevation() )
238  {
239  QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, __qsFilename );
240  return;
241  }
242  bProjectModified = true;
243 }
244 
245 void CChartTable::slotChangeTab( int _iTabIndex )
246 {
247  CChartControl* __poChartControl = QVCTRuntime::useChartControl();
248  bIgnoreUpdate = true;
249  if( _iTabIndex < 0 )
250  {
251  __poChartControl->enableControls( false );
252  }
253  else
254  {
255  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
256  __poChartControl->lockPosition( __poChart->isPositionLocked() );
257  __poChartControl->lockScale( __poChart->isZoomLocked() );
258  __poChartControl->setScale( toScale( __poChart->getZoom(), __poChart ) );
259  __poChartControl->setElevation( __poChart->hasElevation(), __poChart->isElevationShowed() );
260  __poChartControl->enableControls( true );
261  bIgnoreUpdate = false;
262  }
263 }
264 
266 {
267  int __iTabIndex = QTabWidget::currentIndex();
268  if( __iTabIndex >= 0 ) removeTab( __iTabIndex );
269  bProjectModified = true;
270 }
271 
272 void CChartTable::slotCloseTab( int _iTabIndex )
273 {
274  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
275  __pqMutexDataChange->lock();
276  CChart* __poChart = (CChart*)widget( _iTabIndex );
277  removeTab( _iTabIndex );
278  delete __poChart;
279  if( QTabWidget::currentIndex() < 0 )
280  {
282  fdScaleReference = -1.0;
283  }
284  __pqMutexDataChange->unlock();
285  bProjectModified = true;
286 }
287 
289 {
290  if( bIgnoreUpdate ) return;
291  setScaleActual();
292  updateChart();
293 }
294 
296 {
297  if( bIgnoreUpdate ) return;
298  setScaleFit();
299  updateChart();
300 }
301 
302 void CChartTable::slotPointerTarget( bool _bEnable )
303 {
304  if( bIgnoreUpdate ) return;
305  enablePointerTarget( _bEnable );
307  updateChart();
308 }
309 
310 void CChartTable::slotPointerPath( bool _bEnable )
311 {
312  if( bIgnoreUpdate ) return;
313  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
314  __pqMutexDataChange->lock();
315  enablePointerPath( _bEnable );
316  __pqMutexDataChange->unlock();
318  updateChart();
319 }
320 
322 {
323  if( bIgnoreUpdate ) return;
324  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
325  __pqMutexDataChange->lock();
326  enablePointerPathSingle( _bEnable );
327  __pqMutexDataChange->unlock();
329  updateChart();
330 }
331 
332 void CChartTable::slotVesselPointDestroyed( QObject* _pqObject )
333 {
334  if( !_pqObject || (QObject*)poVesselPointSynchronize != _pqObject ) return;
337  updateChart();
338 }
339 
340 //
341 // HANDLERS
342 //
343 
344 bool CChartTable::handlerKeyEvent( QKeyEvent* _pqKeyEvent )
345 {
346  if( QTabWidget::currentIndex() < 0 ) return false;
347  bool __bReturn = false;
348  bool __bControlKey = _pqKeyEvent->modifiers() & Qt::ControlModifier;
349  switch( _pqKeyEvent->key() )
350  {
351  // Position
352  case Qt::Key_Home: setPositionHome(); __bReturn = true; break;
353  case Qt::Key_Up: stepScrPosition( false, false, __bControlKey ); __bReturn = true; break;
354  case Qt::Key_Right: stepScrPosition( true, true, __bControlKey ); __bReturn = true; break;
355  case Qt::Key_Down: stepScrPosition( false, true, __bControlKey ); __bReturn = true; break;
356  case Qt::Key_Left: stepScrPosition( true, false, __bControlKey ); __bReturn = true; break;
357  // Scale
358  case Qt::Key_Plus: stepScale( true, __bControlKey ); __bReturn = true; break;
359  case Qt::Key_Minus: stepScale( false, __bControlKey ); __bReturn = true; break;
360  case Qt::Key_Asterisk: setScaleActual(); __bReturn = true; break;
361  case Qt::Key_Slash: setScaleFit(); __bReturn = true; break;
362  default:;
363  }
364  return __bReturn;
365 }
366 
367 bool CChartTable::handlerMouseEvent( QMouseEvent* _pqMouseEvent )
368 {
369  if( QTabWidget::currentIndex() < 0 ) return false;
370 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
371  QPointF __qPointFMouse = _pqMouseEvent->localPos();
372 #else
373  QPointF __qPointFMouse = _pqMouseEvent->posF();
374 #endif
375  int __iMouseButton = _pqMouseEvent->button();
376  switch( _pqMouseEvent->type() )
377  {
378 
379  case QEvent::MouseButtonDblClick:
380  switch( __iMouseButton )
381  {
382  case Qt::LeftButton:
383  {
384  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
385  CVesselPoint* __poVesselPoint = (CVesselPoint*)QVCTRuntime::useVesselOverlay()->matchScrPosition( __poChart, __qPointFMouse );
386  if( __poVesselPoint ) { __poVesselPoint->toggleMultiSelected(); break; }
387  CTrackPoint* __poTrackPoint = (CTrackPoint*)QVCTRuntime::useTrackOverlay()->matchScrPosition( __poChart, __qPointFMouse );
388  if( __poTrackPoint ) { __poTrackPoint->toggleMultiSelected(); break; }
389  CRoutePoint* __poRoutePoint = (CRoutePoint*)QVCTRuntime::useRouteOverlay()->matchScrPosition( __poChart, __qPointFMouse );
390  if( __poRoutePoint ) { __poRoutePoint->toggleMultiSelected(); break; }
391  CLandmarkPoint* __poLandmarkPoint = (CLandmarkPoint*)QVCTRuntime::useLandmarkOverlay()->matchScrPosition( __poChart, __qPointFMouse );
392  if( __poLandmarkPoint ) { __poLandmarkPoint->toggleMultiSelected(); break; }
393  }
394  setScaleActual();
395  updateChart();
396  break;
397  case Qt::RightButton:
398  setScaleActual();
399  updateChart();
400  break;
401  default:; // we don't care about other buttons
402  }
403  break;
404 
405  case QEvent::MouseButtonPress:
406  switch( __iMouseButton )
407  {
408  case Qt::LeftButton:
409  bMousePressed = true;
410  qPointFMouse = __qPointFMouse;
411  break;
412  case Qt::RightButton:
413  {
414  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
415  setGeoPosition( __poChart->toGeoPosition( __qPointFMouse ) );
416  updateChart();
417  }
418  break;
419  default:; // we don't care about other buttons
420  }
421  break;
422 
423  case QEvent::MouseButtonRelease:
424  if( __iMouseButton == Qt::LeftButton )
425  {
426  bMousePressed = false;
427  if( bMouseDrag )
428  {
429  bMouseDrag = false;
430  dragScrPosition( __qPointFMouse - qPointFMouse );
431  updateChart();
432  }
433  else
434  {
435  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
436 
437  // Match mouse position with overlays' item
438  CPointerOverlay* __poPointerOverlay = QVCTRuntime::usePointerOverlay();
439  CPointerPoint* __poPointerPoint = __poPointerOverlay->usePointerPoint();
440  bool __bPointerTargetPending = bPointerTarget ? __poPointerOverlay->usePointerTarget()->CDataPosition::operator==( CDataPosition::UNDEFINED ) : false;
441  CDataPosition __oGeoPosition;
442  do
443  {
444  __poPointerPoint->resetPosition();
445  __poPointerOverlay->forceRedraw();
446  if( !poOverlayPointMove )
447  {
448 
449  // ... vessel
450  CVesselOverlay* __poVesselOverlay = QVCTRuntime::useVesselOverlay();
451  CVesselPoint* __poVesselPoint = (CVesselPoint*)__poVesselOverlay->matchScrPosition( __poChart, __qPointFMouse );
452  if( __poVesselPoint )
453  {
454  __oGeoPosition = *__poVesselPoint;
455  if( __bPointerTargetPending || bPointerPath || bPointerPathSingle ) break;
456  __poVesselOverlay->setCurrentItem( __poVesselPoint );
457  __poVesselPoint->showDetail();
458  break;
459  }
460 
461  // ... track
462  CTrackOverlay* __poTrackOverlay = QVCTRuntime::useTrackOverlay();
463  CTrackPoint* __poTrackPoint = (CTrackPoint*)__poTrackOverlay->matchScrPosition( __poChart, __qPointFMouse );
464  if( __poTrackPoint )
465  {
466  __oGeoPosition = *__poTrackPoint;
467  if( __bPointerTargetPending || bPointerPath || bPointerPathSingle ) break;
468  __poTrackOverlay->setCurrentItem( __poTrackPoint );
469  __poTrackPoint->showDetail();
470  break;
471  }
472 
473  // ... route
474  CRouteOverlay* __poRouteOverlay = QVCTRuntime::useRouteOverlay();
475  CRoutePoint* __poRoutePoint = (CRoutePoint*)__poRouteOverlay->matchScrPosition( __poChart, __qPointFMouse );
476  if( __poRoutePoint )
477  {
478  __oGeoPosition = *__poRoutePoint;
479  if( __bPointerTargetPending || bPointerPath || bPointerPathSingle ) break;
480  __poRouteOverlay->setCurrentItem( __poRoutePoint );
481  __poRoutePoint->showDetail();
482  break;
483  }
484 
485  // ... landmark
486  CLandmarkOverlay* __poLandmarkOverlay = QVCTRuntime::useLandmarkOverlay();
487  CLandmarkPoint* __poLandmarkPoint = (CLandmarkPoint*)__poLandmarkOverlay->matchScrPosition( __poChart, __qPointFMouse );
488  if( __poLandmarkPoint )
489  {
490  __oGeoPosition = *__poLandmarkPoint;
491  if( __bPointerTargetPending || bPointerPath || bPointerPathSingle ) break;
492  __poLandmarkOverlay->setCurrentItem( __poLandmarkPoint );
493  __poLandmarkPoint->showDetail();
494  break;
495  }
496 
497  }
498 
499  // ... pointer
500  __oGeoPosition = __poChart->toGeoPosition( __qPointFMouse );
501  if( poOverlayPointMove || __bPointerTargetPending ) break;
502  __poPointerPoint->setPosition( __oGeoPosition );
503  __poPointerOverlay->showDetail( __poPointerOverlay->usePointerPoint() );
504  __poPointerOverlay->forceRedraw();
505  __poChart->update();
506 
507  }
508  while( false );
509 
510  // Overlay point move
511  if( poOverlayPointMove )
512  {
516  __poChart->update();
517  break;
518  }
519 
520  // Set pointer target
521  if( setPointerTarget( __oGeoPosition ) ) break;
522 
523  // Extend pointer path
524  if( extendPointerPath( __oGeoPosition ) ) break;
525 
526  }
527  }
528  break;
529 
530  case QEvent::MouseMove:
531  if( bMouseDrag )
532  {
533  dragScrPosition( qPointFMouse - __qPointFMouse );
534  updateChart();
535  qPointFMouse = __qPointFMouse;
536  }
537  else if( bMousePressed )
538  {
539  QPointF __qPointFDelta = __qPointFMouse - qPointFMouse;
540  if( __qPointFDelta.x()*__qPointFDelta.x() + __qPointFDelta.y()*__qPointFDelta.y() > 100 ) bMouseDrag = true;
541  }
542  break;
543 
544  default: return false; // Other events don't get here but better safe than sorry
545 
546  }
547  return true;
548 }
549 
550 bool CChartTable::handlerWheelEvent( QWheelEvent* _pqWheelEvent )
551 {
552  if( QTabWidget::currentIndex() < 0 ) return false;
553 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
554  int __iMouseDelta = _pqWheelEvent->angleDelta().y() / 120;
555 #else
556  int __iMouseDelta = _pqWheelEvent->delta() / 120;
557 #endif
558  if( !__iMouseDelta ) return true;
559  bool __bIncrease = true;
560  if( __iMouseDelta < 0 ) { __bIncrease = false; __iMouseDelta = -__iMouseDelta; }
561  for( int __i=0; __i<__iMouseDelta; __i++ ) stepScale( __bIncrease, true );
562  updateChart();
563  return true;
564 }
565 
566 bool CChartTable::handlerGestureEvent( QGestureEvent* _pqGestureEvent )
567 {
568  if( QTabWidget::currentIndex() < 0 ) return false;
569  bool __bReturn = false;
570  QGesture* __pqGesture = _pqGestureEvent->gesture( Qt::PinchGesture );
571  if( __pqGesture )
572  {
573  // NOTE: To provide a good "user experience", we must use the underlying
574  // chart's linear zoom factor rather than the UI's logarithmic scale
575  // factor.
576  QPinchGesture* __pqPinchGesture = static_cast<QPinchGesture *>(__pqGesture);
577  switch( __pqPinchGesture->state() )
578  {
579 
580  case Qt::GestureStarted:
581  __pqPinchGesture->setGestureCancelPolicy( QGesture::CancelAllInContext );
582  _pqGestureEvent->accept( __pqPinchGesture );
583  fdGestureZoomReference = ((CChart*)QTabWidget::currentWidget())->getZoom();
584  break;
585 
586  case Qt::GestureUpdated:
587  case Qt::GestureFinished:
588  if( __pqPinchGesture->changeFlags() & QPinchGesture::ScaleFactorChanged )
589  {
590  setZoom( fdGestureZoomReference * __pqPinchGesture->totalScaleFactor() );
591  updateChart();
592  }
593  break;
594 
595  default:;
596 
597  }
598  __bReturn = true;
599  }
600  return __bReturn;
601 }
602 
603 
604 //
605 // SETTERS
606 //
607 
608 void CChartTable::setGeoPosition( const CDataPosition& _roGeoPosition, bool _bSkipCurrent )
609 {
610  if( bIgnoreUpdate || count() < 1 ) return;
611  int __iWidgetCurrentIndex = QTabWidget::currentIndex();
612  bool __bLocked = ((CChart*)QTabWidget::currentWidget())->isPositionLocked();
613  if( __bLocked ) oGeoPositionReference = _roGeoPosition;
614  for( int __iWidgetIndex = count() - 1; __iWidgetIndex >= 0; __iWidgetIndex-- )
615  {
616  CChart* __poChart = (CChart*)widget( __iWidgetIndex );
617  if( __iWidgetIndex != __iWidgetCurrentIndex && __bLocked && __poChart->isPositionLocked() )
618  {
619  __poChart->setGeoPosition( _roGeoPosition );
620  }
621  if( __iWidgetIndex == __iWidgetCurrentIndex && !_bSkipCurrent )
622  {
623  __poChart->setGeoPosition( _roGeoPosition );
624  }
625  }
626 }
627 
628 void CChartTable::showGeoPosition( const CDataPosition& _roGeoPosition )
629 {
630  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
631  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
632  if( !__poChart->getDrawArea().contains( __poChart->toDrawPosition( _roGeoPosition ).toPoint() ) )
633  __poChart->setGeoPosition( _roGeoPosition );
634 }
635 
636 void CChartTable::stepScrPosition( bool _bHorizontal, bool _bIncrease, bool _bBigStep )
637 {
638  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
639  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
640  int __iXOffset = _bHorizontal ? ( _bIncrease ? 1 : -1 ) * ( _bBigStep ? __poChart->getDrawArea().width()/5 : __poChart->getDrawArea().width()/50 ) : 0;
641  int __iYOffset = !_bHorizontal ? ( _bIncrease ? 1 : -1 ) * ( _bBigStep ? __poChart->getDrawArea().height()/5 : __poChart->getDrawArea().height()/50 ) : 0;
642  dragScrPosition( QPoint( __iXOffset, __iYOffset ) );
643 }
644 
645 void CChartTable::dragScrPosition( const QPointF& _rqPointFScrPositionOffset )
646 {
647  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 || _rqPointFScrPositionOffset.isNull() ) return;
648  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
649  /*
650  * NOTE: We do not move the chart by calling this->setGeoPosition directly because it leads
651  * to extra offset artefacts due to the pixel<->geographical position back and forth conversion.
652  * Instead, we move the chart directly by modifying the pixel positon and
653  * update the reference geographical position accordingly.
654  */
655  __poChart->move( _rqPointFScrPositionOffset );
656  // __poChart->update();
657  if( __poChart->isPositionLocked() ) setGeoPosition( __poChart->getGeoPosition(), true );
658 }
659 
661 {
662  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
663  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
664  setGeoPosition( __poChart->getGeoPositionCenter() );
665 }
666 
667 void CChartTable::lockPosition( bool _bLock )
668 {
669  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
670  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
671  if( _bLock ) setGeoPosition( oGeoPositionReference );
672  __poChart->lockPosition( _bLock );
673 }
674 
675 void CChartTable::setScale( double _fdScale, bool _bSkipCurrent, bool _bUpdateControl )
676 {
677  if( bIgnoreUpdate || count() < 1 ) return;
678  //qDebug( "DEBUG[%s] %f", Q_FUNC_INFO, _fdScale );
679  int __iWidgetCurrentIndex = QTabWidget::currentIndex();
680  bool __bLocked = ((CChart*)QTabWidget::currentWidget())->isZoomLocked();
681  if( __bLocked ) fdScaleReference = _fdScale;
682  for( int __iWidgetIndex = count() - 1; __iWidgetIndex >= 0; __iWidgetIndex-- )
683  {
684  CChart* __poChart = (CChart*)widget( __iWidgetIndex );
685  if( __iWidgetIndex != __iWidgetCurrentIndex && __bLocked && __poChart->isZoomLocked() )
686  {
687  __poChart->setZoom( toZoom( _fdScale, __poChart ) );
688  }
689  if( __iWidgetIndex == __iWidgetCurrentIndex && !_bSkipCurrent )
690  {
691  __poChart->setZoom( toZoom( _fdScale, __poChart ) );
692  if( _bUpdateControl ) QVCTRuntime::useChartControl()->setScale( _fdScale );
693  // __poChart->update();
694  }
695  }
696 }
697 
698 void CChartTable::stepScale( bool _bIncrease, bool _bBigStep )
699 {
700  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
701  QVCTRuntime::useChartControl()->stepScale( _bIncrease, _bBigStep );
702 }
703 
705 {
706  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
707  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
708  setScale( toScale( __poChart->getZoomActual(), __poChart ) );
709 }
710 
712 {
713  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
714  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
715  setGeoPosition( __poChart->getGeoPositionCenter() );
716  setScale( toScale( __poChart->getZoomFit(), __poChart ) );
717 }
718 
719 void CChartTable::setScaleArea( const CDataPosition& _roGeoPosition1, const CDataPosition& _roGeoPosition2, double _fdScaleCorrection )
720 {
721  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
722  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
723  setGeoPosition( CDataPosition( ( _roGeoPosition1.getLongitude() + _roGeoPosition2.getLongitude() ) / 2.0, ( _roGeoPosition1.getLatitude() + _roGeoPosition2.getLatitude() ) / 2.0 ) );
724  setScale( toScale( __poChart->getZoomArea( _roGeoPosition1, _roGeoPosition2 ) * _fdScaleCorrection, __poChart ) );
725 }
726 
727 void CChartTable::lockScale( bool _bLock )
728 {
729  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
730  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
731  if( _bLock ) setScale( fdScaleReference );
732  __poChart->lockZoom( _bLock );
733 }
734 
735 void CChartTable::setZoom( double _fdZoom, bool _bSkipCurrent, bool _bUpdateControl )
736 {
737  if( count() < 1 ) return;
738  //qDebug( "DEBUG[%s] %f", Q_FUNC_INFO, _fdZoom );
739  double __fdScale = toScale( _fdZoom );
740  int __iWidgetCurrentIndex = QTabWidget::currentIndex();
741  bool __bLocked = ((CChart*)QTabWidget::currentWidget())->isZoomLocked();
742  if( __bLocked ) fdScaleReference = __fdScale;
743  for( int __iWidgetIndex = count() - 1; __iWidgetIndex >= 0; __iWidgetIndex-- )
744  {
745  CChart* __poChart = (CChart*)widget( __iWidgetIndex );
746  if( __iWidgetIndex != __iWidgetCurrentIndex && __bLocked && __poChart->isZoomLocked() )
747  {
748  __poChart->setZoom( _fdZoom );
749  }
750  if( __iWidgetIndex == __iWidgetCurrentIndex && !_bSkipCurrent )
751  {
752  __poChart->setZoom( _fdZoom );
753  if( _bUpdateControl ) QVCTRuntime::useChartControl()->setScale( __fdScale );
754  // __poChart->update();
755  }
756  }
757 }
758 
759 void CChartTable::enablePointerTarget( bool _bEnable )
760 {
761  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
762  bIgnoreUpdate = true;
763  bPointerTarget = _bEnable;
766  bIgnoreUpdate = false;
767 }
768 
769 bool CChartTable::setPointerTarget( const CDataPosition& _roGeoPosition )
770 {
771  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return false;
772  CPointerOverlay* __poPointerOverlay = QVCTRuntime::usePointerOverlay();
773  if( bPointerTarget && __poPointerOverlay->usePointerTarget()->CDataPosition::operator==( CDataPosition::UNDEFINED ) )
774  {
775  __poPointerOverlay->setPosition( _roGeoPosition, true );
776  __poPointerOverlay->showDetail( __poPointerOverlay->usePointerTarget() );
777  __poPointerOverlay->forceRedraw();
778  ((CChart*)QTabWidget::currentWidget())->update();
779  return true;
780  }
781  return false;
782 }
783 
784 void CChartTable::enablePointerPath( bool _bEnable )
785 {
786  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
787  bIgnoreUpdate = true;
788  bPointerPath = _bEnable;
790  if( !bPointerPath )
791  {
792  if( bPointerPathSingle )
793  {
794  bPointerPathSingle = false;
796  }
799  }
800  bIgnoreUpdate = false;
801 }
802 
804 {
805  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return;
806  bIgnoreUpdate = true;
807  bPointerPathSingle = _bEnable;
809  if( !bPointerPathSingle )
810  {
813  }
814  bIgnoreUpdate = false;
815 }
816 
817 bool CChartTable::extendPointerPath( const CDataPosition& _roGeoPosition )
818 {
819  if( bIgnoreUpdate || QTabWidget::currentIndex() < 0 ) return false;
820  CPointerOverlay* __poPointerOverlay = QVCTRuntime::usePointerOverlay();
822  {
823  if( bPointerPathSingle && __poPointerOverlay->getPathSegments() )
824  {
825  if( !bPointerPath )
826  {
828  return false;
829  }
830  __poPointerOverlay->clearPath();
831  }
832  __poPointerOverlay->setPath( _roGeoPosition );
833  __poPointerOverlay->showDetail( __poPointerOverlay->usePointerPoint() );
834  __poPointerOverlay->forceRedraw();
835  ((CChart*)QTabWidget::currentWidget())->update();
836  return true;
837  }
838  return false;
839 }
840 
842 {
843  bool __bRedraw = poOverlayObjectSelected != _poOverlayObject;
844  poOverlayObjectSelected = _poOverlayObject;
845  if( __bRedraw )
846  {
851  updateChart();
852  }
853 }
854 
856 {
857  poOverlayPointMove = _poOverlayPoint;
859 }
860 
862 {
863  if( poVesselPointSynchronize == _poVesselPoint ) return;
864  poVesselPointSynchronize = _poVesselPoint;
865  QObject::connect( poVesselPointSynchronize, SIGNAL( destroyed(QObject*) ), this, SLOT( slotVesselPointDestroyed(QObject*) ) );
866 }
867 
869 {
870  if( poVesselPointSynchronize ) QObject::disconnect( poVesselPointSynchronize, 0, this, 0 );
872 }
873 
874 //
875 // OTHER
876 //
877 
879 {
880  if( !poVesselPointSynchronize ) return;
882  for( int __i = count() - 1; __i >= 0; __i-- )
883  {
884  CChart* __poChart = (CChart*)widget( __i );
885  if( __poChart->isPositionLocked() ) __poChart->setGeoPosition( oGeoPositionReference );
886  }
887 }
888 
890 {
891  QTabWidget::clear();
897 }
898 
899 void CChartTable::load( const QString& _rqsFilename )
900 {
901  QFileInfo __qFileInfo( _rqsFilename );
902  QString __qsError;
903  do // error-catching context [begin]
904  {
905  // File
906  QFileInfo __qFileInfo( _rqsFilename );
907  QFile __qFile( __qFileInfo.absoluteFilePath() );
908  if( !__qFile.open( QIODevice::ReadOnly ) )
909  {
910  __qsError = QString( "Failed to open file (%1)" ).arg( __qFile.fileName() );
911  break;
912  }
913  QDomDocument __qDocDocument;
914  if( !__qDocDocument.setContent( &__qFile ) )
915  {
916  __qsError = QString( "Failed to parse XML (%1)" ).arg( __qFile.fileName() );
917  __qFile.close();
918  break;
919  }
920  __qFile.close();
921 
922  // XML
923  QDomElement __qDomElement = __qDocDocument.documentElement();
924  QString __qDocType = __qDomElement.nodeName();
925  if( __qDomElement.isNull() || ( __qDocType != "QVCT" ) )
926  {
927  __qsError = QString( "Invalid XML document type (%1); expected: 'QVCT'" ).arg( __qFile.fileName() );
928  break;
929  }
930  // ... settings
931  QVCTRuntime::useSettings()->parseQVCT( __qDomElement );
932  // ... chart table
933  if( parseQVCT( __qDomElement ) )
934  {
935  QTabWidget::setCurrentIndex( 0 );
936  CChartControl* __poChartControl = QVCTRuntime::useChartControl();
937  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
938  bIgnoreUpdate = true;
939  __poChartControl->lockPosition( __poChart->isPositionLocked() );
940  __poChartControl->lockScale( __poChart->isZoomLocked() );
941  __poChartControl->setScale( toScale( __poChart->getZoom(), __poChart ) );
942  __poChartControl->enableControls( true );
943  bIgnoreUpdate = false;
944  }
945  // ... overlays
946  QVCTRuntime::useLandmarkOverlay()->parseQVCT( __qDomElement );
947  QVCTRuntime::useLandmarkOverlay()->QTreeWidgetItem::setExpanded( true );
948  QVCTRuntime::useRouteOverlay()->parseQVCT( __qDomElement );
949  QVCTRuntime::useRouteOverlay()->QTreeWidgetItem::setExpanded( true );
950  QVCTRuntime::useTrackOverlay()->parseQVCT( __qDomElement );
951  QVCTRuntime::useTrackOverlay()->QTreeWidgetItem::setExpanded( true );
952  QVCTRuntime::useVesselOverlay()->parseQVCT( __qDomElement );
953  QVCTRuntime::useVesselOverlay()->QTreeWidgetItem::setExpanded( true );
954  }
955  while( false ); // error-catching context [end]
956  if( !__qsError.isEmpty() )
957  {
958  qCritical( "ERROR[%s]: %s", Q_FUNC_INFO, qPrintable( __qsError ) );
959  QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, _rqsFilename );
960  return;
961  }
962 }
963 
964 void CChartTable::save( const QString& _rqsFilename ) const
965 {
966  QFileInfo __qFileInfo( _rqsFilename );
967  QString __qsFormat = __qFileInfo.suffix();
968  if( __qsFormat != "qvct" )
969  {
970  qCritical( "ERROR[%s]: Invalid file format/extention (%s); expected: 'qvct'", Q_FUNC_INFO, qPrintable( __qsFormat ) );
971  return;
972  }
973 
974  // File [open]
975  QFile __qFile( __qFileInfo.absoluteFilePath() );
976  if( !__qFile.open( QIODevice::WriteOnly ) )
977  {
978  qCritical( "ERROR[%s]: Failed to open file (%s)", Q_FUNC_INFO, qPrintable( __qFile.fileName() ) );
979  return;
980  }
981 
982  // XML [start]
983  QXmlStreamWriter __qXmlStreamWriter( &__qFile );
984  __qXmlStreamWriter.setAutoFormatting( true );
985  __qXmlStreamWriter.writeStartDocument();
986 
987  // Data
988  __qXmlStreamWriter.writeStartElement( "QVCT" );
989  // ... settings
990  QVCTRuntime::useSettings()->dumpQVCT( __qXmlStreamWriter, true );
991  // ... chart table
992  dumpQVCT( __qXmlStreamWriter );
993  // ... overlays
994  QVCTRuntime::useLandmarkOverlay()->dumpQVCT( __qXmlStreamWriter, 0, true );
995  QVCTRuntime::useRouteOverlay()->dumpQVCT( __qXmlStreamWriter, 0, true );
996  QVCTRuntime::useTrackOverlay()->dumpQVCT( __qXmlStreamWriter, 0, true );
997  QVCTRuntime::useVesselOverlay()->dumpQVCT( __qXmlStreamWriter, 0, true );
998  // ... [end]
999  __qXmlStreamWriter.writeEndElement(); // QVCT
1000 
1001  // XML [end]
1002  __qXmlStreamWriter.writeEndDocument();
1003 
1004  // File [close]
1005  __qFile.close();
1006 }
1007 
1008 int CChartTable::parseQVCT( const QDomElement& _rqDomElement )
1009 {
1010  // Chart table
1011  QDomElement __qDomElementChartTable = _rqDomElement.firstChildElement( "ChartTable" );
1012  if( __qDomElementChartTable.isNull() ) return 0;
1013  if( __qDomElementChartTable.hasAttribute( "longitude" ) && __qDomElementChartTable.hasAttribute( "longitude" ) )
1014  {
1015  oGeoPositionReference.setPosition( __qDomElementChartTable.attribute( "longitude" ).toDouble(),
1016  __qDomElementChartTable.attribute( "latitude" ).toDouble() );
1017  }
1018  if( __qDomElementChartTable.hasAttribute( "scale" ) )
1019  fdScaleReference = __qDomElementChartTable.attribute( "scale" ).toDouble();
1020  // ... charts
1021  int __iCount = 0;
1022  for( QDomElement __qDomElementChart = __qDomElementChartTable.firstChildElement( "Chart" );
1023  !__qDomElementChart.isNull();
1024  __qDomElementChart = __qDomElementChart.nextSiblingElement( "Chart" ) )
1025  {
1026  QString __qsFilename = __qDomElementChart.hasAttribute( "file" ) ? __qDomElementChart.attribute( "file" ) : __qDomElementChart.attribute( "raster" );
1027  CChart* __poChart = loadChart( __qsFilename );
1028  if( !__poChart )
1029  {
1030  QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, __qsFilename );
1031  continue;
1032  }
1033  __poChart->parseQVCT( __qDomElementChart );
1034  __iCount++;
1035  }
1036  return __iCount;
1037 }
1038 
1039 void CChartTable::dumpQVCT( QXmlStreamWriter & _rqXmlStreamWriter ) const
1040 {
1041  // Chart table
1042  _rqXmlStreamWriter.writeStartElement( "ChartTable" );
1044  {
1045  _rqXmlStreamWriter.writeAttribute( "longitude", QString::number( oGeoPositionReference.getLongitude() ) );
1046  _rqXmlStreamWriter.writeAttribute( "latitude", QString::number( oGeoPositionReference.getLatitude() ) );
1047  }
1048  if( fdScaleReference >= 0.0 )
1049  _rqXmlStreamWriter.writeAttribute( "scale", QString::number( fdScaleReference ) );
1050  // ... charts
1051  int __iCount = QTabWidget::count();
1052  for( int __i = 0; __i < __iCount; __i++ )
1053  ((CChart*)QTabWidget::widget( __i ))->dumpQVCT( _rqXmlStreamWriter );
1054  // ... [end]
1055  _rqXmlStreamWriter.writeEndElement(); // ChartTable
1056 }
1057 
1058 CChart* CChartTable::loadChart( const QString& _rqsFilename )
1059 {
1060  // Create new chart widget
1061  CChart* __poChart = new CChart( _rqsFilename );
1062  if( __poChart->getStatus() != QVCT::OK )
1063  {
1064  delete __poChart;
1065  return 0;
1066  }
1067 
1068  // Set reference position
1070  else __poChart->setGeoPosition( oGeoPositionReference );
1071 
1072  // Set reference scale factor
1073  if( fdScaleReference < 0 ) fdScaleReference = toScale( __poChart->getZoom(), __poChart );
1074  else __poChart->setZoom( toZoom( fdScaleReference, __poChart ) );
1075 
1076  // Have the chart table manage chart events
1077  __poChart->installEventFilter( this );
1078  // ... including pinch gestures
1079  if( QVCTRuntime::useSettings()->isScreenGestures() ) __poChart->grabGesture( Qt::PinchGesture );
1080 
1081  // Add chart to chart table
1082  QFileInfo __qFileInfo( _rqsFilename );
1083  addTab( __poChart, __qFileInfo.baseName() );
1084  setCurrentWidget( __poChart );
1085  return __poChart;
1086 }
1087 
1089 {
1090  if( QTabWidget::currentIndex() < 0 ) return;
1091  ((CChart*)QTabWidget::currentWidget())->update();
1092 }
1093 
1094 bool CChartTable::addElevation( const QString& _rqsFilename )
1095 {
1096  if( QTabWidget::currentIndex() < 0 ) return false;
1097  CChart* __poChart = (CChart*)QTabWidget::currentWidget();
1098  if( __poChart->hasElevation() ) return true;
1099  __poChart->addElevation( _rqsFilename );
1100  return __poChart->hasElevation();
1101 }
1102 
1104 {
1105  if( QTabWidget::currentIndex() < 0 ) return false;
1106  return ((CChart*)QTabWidget::currentWidget())->hasElevation();
1107 }
1108 
1109 void CChartTable::showElevation( bool _bShow )
1110 {
1111  if( QTabWidget::currentIndex() < 0 ) return;
1112  ((CChart*)QTabWidget::currentWidget())->showElevation( _bShow );
1113  updateChart();
1114 }
1115 
1116 double CChartTable::toZoom( double _fdScale, const CChart* _poChart )
1117 {
1118  //qDebug( "DEBUG[%s] Scale: %f", Q_FUNC_INFO, _fdScale );
1119  if( !_poChart && QTabWidget::currentIndex() < 0 ) return 1;
1120  const CChart* __poChart = _poChart ? _poChart : (CChart*)QTabWidget::currentWidget();
1121  /*
1122  * The zoom factor is computed based on the ratio between:
1123  * - the "actual" chart scale,
1124  * computed as the ratio between the screen resolution
1125  * and the chart resolution at the current position
1126  * - the absolute reference scale (10'000 to 10'000'000),
1127  * computed from the (normalized) reference scale factor
1128  */
1129  // screen res. [px/m] chart res. [m/px] absolute reference scale
1130  double __fdZoom = 39.37*iDpi * __poChart->getResolution() / pow( 10, 4.0+4.0*_fdScale );
1131  //qDebug( "DEBUG[%s] Zoom: %f", Q_FUNC_INFO, __fdZoom );
1132  return __fdZoom;
1133 }
1134 
1135 double CChartTable::toScale( double _fdZoom, const CChart* _poChart )
1136 {
1137  //qDebug( "DEBUG[%s] Zoom: %f", Q_FUNC_INFO, _fdZoom );
1138  if( !_poChart && QTabWidget::currentIndex() < 0 ) return 0;
1139  const CChart* __poChart = _poChart ? _poChart : (CChart*)QTabWidget::currentWidget();
1140  double __fdScale = ( log10( 39.37*iDpi * __poChart->getResolution() / _fdZoom ) - 4.0 ) / 4.0;
1141  //qDebug( "DEBUG[%s] Scale: %f", Q_FUNC_INFO, __fdScale );
1142  return __fdScale;
1143 }
[UI] Chart control user-interface
void enableControls(bool _bEnable)
Enables/disables all chart controls.
void stepScale(bool _bIncrease, bool _bBigStep=true)
Increases/decreases the scale by discrete steps.
void enablePointer(bool _bEnable)
Enables/disables pointer actions.
void setScale(double _fdScale)
Sets the scale at the given value.
void enableMeasureSingle(bool _bEnable)
Enables/disables single measurement.
void setElevation(bool _bHasElevation, bool _bShowElevation)
Sets elevation status.
void lockScale(bool _bLock)
Sets the scale lock/unlock status.
void enableTarget(bool _bEnable)
Enables/disables target.
void enableMeasure(bool _bEnable)
Enables/disables ongoing measurements.
void lockPosition(bool _bLock)
Sets the position lock/unlock status.
double fdGestureZoomReference
Reference zoom for pinch gesture.
Definition: CChartTable.hpp:92
int parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
double fdGestureTimeLast
Keep track of when a gesture event last occured.
Definition: CChartTable.hpp:90
virtual bool eventFilter(QObject *_pqObject, QEvent *_pqEvent)
void slotLoad()
[UI:Slot] Slot to load a full project's content from file
int iDpi
Resolution, in Dots-per-Inch (DPI)
Definition: CChartTable.hpp:76
void slotSave()
[UI:Slot] Slot to save the full project's content to file
void setOverlayPointMove(COverlayPoint *_poOverlayPoint)
Sets the overlay point to be moved (and lock all other actions while it is ongoing)
double toZoom(double _fdScale, const CChart *_poChart=0)
Converts the given scale factor to zoom factor (for the current position and - by default - the curre...
bool extendPointerPath(const CDataPosition &_roGeoPosition)
Extends the pointer path; returns true if is was actually extended, false otherwise.
void enablePointerTarget(bool _bEnable)
Enables/disables pointer target.
double fdScaleReference
Reference scale factor (shared by all "locked" maps)
Definition: CChartTable.hpp:73
QPointF qPointFMouse
Mouse position (saved dragging purposes)
Definition: CChartTable.hpp:83
COverlayObject * poOverlayObjectSelected
Currently selected overlay object.
bool handlerKeyEvent(QKeyEvent *_pqKeyEvent)
Key events handler.
void showElevation(bool _bShow)
Display elevation data (instead of raster data) of the currently selected chart (if any)
void setPositionHome()
Sets the reference chart (geographical) position to the current chart's center position.
void slotVesselPointDestroyed(QObject *_pqObject)
[APP:Slot] Slot to handle vessel point destruction
void setVesselPointSynchronize(CVesselPoint *_poVesselPoint)
Sets the vessel point used to synchronize the chart reference (geographical) position.
bool bProjectModified
Flag to track project changes (and trigger user confirmation before discarding unsaved data)
Definition: CChartTable.hpp:65
double toScale(double _fdZoom, const CChart *_poChart=0)
Converts the given zoom factor to scale factor (for the current position and - by default - the curre...
bool handlerMouseEvent(QMouseEvent *_pqMouseEvent)
Mouse events handler.
void slotChangeTab(int _iTabIndex)
[UI:Slot] Slot to handle active tab change
void setZoom(double _fdZoom, bool _bSkipCurrent=false, bool _bUpdateControl=true)
Sets the reference zoom factor.
void lockScale(bool _bLock)
Sets the scale lock/unlock status.
void constructLayout()
Constructs the layout of the user-interface.
Definition: CChartTable.cpp:81
CChartTable(QWidget *_pqParent=0)
Definition: CChartTable.cpp:57
CVesselPoint * poVesselPointSynchronize
Vessel point to synchronize to.
void setScale(double _fdScale, bool _bSkipCurrent=false, bool _bUpdateControl=true)
Sets the reference scale factor.
void slotPointerTarget(bool _bEnable)
[UI:Slot] Slot to enable/disable pointer target
bool bIgnoreUpdate
Flag that disables position, scale and pointer updates.
Definition: CChartTable.hpp:80
bool bMousePressed
Mouse-pressed status.
Definition: CChartTable.hpp:85
void lockPosition(bool _bLock)
Sets the position lock/unlock status.
void setScaleFit()
Sets the reference scale factor to match the current chart's "fit" scale (entire chart visible)
void synchronizeVesselPoint()
Synchronize the reference chart (geographical) position with the designed vessel.
void setScaleArea(const CDataPosition &_roGeoPosition1, const CDataPosition &_roGeoPosition2, double _fdScaleCorrection=1.0)
Sets the reference scale factor to display the given (geographical) area (defined by its opposite cor...
virtual QSize sizeHint() const
Definition: CChartTable.cpp:97
void slotLoadChart()
[UI:Slot] Slot to load a new chart
void stepScale(bool _bIncrease, bool _bBigStep=true)
Discretely increases/decreases the reference scale factor.
CDataPosition oGeoPositionReference
Reference chart (geographical) position (shared by all "locked" maps)
Definition: CChartTable.hpp:69
bool bMouseDrag
Mouse-drag status.
Definition: CChartTable.hpp:87
COverlayPoint * poOverlayPointMove
Overlay point being moved (non-0 only when a move is being performed)
void stepScrPosition(bool _bHorizontal, bool _bIncrease, bool _bBigStep=true)
Discretely move the reference chart (geographical) position.
bool bPointerPathSingle
Pointer single-segment path status.
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter) const
Stores this object's content to the given QVCT destination (file)
bool bPointerPath
Pointer path status.
Definition: CChartTable.hpp:99
bool handlerGestureEvent(QGestureEvent *_pqGestureEvent)
Gesture events handler.
void updateChart()
Update the (current) chart content (on screen)
bool setPointerTarget(const CDataPosition &_roGeoPosition)
Sets the pointer target's position; returns true if is was actually set, false otherwise.
void slotCloseTab()
[UI:Slot] Slot to close the current tab
void slotScaleFit()
[UI:Slot] Slot to trigger scaling to "fit" scale
void showGeoPosition(const CDataPosition &_roGeoPosition)
Shows the given (geographical) position on chart.
void slotPointerPathSingle(bool _bEnable)
[UI:Slot] Slot to enable/disable single measurement (pointer path)
virtual void clear()
void slotPointerPath(bool _bEnable)
[UI:Slot] Slot to enable/disable ongoing measurements (pointer path)
void load(const QString &_rqsFilename)
Load a full project's content from the given file.
void slotAddElevation()
[UI:Slot] Slot to add elevation data to the currently displayed chart
void enablePointerPathSingle(bool _bEnable)
Enables/disables single measurement (pointer path)
void slotScaleActual()
[UI:Slot] Slot to trigger scaling to "actual" scale
void dragScrPosition(const QPointF &_rqPointFScrPositionOffset)
Moves the reference chart (geographical) position according to the given screen offset.
bool handlerWheelEvent(QWheelEvent *_pqWheelEvent)
Wheel events handler.
bool bPointerTarget
Pointer target status.
Definition: CChartTable.hpp:96
CChart * loadChart(const QString &_rqsFilename)
Load the given chart from file.
void setScaleActual()
Sets the reference scale factor to match the current chart's "actual" scale (1:1 zoom)
void setGeoPosition(const CDataPosition &_roGeoPosition, bool _bSkipCurrent=false)
Sets the reference chart (geographical) position.
void slotPrintChart()
[UI:Slot] Slot to print the currently displayed chart
bool hasElevation()
Returns whether the currently selected chart has been associated elevation data (if any)
void setOverlayObjectSelected(COverlayObject *_poOverlayObject)
Sets the currently selected overlay object.
bool addElevation(const QString &_rqsFilename)
Add elevation data to the currently displayed chart (if any)
void enablePointerPath(bool _bEnable)
Enables/disables ongoing measurements (pointer path)
void save(const QString &_rqsFilename) const
Save the full project's content to the given file.
void resetVesselPointSynchronize()
Resets (clears) the vessel point used to synchronize the chart reference (geographical) position.
[UI] Chart (view)
Definition: CChart.hpp:44
bool hasElevation() const
Returns whether this chart has been associated elevation model data.
Definition: CChart.hpp:149
void parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
Definition: CChart.cpp:283
void lockZoom(bool _bLock)
Sets the zoom lock status.
Definition: CChart.hpp:115
bool isPositionLocked() const
Returns the position lock status.
Definition: CChart.hpp:137
bool isZoomLocked() const
Returns the zoom lock status.
Definition: CChart.hpp:147
double getZoomFit() const
Returns the zoom factor allowing to view the entire chart.
Definition: CChart.cpp:153
double getZoom() const
Returns the current zoom factor.
Definition: CChart.hpp:139
double getZoomActual() const
Returns the zoom factor corresponding to a 1:1 dataset/screen pixels ratio.
Definition: CChart.hpp:141
void print(QPrinter *_pqPrinter)
Prints the chart.
Definition: CChart.cpp:253
double getResolution() const
Returns the resolution of the chart at its current position, in meters per pixel [m/px].
Definition: CChart.cpp:176
void move(const QPointF &_rqPointFDrawPositionOffset)
Move the current (center) chart position by specified offset (in the draw area)
Definition: CChart.cpp:198
bool isElevationShowed() const
Returns the elevation model show status.
Definition: CChart.hpp:151
QRectF getDrawArea() const
Returns the viewport draw area.
Definition: CChart.hpp:127
void setZoom(double _fdZoom)
Sets the current zoom factor.
Definition: CChart.hpp:113
void setGeoPosition(const CDataPosition &_roGeoPosition)
Sets the current (center) position (geographical coordinates) of the chart.
Definition: CChart.cpp:105
QVCT::EStatus getStatus() const
Returns the internal status of the object.
Definition: CChart.cpp:128
CDataPosition getGeoPosition() const
Returns the current (center) position (geographical coordinates) of the chart.
Definition: CChart.cpp:143
void lockPosition(bool _bLock)
Sets the position lock status.
Definition: CChart.hpp:111
void setDrawArea(QRectF _qRectFDrawArea)
Sets the viewport draw area.
Definition: CChart.hpp:105
void resetDrawArea()
Resets the viewport draw area (to the widget's area)
Definition: CChart.cpp:100
QPointF toDrawPosition(const CDataPosition &_roGeoPosition) const
Converts the given (geographical) position [long,lat,elev] to chart draw point [px].
Definition: CChart.cpp:192
CDataPosition toGeoPosition(const QPointF &_rqPointFDrawPosition) const
Converts the given chart draw position to geographical position.
Definition: CChart.cpp:185
double getZoomArea(const CDataPosition &_roGeoPosition1, const CDataPosition &_roGeoPosition2) const
Returns the zoom factor allowing to view the given geographical area (defined by its opposite corners...
Definition: CChart.cpp:161
void addElevation(const QString &_rqsFileName)
Add elevation model data to chart.
Definition: CChart.cpp:69
CDataPosition getGeoPositionCenter() const
Returns the center position (geographical coordinates) of the chart.
Definition: CChart.cpp:138
(Geographical) Position data [long,lat,elev]
double getLongitude() const
Returns this position's longitude, in degrees.
void resetPosition()
Resets all coordinates (to an undefined position)
double getElevation() const
Returns this position's elevation, in meters.
double getLatitude() const
Returns this position's latitude, in degrees.
static const CDataPosition UNDEFINED
Specific value for an undefined position.
void setPosition(double _fdLongitude, double _fdLatitude, double _fdElevation=UNDEFINED_ELEVATION)
Sets new coordinates.
[UI] Landmark overlay container
virtual COverlayPoint * matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns the overlay's point that (first) matches the given screen position (0 if none is found)
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, CLandmarkContainer *_poLandmarkContainer=0, bool _bProjectDump=false) const
Stores this object's content to the given QVCT destination (file)
int parseQVCT(const QDomElement &_rqDomElement, CLandmarkContainer **_ppoLandmarkContainer=0)
Retrieves this object's content from the given QVCT source (file)
void clear()
Clear the entire content of this overlay.
[UI] Landmark overlay point (item)
void toggleMultiSelected()
Toggles this landmark's selection status.
virtual void showDetail()
Displays this object's details (in the appropriate widget/view)
void fileError(QVCT::EFileOperation _eFileOperation, const QString &_rqsFilename)
Displays a generic error message for an invalid file name and operation (open/save)
QString fileDialog(QVCT::EFileOperation _eFileOperation, const QString &_rqsTitle, const QString &_rqsFilter)
Displays a generic dialog to pick a file for the given operation (open/save)
Generic overlay object.
virtual COverlay * useOverlay()=0
Returns this object's (base) overlay.
virtual void showDetail()=0
Displays this object's details (in the appropriate widget/view)
Generic overlay point.
void forceRedraw()
Forces this overlay's rendering (not matter its cache content)
Definition: COverlay.hpp:115
[UI] Pointer overlay
void setPath(const CChart *_poChart, const QPointF &_rqPointFScrPosition)
Adds the given screen position to the pointer path.
virtual void setPosition(const QTreeWidgetItem *_pqTreeWidgetItem) const
Centers the chart on the given overlay object's position.
int getPathSegments() const
Returns the quantity of segments along the pointer path (0 if no path is defined)
CPointerPoint * usePointerTarget()
Returns the pointer point corresponding to the target.
void clearPath()
Clears the pointer path.
void clearPosition(bool _bTarget=false)
Clears the mouse pointer or target.
virtual void showDetail(const QTreeWidgetItem *_pqTreeWidgetItem) const
Displays the given overlay object's details (in the appropriate widget/view)
CPointerPoint * usePointerPoint()
Returns the pointer point corresponding to the mouse pointer.
virtual void refreshContent()
Refreshes the content of the underlying widget.
[UI] Pointer overlay point (item)
[UI] Route overlay container
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, CRouteContainer *_poRouteContainer=0, bool _bProjectDump=false) const
Stores this object's content to the given QVCT destination (file)
virtual COverlayPoint * matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns the overlay's point that (first) matches the given screen position (0 if none is found)
void clear()
Clear the entire content of this overlay.
int parseQVCT(const QDomElement &_rqDomElement, CRouteContainer **_ppoRouteContainer=0)
Retrieves this object's content from the given QVCT source (file)
[UI] Route overlay point (item) / waypoint
Definition: CRoutePoint.hpp:40
virtual void showDetail()
Displays this object's details (in the appropriate widget/view)
Definition: CRoutePoint.cpp:97
void toggleMultiSelected()
Toggles this waypoint's selection status.
void parseQVCT(const QDomElement &_rqDomElement)
Retrieves parameters from the given QVCT source (file)
Definition: CSettings.cpp:628
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, bool _bProjectDump=false) const
Stores parameters to the given QVCT destination (file)
Definition: CSettings.cpp:396
bool isPrintHighRes()
[Misc] Returns the high-resolution printing status
Definition: CSettings.hpp:441
int getScreenDpi()
[Misc] Returns the screen Dots-per-Inch (DPI)
Definition: CSettings.hpp:429
[UI] Track overlay container
void clear()
Clear the entire content of this overlay.
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, CTrackContainer *_poTrackContainer=0, bool _bProjectDump=false) const
Stores this object's content to the given QVCT destination (file)
virtual COverlayPoint * matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns the overlay's point that (first) matches the given screen position (0 if none is found)
int parseQVCT(const QDomElement &_rqDomElement, CTrackContainer **_ppoTrackContainer=0)
Retrieves this object's content from the given QVCT source (file)
[UI] Track overlay point (item)
Definition: CTrackPoint.hpp:40
void toggleMultiSelected()
Toggles this track point's selection status.
virtual void showDetail()
Displays this object's details (in the appropriate widget/view)
Definition: CTrackPoint.cpp:77
[UI] Vessel overlay container
virtual COverlayPoint * matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns the overlay's point that (first) matches the given screen position (0 if none is found)
void clear()
Clear the entire content of this overlay.
int parseQVCT(const QDomElement &_rqDomElement, CVesselContainer **_ppoVesselContainer=0)
Retrieves this object's content from the given QVCT source (file)
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, CVesselContainer *_poVesselContainer=0, bool _bProjectDump=false) const
Stores this object's content to the given QVCT destination (file)
[UI] Vessel overlay point (item) / vessel
void toggleMultiSelected()
Toggles this vessel's selection status.
virtual void showDetail()
Displays this object's details (in the appropriate widget/view)
static CPointerOverlay * usePointerOverlay()
static CPointerPointDetailView * usePointerPointDetailView()
static CVesselOverlay * useVesselOverlay()
static QMutex * useMutexDataChange()
static CRouteOverlay * useRouteOverlay()
static CChartControl * useChartControl()
static CMainWindow * useMainWindow()
static CSettings * useSettings()
static CLandmarkOverlay * useLandmarkOverlay()
static CTrackOverlay * useTrackOverlay()
@ OK
Definition: QVCT.hpp:41
@ SAVE
Definition: QVCT.hpp:42
@ OPEN
Definition: QVCT.hpp:42
double microtime()
Returns the system time with microseconds resolution, in seconds.
Definition: main.cpp:30