Qt Virtual Chart Table (QVCT)
CDeviceOverlay.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 <QByteArray>
21 #include <QDataStream>
22 #include <QDomDocument> // QtXml module
23 #include <QFileInfo>
24 #include <QList>
25 #include <QMimeData>
26 #include <QPainter>
27 #include <QPointF>
28 #include <QStringList>
29 #include <QTreeWidget>
30 #include <QTreeWidgetItem>
31 #include <QWidget>
32 #include <QXmlStreamWriter>
33 
34 // QVCT
35 #include "QVCTRuntime.hpp"
36 #include "devices/CDevice.hpp"
38 
39 
40 //------------------------------------------------------------------------------
41 // CONSTRUCTORS / DESTRUCTOR
42 //------------------------------------------------------------------------------
43 
44 CDeviceOverlay::CDeviceOverlay( QWidget* _pqParent )
45  : COverlayBaseTree( _pqParent, tr("Devices") )
46 {
47  // Tree widget
48  // ... columns
49  QTreeWidget::setColumnCount( 2 );
50  QTreeWidget::setColumnWidth( NAME, 200 );
51  // ... header
52  QTreeWidgetItem* __pqTreeWidgetItem = new QTreeWidgetItem();
53  __pqTreeWidgetItem->setText( NAME, tr("Name") );
54  __pqTreeWidgetItem->setIcon( SELECT, QIcon( ":icons/16x16/select.png" ) );
55  QTreeWidget::setHeaderItem( __pqTreeWidgetItem );
56  QTreeWidget::resizeColumnToContents( SELECT );
57  // ... top-level item
58  QTreeWidgetItem::setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable );
59  QTreeWidgetItem::setText( NAME, COverlay::qsName );
60 }
61 
63 {
65  clear();
66 }
67 
68 
69 //------------------------------------------------------------------------------
70 // METHODS: COverlay (implement/override)
71 //------------------------------------------------------------------------------
72 
73 void CDeviceOverlay::showDetail( const QTreeWidgetItem* _pqTreeWidgetItem ) const
74 {
75  if( !_pqTreeWidgetItem ) return;
76  switch( _pqTreeWidgetItem->type() )
77  {
78 
80  // NOP; top-level overlay has no detail view
81  break;
82 
84  {
85  CDevice* __poDevice = (CDevice*)_pqTreeWidgetItem;
86  __poDevice->showDetail();
87  }
88  break;
89 
90  default:;
91 
92  }
93 }
94 
95 
96 //------------------------------------------------------------------------------
97 // METHODS: COverlayBaseTree (implement/override)
98 //------------------------------------------------------------------------------
99 
100 void CDeviceOverlay::onChange( QTreeWidgetItem* _pqTreeWidgetItem, int _iColumn )
101 {
102  switch( _pqTreeWidgetItem->type() )
103  {
104 
106  {
107  CDevice* __poDevice = (CDevice*)_pqTreeWidgetItem;
108  switch( _iColumn )
109  {
110  case SELECT:
111  __poDevice->setMultiSelected( _pqTreeWidgetItem->checkState( SELECT ) == Qt::Checked );
112  break;
113  default:;
114  }
115  }
116  break;
117 
118  default:;
119 
120  }
121 }
122 
123 
124 //------------------------------------------------------------------------------
125 // METHODS
126 //------------------------------------------------------------------------------
127 
128 //
129 // OTHER
130 //
131 
132 CDevice* CDeviceOverlay::pickDevice( const QString& _rqsName )
133 {
134  int __iCount = QTreeWidgetItem::childCount();
135  for( int __i = 0; __i < __iCount; __i++ )
136  {
137  CDevice* __poDevice = (CDevice*)QTreeWidgetItem::child( __i );
138  if( __poDevice->getName() == _rqsName ) return __poDevice;
139  }
140  return 0;
141 }
142 
144 {
145  int __iCount = 0;
146  for( int __i = QTreeWidgetItem::childCount()-1; __i >= 0; __i-- )
147  {
148  CDevice* __poDevice = (CDevice*)QTreeWidgetItem::child( __i );
149  if( __poDevice->isMultiSelected() )
150  {
151  __iCount++;
152  QTreeWidgetItem::removeChild( __poDevice );
153  delete __poDevice;
154  }
155  }
156  return __iCount;
157 }
158 
160 {
161  QTreeWidgetItem* __pqTreeWidgetItem = QTreeWidgetItem::takeChild( 0 );
162  while( __pqTreeWidgetItem )
163  {
164  delete (CDevice*)__pqTreeWidgetItem;
165  __pqTreeWidgetItem = QTreeWidgetItem::takeChild( 0 );
166  }
167 }
168 
169 CDevice* CDeviceOverlay::load( const QString& _rqsFilename, bool _bSilent )
170 {
171  QFileInfo __qFileInfo( _rqsFilename );
172  CDevice* __poDevice = 0;
173  QString __qsError;
174  do // error-catching context [begin]
175  {
176  // File
177  QFileInfo __qFileInfo( _rqsFilename );
178  QFile __qFile( __qFileInfo.absoluteFilePath() );
179  if( !__qFile.open( QIODevice::ReadOnly ) )
180  {
181  __qsError = QString( "Failed to open file (%1)" ).arg( __qFile.fileName() );
182  break;
183  }
184  QDomDocument __qDocDocument;
185  if( !__qDocDocument.setContent( &__qFile ) )
186  {
187  __qsError = QString( "Failed to parse XML (%1)" ).arg( __qFile.fileName() );
188  __qFile.close();
189  break;
190  }
191  __qFile.close();
192 
193  // XML
194  QDomElement __qDomElement = __qDocDocument.documentElement();
195  QString __qDocType = __qDomElement.nodeName();
196  if( __qDomElement.isNull() || __qDocType != "QVCT" )
197  {
198  __qsError = QString( "Invalid XML document type (%1); expected: 'QVCT'" ).arg( __qFile.fileName() );
199  break;
200  }
201  parseQVCT( __qDomElement, &__poDevice );
202  }
203  while( false ); // error-catching context [end]
204  if( !__qsError.isEmpty() )
205  {
206  qCritical( "ERROR[%s]: %s", Q_FUNC_INFO, qPrintable( __qsError ) );
207  if( !_bSilent ) QVCTRuntime::useMainWindow()->fileError( QVCT::OPEN, _rqsFilename );
208  return 0;
209  }
210  QTreeWidgetItem::setExpanded( true );
211  return __poDevice;
212 }
213 
214 int CDeviceOverlay::parseQVCT( const QDomElement& _rqDomElement, CDevice** _ppoDevice )
215 {
216  CDevice* __poDevice = 0;
217  int __iCount = 0;
218  for( QDomElement __qDomElement = _rqDomElement.firstChildElement( "Device" );
219  !__qDomElement.isNull();
220  __qDomElement = __qDomElement.nextSiblingElement( "Device" ) )
221  {
222  __iCount++;
223  QString __qsName = __qDomElement.attribute( "name" );
224  if( !__qsName.isEmpty() ) __qsName = COverlay::newChildName( __qsName );
225  else __qsName = COverlay::newChildName( tr("Device"), 1, true );
226  QString __qsDriver = __qDomElement.attribute( "driver" );
227  CDeviceDriver::EDriver __eDriver = CDeviceDriver::fromCode( __qsDriver );
228  if( __eDriver == CDeviceDriver::UNDEFINED )
229  {
230  qCritical( "ERROR[%s]: Missing or invalid device driver code (%s)", Q_FUNC_INFO, qPrintable( __qsDriver ) );
231  continue;
232  }
233  __poDevice = CDeviceDriver::createDevice( __qsName, __eDriver );
234  __poDevice->parseQVCT( __qDomElement );
235  QTreeWidgetItem::addChild( __poDevice );
236  }
237  if( _ppoDevice ) *_ppoDevice = __poDevice;
238  return __iCount;
239 }
240 
241 void CDeviceOverlay::save( const QString& _rqsFilename, CDevice* _poDevice, bool _bApplicationDump ) const
242 {
243  QFileInfo __qFileInfo( _rqsFilename );
244  QString __qsFormat = __qFileInfo.suffix();
245  if( __qsFormat != "qvct" )
246  {
247  qCritical( "ERROR[%s]: Invalid file format/extention (%s); expected: 'qvct'", Q_FUNC_INFO, qPrintable( __qsFormat ) );
248  return;
249  }
250 
251  // File [open]
252  QFile __qFile( __qFileInfo.absoluteFilePath() );
253  if( !__qFile.open( QIODevice::WriteOnly ) )
254  {
255  qCritical( "ERROR[%s]: Failed to open file (%s)", Q_FUNC_INFO, qPrintable( __qFile.fileName() ) );
256  return;
257  }
258 
259  // XML [start]
260  QXmlStreamWriter __qXmlStreamWriter( &__qFile );
261  __qXmlStreamWriter.setAutoFormatting( true );
262  __qXmlStreamWriter.writeStartDocument();
263 
264  // Data
265  dumpQVCT( __qXmlStreamWriter, _poDevice, _bApplicationDump );
266 
267  // XML [end]
268  __qXmlStreamWriter.writeEndDocument();
269 
270  // File [close]
271  __qFile.close();
272 }
273 
274 void CDeviceOverlay::dumpQVCT( QXmlStreamWriter & _rqXmlStreamWriter, CDevice* _poDevice, bool _bApplicationDump ) const
275 {
276  // Data
277  _rqXmlStreamWriter.writeStartElement( "QVCT" );
278  // ... containers
279  if( _poDevice )
280  {
281  _poDevice->dumpQVCT( _rqXmlStreamWriter );
282  }
283  else // no container given; assume selection dump or full dump
284  {
285  int __iCount = QTreeWidgetItem::childCount();
286  for( int __i = 0; __i < __iCount; __i++ )
287  {
288  CDevice* __poDevice = (CDevice*)QTreeWidgetItem::child( __i );
289  if( !_bApplicationDump && !__poDevice->isMultiSelected() ) continue;
290  __poDevice->dumpQVCT( _rqXmlStreamWriter );
291  }
292  }
293  // ... [end]
294  _rqXmlStreamWriter.writeEndElement(); // QVCT
295 }
EDriver
Driver ID.
@ UNDEFINED
Undefined driver.
static CDevice * createDevice(const QString &_rqsDeviceName, EDriver _eDriver)
Create a new device based on the specified driver.
static EDriver fromCode(const QString &_rqsCode)
Returns the device driver ID corresponding to the given machine-friendly code.
CDeviceOverlay(QWidget *_pqParent=0)
int deleteSelection()
Deletes selected devices from this overlay.
void clear()
Clear the entire content of this overlay.
CDevice * pickDevice(const QString &_rqsName)
Returns the device matching the given name (0 if none is found)
void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter, CDevice *_poDevice=0, bool _bApplicationDump=false) const
Stores this object's content to the given QVCT destination (file)
virtual void showDetail(const QTreeWidgetItem *_pqTreeWidgetItem) const
Displays the given overlay object's details (in the appropriate widget/view)
@ NAME
Device name.
@ SELECT
Device selection status.
int parseQVCT(const QDomElement &_rqDomElement, CDevice **_ppoDevice=0)
Retrieves this object's content from the given QVCT source (file)
void save(const QString &_rqsFilename, CDevice *_poDevice=0, bool _bApplicationDump=false) const
Save this object's content (device) to the given file (all selected items if no device is given)
virtual void onChange(QTreeWidgetItem *_pqTreeWidgetItem, int __iColumn)
Handles item (content) changes in the underlying QTreeWidget.
virtual ~CDeviceOverlay()
CDevice * load(const QString &_rqsFilename, bool _bSilent=false)
Load this object's content from the given file and returns the last loaded device (0 if none)
Generic navigation device (GPS, speedometer, compass, etc.)
Definition: CDevice.hpp:43
virtual void showDetail()=0
Displays the device's details (in the appropriate widget/view)
virtual void parseQVCT(const QDomElement &_rqDomElement)=0
Retrieves the device's configuration from the given QVCT source (file)
virtual void dumpQVCT(QXmlStreamWriter &_rqXmlStreamWriter) const =0
Stores the device's configuration to the given QVCT destination (file)
void fileError(QVCT::EFileOperation _eFileOperation, const QString &_rqsFilename)
Displays a generic error message for an invalid file name and operation (open/save)
Generic overlay base (tree widget)
void destroy()
Prepare the underlying QTreeWidget for destruction.
void setMultiSelected(bool _bMultiSelected)
Sets this item's selection status.
bool isMultiSelected() const
Returns this item's selection status.
@ OVERLAY
(Base) overlay
QString getName() const
Returns this object's name.
QString newChildName(const QString &_rqsName, int __iZeroPrefix=0, bool __bForceSuffix=false) const
Returns a valid name for a new sibling of this object.
Definition: COverlay.cpp:123
QString qsName
Overlay name.
Definition: COverlay.hpp:52
static CMainWindow * useMainWindow()
@ OPEN
Definition: QVCT.hpp:42