Qt Virtual Chart Table (QVCT)
CVesselContainer.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 // QT
20 #include <QDateTime>
21 #include <QDomElement> // QtXml module
22 #include <QFileInfo>
23 #include <QFileDialog>
24 #include <QPainter>
25 #include <QPointF>
26 #include <QTimer>
27 #include <QTreeWidgetItem>
28 
29 // QVCT
30 #include "QVCTRuntime.hpp"
37 
38 
39 //------------------------------------------------------------------------------
40 // CONSTRUCTORS / DESTRUCTOR
41 //------------------------------------------------------------------------------
42 
43 CVesselContainer::CVesselContainer( const QString& _rqsName )
44  : COverlayContainer( COverlayObject::CONTAINER, _rqsName )
45  , bDynamic( false )
46  , qsType()
47  , qsDescription()
48  , qsComment()
49  , qsUrl()
50 {
51  QTreeWidgetItem::setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDropEnabled );
52  QTreeWidgetItem::setText( CVesselOverlay::NAME, qsName );
53  QTreeWidgetItem::setCheckState( CVesselOverlay::VISIBLE, Qt::Checked );
54  pqTimerDynamicCleanup = new QTimer( this );
55  QObject::connect( pqTimerDynamicCleanup, SIGNAL( timeout() ), this, SLOT( slotTimerDynamicCleanup() ) );
56 }
57 
59 {
60  clear();
61 }
62 
63 
64 //------------------------------------------------------------------------------
65 // METHODS: COverlayObject (implement/override)
66 //------------------------------------------------------------------------------
67 
68 void CVesselContainer::serialize( QDataStream& _rqDataStream ) const
69 {
70  COverlayObject::serialize( _rqDataStream );
71  _rqDataStream << qsType << qsDescription << qsComment << qsUrl;
72 }
73 
74 void CVesselContainer::unserialize( QDataStream& _rqDataStream )
75 {
76  COverlayObject::unserialize( _rqDataStream );
77  _rqDataStream >> qsType >> qsDescription >> qsComment >> qsUrl;
78  QTreeWidgetItem::setText( CVesselOverlay::NAME, qsName );
79 }
80 
81 void CVesselContainer::draw( const CChart* _poChart, QPainter* _pqPainter )
82 {
83  if( !bVisible ) return;
84  int __iCount = QTreeWidgetItem::childCount();
85  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
86  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->draw( _poChart, _pqPainter );
87 }
88 
90 {
96 }
97 
99 {
100  CVesselContainerEditView* __poVesselContainerEditView = new CVesselContainerEditView( this );
101  if( __poVesselContainerEditView->exec() == QDialog::Accepted ) showDetail();
102  delete __poVesselContainerEditView;
103 }
104 
105 
106 //------------------------------------------------------------------------------
107 // METHODS: COverlayContainer (implement/override)
108 //------------------------------------------------------------------------------
109 
110 COverlayPoint* CVesselContainer::matchScrPosition( const CChart* _poChart, const QPointF& _rqPointFScrPosition ) const
111 {
112  if( !bVisible ) return 0;
113  int __iCount = QTreeWidgetItem::childCount();
114  for( int __i = __iCount-1 ; __i >= bDynamic ? 1 : 0; __i-- ) // we must go in the reverse order of CVesselContainer::draw() to pick the correct (overlapping) item
115  {
116  COverlayPoint* __poOverlayPoint = (COverlayPoint*)QTreeWidgetItem::child( __i );
117  if( __poOverlayPoint->matchScrPosition( _poChart, _rqPointFScrPosition ) )
118  return __poOverlayPoint;
119  }
120  return 0;
121 }
122 
123 
124 //------------------------------------------------------------------------------
125 // METHODS: COverlayVisibility (override)
126 //------------------------------------------------------------------------------
127 
128 void CVesselContainer::setVisibleName( bool _bVisibleName )
129 {
130  bVisibleName = _bVisibleName;
131  int __iCount = QTreeWidgetItem::childCount();
132  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
133  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->setVisibleName( bVisibleName );
134 }
135 
136 void CVesselContainer::setVisiblePosition( bool _bVisiblePosition )
137 {
138  bVisiblePosition = _bVisiblePosition;
139  int __iCount = QTreeWidgetItem::childCount();
140  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
141  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->setVisiblePosition( bVisiblePosition );
142 }
143 
144 void CVesselContainer::setVisibleCourse( bool _bVisibleCourse )
145 {
146  bVisibleCourse = _bVisibleCourse;
147  int __iCount = QTreeWidgetItem::childCount();
148  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
149  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->setVisibleCourse( bVisibleCourse );
150 }
151 
153 {
154  // Toggle global visibility
156  // Set points visibility
157  int __iCount = QTreeWidgetItem::childCount();
158  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
159  {
160  CVesselPoint* __poVesselPoint = (CVesselPoint*)QTreeWidgetItem::child( __i );
161  __poVesselPoint->setVisibleName( bVisibleName );
162  __poVesselPoint->setVisiblePosition( bVisiblePosition );
163  __poVesselPoint->setVisibleCourse( bVisibleCourse );
164  }
165 }
166 
167 
168 //------------------------------------------------------------------------------
169 // METHODS
170 //------------------------------------------------------------------------------
171 
172 //
173 // SLOTS
174 //
175 
177 {
178  //qDebug( "DEBUG[%s]: Begin", Q_FUNC_INFO );
179  if( !bDynamic ) return;
180  QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange();
181  __pqMutexDataChange->lock();
182  CVesselContainerDevice* __poVesselContainerDevice = (CVesselContainerDevice*)QTreeWidgetItem::child( 0 );
183  cleanPointDynamic( __poVesselContainerDevice->getTTL() );
184  __pqMutexDataChange->unlock();
185  //qDebug( "DEBUG[%s]: End", Q_FUNC_INFO );
186 }
187 
188 //
189 // GETTERS
190 //
191 
193 {
194  int __iCount = QTreeWidgetItem::childCount();
195  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
196  if( !((CVesselPoint*)QTreeWidgetItem::child( __i ))->isDeviceConnected() ) return false;
197  return true;
198 }
199 
200 //
201 // OTHER
202 //
203 
204 void CVesselContainer::setDevice( CVesselContainerDevice* _poVesselContainerDevice )
205 {
206  clear();
207  bDynamic = true;
208  QTreeWidgetItem::addChild( _poVesselContainerDevice );
209  _poVesselContainerDevice->connectDevice();
210 }
211 
213 {
214  int __iCount = QTreeWidgetItem::childCount();
215  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
216  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->connectDevice();
217  pqTimerDynamicCleanup->start( std::max( QVCTRuntime::useSettings()->getRateRefresh(), 1000 ) );
218 }
219 
221 {
222  pqTimerDynamicCleanup->stop();
223  int __iCount = QTreeWidgetItem::childCount();
224  for( int __i = bDynamic ? 1 : 0; __i < __iCount; __i++ )
225  ((CVesselPoint*)QTreeWidgetItem::child( __i ))->disconnectDevice();
226 }
227 
229 {
230  if( !bDynamic ) return;
231  clear();
232 }
233 
234 CVesselPoint* CVesselContainer::addPoint( const QString& _rqsName, const CDataPosition& _roDataPosition )
235 {
236  if( bDynamic ) return 0;
237  CVesselPoint* __poVesselPoint = new CVesselPoint( _rqsName, _roDataPosition );
238  __poVesselPoint->setVisibility( this->getVisibility() | 1 );
239  QTreeWidgetItem::addChild( __poVesselPoint );
240  return __poVesselPoint;
241 }
242 
243 void CVesselContainer::addPointDynamic( const CDeviceDataFix& _roDeviceDataFix, const QString& _rqsDeviceName )
244 {
245  if( !bDynamic ) return;
246  int __iCount = QTreeWidgetItem::childCount();
247  for( int __i = 1; __i < __iCount; __i++ )
248  {
249  CVesselPoint* __poVesselPoint = (CVesselPoint*)QTreeWidgetItem::child( __i );
250  if( __poVesselPoint->getName() == _roDeviceDataFix.getSourceName() ) return;
251  }
252  CVesselPoint* __poVesselPoint = new CVesselPoint( _roDeviceDataFix.getSourceName(), true );
253  __poVesselPoint->setType( tr("Dynamic Vessel") );
254  __poVesselPoint->setDescription( tr("This vessel has been automatically added as a result of the parent flotilla's device activity.") );
255  __poVesselPoint->setSymbol( "DynamicVessel" );
256  __poVesselPoint->setVisibility( this->getVisibility() | 1 );
257  QTreeWidgetItem::addChild( __poVesselPoint );
258  CVesselPointDevice* __poVesselPointDevice = new CVesselPointDevice( _rqsDeviceName, _roDeviceDataFix.getSourceName(), true );
259  __poVesselPointDevice->setSynchronized( true, true, true, // position & elevation
260  true, true, true, // ground course
261  false, false, false, // apparent course
262  true ); // additional textual data
263  __poVesselPoint->addChild( __poVesselPointDevice );
264  __poVesselPointDevice->syncDataFix( _roDeviceDataFix );
265  __poVesselPointDevice->connectDevice();
266 }
267 
269 {
270  if( !bDynamic ) return 0;
271  double __fdCurrentTime = (double)QDateTime::currentDateTime().toTime_t();
272  int __iCount = 0;
273  for( int __i = QTreeWidgetItem::childCount()-1; __i >= 1; __i-- )
274  {
275  CVesselPoint* __poVesselPoint = (CVesselPoint*)QTreeWidgetItem::child( __i );
276  double __fdVesselTime = __poVesselPoint->getTime();
277  if( __fdVesselTime != CDataTime::UNDEFINED_TIME
278  && __fdCurrentTime - __fdVesselTime > (double)_iTTL )
279  {
280  __iCount++;
281  QTreeWidgetItem::removeChild( __poVesselPoint );
282  delete __poVesselPoint;
283  }
284  }
285  return __iCount;
286 }
287 
288 int CVesselContainer::parseQVCT( const QDomElement& _rqDomElement )
289 {
290  COverlayVisibility::setVisibility( _rqDomElement.attribute( "visibility", "3" ).toInt() );
291  QTreeWidgetItem::setCheckState( CVesselOverlay::VISIBLE, bVisible ? Qt::Checked : Qt::Unchecked );
292  qsType = _rqDomElement.attribute( "type" );
293  qsUrl = _rqDomElement.attribute( "url" );
294  qsDescription = _rqDomElement.firstChildElement( "Description" ).text();
295  qsComment = _rqDomElement.firstChildElement( "Comment" ).text();
296  QDomElement __qDomElement = _rqDomElement.firstChildElement( "Device" );
297  if( !__qDomElement.isNull() )
298  {
299  CVesselContainerDevice* __poVesselContainerDevice = new CVesselContainerDevice( __qDomElement.attribute( "name" ) );
300  __poVesselContainerDevice->parseQVCT( __qDomElement );
301  setDevice( __poVesselContainerDevice );
302  return 0;
303  }
304  int __iCount = 0;
305  for( QDomElement __qDomElement = _rqDomElement.firstChildElement( "Vessel" );
306  !__qDomElement.isNull();
307  __qDomElement = __qDomElement.nextSiblingElement( "Vessel" ) )
308  {
309  __iCount++;
310  QString __qsName = __qDomElement.attribute( "name" );
311  if( __qsName.isEmpty() ) COverlayObject::newChildName( tr("Vessel"), 1, __iCount );
312  CVesselPoint* __poVesselPoint = new CVesselPoint( __qsName );
313  __poVesselPoint->parseQVCT( __qDomElement );
314  addChild( __poVesselPoint );
315  }
316  return __iCount;
317 }
318 
319 void CVesselContainer::dumpQVCT( QXmlStreamWriter & _rqXmlStreamWriter, bool bOnlySelected ) const
320 {
321  // Data
322  _rqXmlStreamWriter.writeStartElement( "Flotilla" );
323  // ... name
324  if( !qsName.isEmpty() ) _rqXmlStreamWriter.writeAttribute( "name", qsName );
325  // ... visibility
326  _rqXmlStreamWriter.writeAttribute( "visibility", QString::number( COverlayVisibility::getVisibility() ) );
327  // ... type
328  if( !qsType.isEmpty() ) _rqXmlStreamWriter.writeAttribute( "type", qsType );
329  // ... url
330  if( !qsUrl.isEmpty() ) _rqXmlStreamWriter.writeAttribute( "url", qsUrl );
331  // ... description
332  if( !qsDescription.isEmpty() )
333  {
334  _rqXmlStreamWriter.writeStartElement( "Description" );
335  _rqXmlStreamWriter.writeCDATA( qsDescription );
336  _rqXmlStreamWriter.writeEndElement(); // Description
337  }
338  // ... comment
339  if( !qsComment.isEmpty() )
340  {
341  _rqXmlStreamWriter.writeStartElement( "Comment" );
342  _rqXmlStreamWriter.writeCDATA( qsComment );
343  _rqXmlStreamWriter.writeEndElement(); // Comment
344  }
345  // ... points
346  if( !bDynamic )
347  {
348  int __iCount = QTreeWidgetItem::childCount();
349  for( int __i = 0; __i < __iCount; __i++ )
350  {
351  CVesselPoint* __poVesselPoint = (CVesselPoint*)QTreeWidgetItem::child( __i );
352  if( bOnlySelected && !__poVesselPoint->isMultiSelected() ) continue;
353  __poVesselPoint->dumpQVCT( _rqXmlStreamWriter );
354  }
355  }
356  else
357  {
358  CVesselContainerDevice* __poVesselContainerDevice = (CVesselContainerDevice*)QTreeWidgetItem::child( 0 );
359  __poVesselContainerDevice->dumpQVCT( _rqXmlStreamWriter );
360  }
361  // ... [end]
362  _rqXmlStreamWriter.writeEndElement(); // Flotilla
363 }
364 
366 {
367  int __iCount = 0;
368  for( int __i = QTreeWidgetItem::childCount()-1; __i >= bDynamic ? 1 : 0; __i-- )
369  {
370  CVesselPoint* __poVesselPoint = (CVesselPoint*)QTreeWidgetItem::child( __i );
371  if( __poVesselPoint->isMultiSelected() )
372  {
373  __iCount++;
374  QTreeWidgetItem::removeChild( __poVesselPoint );
375  delete __poVesselPoint;
376  }
377  }
378  return __iCount;
379 }
380 
382 {
383  QTreeWidgetItem* __pqTreeWidgetItem = QTreeWidgetItem::takeChild( 0 );
384  if( __pqTreeWidgetItem && bDynamic )
385  {
386  delete (CVesselContainerDevice*)__pqTreeWidgetItem;
387  __pqTreeWidgetItem = QTreeWidgetItem::takeChild( 0 );
388  }
389  while( __pqTreeWidgetItem )
390  {
391  delete (CVesselPoint*)__pqTreeWidgetItem;
392  __pqTreeWidgetItem = QTreeWidgetItem::takeChild( 0 );
393  }
394  bDynamic = false;
395 }
void setOverlayObjectSelected(COverlayObject *_poOverlayObject)
Sets the currently selected overlay object.
[UI] Chart (view)
Definition: CChart.hpp:44
(Geographical) Position data [long,lat,elev]
double getTime() const
Returns this time's time, in seconds from Unix epoch.
Definition: CDataTime.hpp:89
static constexpr double UNDEFINED_TIME
Specific value for an undefined time.
Definition: CDataTime.hpp:44
Fix data [source,time,position,course,DOPs,...].
QString getSourceName() const
Returns the source name.
Generic overlay container.
void switchView(EView eView)
Displays the requested container/item details (switching to the appropriate widget)
@ VESSEL_CONTAINER
Vessel container.
bool isMultiSelected() const
Returns this item's selection status.
@ VESSEL
Vessel overlay.
void switchView(EView eView)
Displays the requested overlay (switching to the appropriate tab)
void setOverlayObject(COverlayObject *_poOverlayObject)
Sets the overlay object to be displayed (and refreshes the underlying widget)
Generic overlay object.
virtual void serialize(QDataStream &_rqDataStream) const
Serializes (store) this object's data to binary format.
QString getName() const
Returns this object's name.
virtual void unserialize(QDataStream &_rqDataStream)
Unserializes (restore) this object's data from binary format.
QString newChildName(const QString &_rqsName, int _iZeroPrefix=0, bool _bForceSuffix=false) const
Returns a valid (non-duplicate) name for a new sibling of this object.
QString qsName
Object name.
Generic overlay point.
virtual bool matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns whether this point matches the given screen position.
virtual void setVisibleCourse(bool _bVisibleCourse)
Sets the course's visibility status.
virtual void setVisiblePosition(bool _bVisiblePosition)
Sets the position's visibility status.
void setVisibility(int _iVisibilityCode)
Sets the global (coded) visibility status.
virtual void toggleVisibility(bool _bIncludeCourse, bool _bIncludeRouting)
Toggle the visibility status.
bool bVisible
Global (marker) visibility status.
bool bVisiblePosition
Position's visibility status.
bool bVisibleName
Name's (tag) visibility status.
int getVisibility() const
Returns the global (coded) visibility status.
virtual void setVisibleName(bool _bVisibleName)
Sets the name's (tag) visibility status.
bool bVisibleCourse
Course's visibility status.
virtual void refreshContent()
Refreshes the content of the underlying widget.
int getTTL() const
Returns the (vessels) time-to-live.
bool connectDevice()
Connects to the actual device.
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter) const
Stores this object's content to the given QVCT destination (file)
void parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
[UI] Vessel container's edit view
virtual void setVisibleName(bool _bVisibleName)
Sets the name's (tag) visibility status.
bool bDynamic
Dynamic status.
QTimer * pqTimerDynamicCleanup
Dynamic flotilla clean-up timer.
void clearDevice()
Clears the device set to dynamically generate this flotilla.
QString qsComment
Vessel's comment.
CVesselContainer(const QString &_rqsName)
void addPointDynamic(const CDeviceDataFix &_roDeviceDataFix, const QString &_rqsDeviceName)
Add a new dynamic vessel (item/point) with the given data fix to this container.
virtual ~CVesselContainer()
virtual void setVisibleCourse(bool _bVisibleCourse)
Sets the course's visibility status.
virtual void showDetail()
Displays this object's details (in the appropriate widget/view)
bool isDeviceConnected() const
Returns whether this flotilla's vessels devices are all connected.
virtual void unserialize(QDataStream &_rqDataStream)
Unserializes (restore) this object's data from binary format.
virtual void draw(const CChart *_poChart, QPainter *_pqPainter)
Draws this object (itself or its content)
virtual void showEdit()
Displays this object's edit widget/view.
QString qsType
Vessel's type.
int cleanPointDynamic(int _iTTL)
Deletes dynamic vessels (items/points) that have not been updated for the given "time-to-live" second...
int deleteSelection()
Deletes selected items within this container.
CVesselPoint * addPoint(const QString &_rqsName, const CDataPosition &_roDataPosition=CDataPosition::UNDEFINED)
Add a new vessel (item/point) to this container.
virtual COverlayPoint * matchScrPosition(const CChart *_poChart, const QPointF &_rqPointFScrPosition) const
Returns the overlay container's point that (first) matches the given screen position (0 if none is fo...
QString qsDescription
Vessel's description.
QString qsUrl
Vessel's URL.
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, bool bOnlySelected=false) const
Stores this object's content to the given QVCT destination (file)
void setDevice(CVesselContainerDevice *_poVesselContainerDevice)
Sets a device to dynamically generate this flotilla.
void disconnectDevice()
Disconnects all children vessels devices.
int parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
virtual void serialize(QDataStream &_rqDataStream) const
Serializes (store) this object's data to binary format.
void clear()
Clear the entire content of this container.
virtual void toggleVisibility()
void connectDevice()
Connects all children vessels devices.
void slotTimerDynamicCleanup()
[Slot] Slot to handle activity signal emitted by device
virtual void setVisiblePosition(bool _bVisiblePosition)
Sets the position's visibility status.
@ NAME
Vessel name.
@ VISIBLE
Vessel visibility status.
[UI] Vessel device
void syncDataFix(const CDeviceDataFix &_roDeviceDataFix)
Synchronizes fix data (sent by device)
void setSynchronized(bool _bSynchronizePosition, bool _bSynchronizeElevation, bool _bSynchronizeTime, bool _bSynchronizeGroundBearing, bool _bSynchronizeGroundSpeed, bool _bSynchronizeGroundSpeedVertical, bool _bSynchronizeApparentBearing, bool _bSynchronizeApparentSpeed, bool _bSynchronizeApparentSpeedVertical, bool _bSynchronizeText)
Sets the synchronizazion flags.
bool connectDevice()
Connects to the actual device.
[UI] Vessel overlay point (item) / vessel
void setType(const QString &_rqsType)
Sets this vessel's type.
void setDescription(const QString &_rqsDescription)
Sets this vessel's description.
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter) const
Stores this object's content to the given QVCT destination (file)
void setSymbol(const QString &_rqsSymbol)
Sets this vessel's symbol.
void parseQVCT(const QDomElement &_rqDomElement)
Retrieves this object's content from the given QVCT source (file)
static COverlayDetailView * useOverlayDetailView()
static CVesselContainerDetailView * useVesselContainerDetailView()
static QMutex * useMutexDataChange()
static COverlayListView * useOverlayListView()
static CChartTable * useChartTable()
static CSettings * useSettings()