Qt Virtual Chart Table (QVCT)
CInstrumentGAChronograph.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 <QBrush>
24 #include <QFont>
25 #include <QPainter>
26 #include <QPointF>
27 #include <QPen>
28 #include <QPixmap>
29 #include <QSizeF>
30 #include <QWidget>
31 
32 // QVCT
33 #include "QVCTRuntime.hpp"
35 
36 
37 //------------------------------------------------------------------------------
38 // CONSTRUCTORS / DESTRUCTOR
39 //------------------------------------------------------------------------------
40 
42  : CInstrument( _poVesselCockpit )
43  , bForceRedraw( true )
44  , eUnit( CUnitTimeZone::UTC )
45  , fdTime( 0.0 )
46  , fdSW1TimeStarted( 0.0 )
47  , fdSW1TimeAccumulated( 0.0 )
48  , fdSW2TimeStarted( 0.0 )
49  , fdSW2TimeAccumulated( 0.0 )
50 {
51 }
52 
53 
54 //------------------------------------------------------------------------------
55 // METHODS: QWidget (implement/override)
56 //------------------------------------------------------------------------------
57 
58 void CInstrumentGAChronograph::mouseReleaseEvent( QMouseEvent* _pqMouseEvent )
59 {
60 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
61  QPointF __qPointFMouse = _pqMouseEvent->localPos();
62 #else
63  QPointF __qPointFMouse = _pqMouseEvent->posF();
64 #endif
65  if( __qPointFMouse.x() < QWidget::size().width()/2 )
66  { // left-hand side
67  if( fdSW1TimeStarted )
68  {
70  fdSW1TimeStarted = 0;
71  }
72  else
74  }
75  else
76  { // right-hand side
77  if( fdSW2TimeStarted )
78  {
80  fdSW2TimeStarted = 0;
81  }
82  else
84  }
85  bForceRedraw = true;
86  QWidget::update();
87 }
88 
89 void CInstrumentGAChronograph::mouseDoubleClickEvent( QMouseEvent* _pqMouseEvent )
90 {
91  // NOTE: don't forget that the widget also receives the two corresponding mouseReleaseEvents
92 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
93  QPointF __qPointFMouse = _pqMouseEvent->localPos();
94 #else
95  QPointF __qPointFMouse = _pqMouseEvent->posF();
96 #endif
97  if( __qPointFMouse.x() < QWidget::size().width()/2 )
98  { // left-hand side
100  }
101  else
102  { // right-hand side
104  }
105  bForceRedraw = true;
106  QWidget::update();
107 }
108 
109 
110 //------------------------------------------------------------------------------
111 // METHODS: CInstrument (implement/override)
112 //------------------------------------------------------------------------------
113 
115 {
116  // Retrieve parameters and values
118  double __fdTime = floor( microtime() + 0.5 ); // we don't use milli-seconds
119 
120  // Redraw pixmap only if required
121  if( bForceRedraw
122  || qPixmapBuffer.size() != QWidget::size()
123  || eUnit != __eUnit
124  || fdTime != __fdTime )
125  {
126  // Draw resources
127  if( bForceRedraw
128  || qPixmapBufferBackground.size() != QWidget::size()
129  || eUnit != __eUnit )
130  {
131  drawStatic( __eUnit );
132  }
133  drawDynamic( __eUnit, __fdTime );
134 
135  // Update cache parameters and values
136  bForceRedraw = false;
137  eUnit = __eUnit;
138  fdTime = __fdTime;
139  }
140 
141  // Draw pixmap
142  QPainter __qPainter;
143  __qPainter.begin( this );
144  __qPainter.setRenderHints( QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing );
145  __qPainter.drawPixmap( 0, 0, qPixmapBuffer );
146  __qPainter.end();
147 }
148 
149 
150 //------------------------------------------------------------------------------
151 // METHODS
152 //------------------------------------------------------------------------------
153 
154 //
155 // OTHER
156 //
157 
159 {
160  // Widget geometry
161  QPointF __qPointFCenter = QPointF( QRectF( QWidget::rect() ).center() );
162  double __fdSizeFactor = ( QWidget::width() < QWidget::height() ? (double)QWidget::width() : (double)QWidget::height() ) / 1200.0;
163  QTransform __qTransform;
164  __qTransform.translate( __qPointFCenter.x(), __qPointFCenter.y() );
165  __qTransform.scale( __fdSizeFactor, __fdSizeFactor );
166 
167  // Painter and resources
168  if( qPixmapBufferBackground.size() != QWidget::size() ) qPixmapBufferBackground = QPixmap( QWidget::size() );
169  qPixmapBufferBackground.fill( Qt::transparent );
170  QPainter __qPainter( &qPixmapBufferBackground );
171  QPen __qPen;
172  QFont __qFont;
173  __qPainter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
174 
175  // Draw
176  __qPainter.setWorldTransform( __qTransform );
177 
178  // ... delimiting corona
179  __qPen.setColor( Qt::white );
180  __qPen.setWidth( 10.0 );
181  __qPainter.setPen( __qPen );
182  __qPainter.setBrush( QBrush( QColor( 32, 32, 32, 255 ) ) );
183  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 495.0, 495.0 );
184 
185  // ... small (1-minute) ticks
186  for( int __i=0; __i<60; __i++ )
187  {
188  double __fdAngle = (double)__i * QVCT::PI / 30.0;
189  QPointF __qPointFAngle( sin( __fdAngle ), -cos( __fdAngle ) );
190  __qPainter.drawLine( 450.0*__qPointFAngle, 480.0*__qPointFAngle );
191  }
192 
193  // ... large (10-minutes) ticks
194  {
195  for( int __i=1; __i<=12; __i++ )
196  {
197  double __fdAngle = (double)__i * QVCT::PI / 6.0;
198  QPointF __qPointFAngle( sin( __fdAngle ), -cos( __fdAngle ) );
199  __qPainter.drawLine( 420.0*__qPointFAngle, 480.0*__qPointFAngle );
200  }
201  }
202 
203  // ... digits (hours)
204  __qFont.setPixelSize( 90.0 );
205  __qFont.setBold( true );
206  __qPainter.setFont( __qFont );
207  {
208  QRectF __qRectFText( QPointF( -90.0, -45.0 ), QSizeF( 180.0, 90.0 ) );
209  for( int __i=1; __i<=12; __i++ )
210  {
211  double __fdAngle = (double)__i * QVCT::PI / 6.0;
212  QPointF __qPointFAngle( sin( __fdAngle )*( __i<10 ? 1.05 : 1.0 ), -cos( __fdAngle )*1.05 );
213  __qPainter.drawText( __qRectFText.translated( 340.0*__qPointFAngle ), Qt::AlignCenter, QString::number( __i ) );
214  }
215  }
216 
217  // ... digits (minutes)
218  __qFont.setPixelSize( 50.0 );
219  __qFont.setBold( false );
220  __qPainter.setFont( __qFont );
221  {
222  QRectF __qRectFText( QPointF( -50.0, -25.0 ), QSizeF( 100.0, 50.0 ) );
223  for( int __i=1; __i<=12; __i++ )
224  {
225  double __fdAngle = (double)__i * QVCT::PI / 6.0;
226  QPointF __qPointFAngle( sin( __fdAngle )*( __i<2 ? 1.05 : 1.0 ), -cos( __fdAngle )*1.05 );
227  __qPainter.drawText( __qRectFText.translated( 240.0*__qPointFAngle ), Qt::AlignCenter, QString::number( __i*5 ) );
228  }
229  }
230 
231  // ... name and units
232  __qPen.setColor( Qt::lightGray );
233  __qPen.setWidth( 5.0 );
234  __qPainter.setPen( __qPen );
235  __qPainter.setBrush( QBrush( QColor( 32, 32, 32, 255 ) ) );
236  __qFont.setPixelSize( 50.0 );
237  __qFont.setBold( false );
238  __qPainter.setFont( __qFont );
239  {
240  QRectF __qRectFText( QPointF( -200.0, -30.0 ), QSizeF( 400.0, 60.0 ) );
241  __qPainter.drawText( __qRectFText.translated( QPointF( 0, -150.0 ) ), Qt::AlignCenter, CUnitTimeZone::toSymbol( _eUnit ) );
242  __qPainter.drawText( __qRectFText.translated( QPointF( 0, +150.0 ) ), Qt::AlignCenter, "TIME" );
243  }
244 
245  // ... data
246  {
247  QRectF __qRectFFrame( QPointF( -150.0, -60.0 ), QSizeF( 300.0, 120.0 ) );
248  QRectF __qRectFText( QPointF( -125.0, -30.0 ), QSizeF( 250.0, 60.0 ) );
249  __qPainter.drawRoundedRect( __qRectFFrame.translated( QPointF( -425.0, -515.0 ) ), 10.0, 10.0 );
250  __qPainter.drawText( __qRectFText.translated( QPointF( -440.0, -540.0 ) ), Qt::AlignLeft, "SW1" );
251  __qPainter.drawRoundedRect( __qRectFFrame.translated( QPointF( +425.0, -515.0 ) ), 10.0, 10.0 );
252  __qPainter.drawText( __qRectFText.translated( QPointF( +440.0, -540.0 ) ), Qt::AlignRight, "SW2" );
253  __qPainter.drawRoundedRect( __qRectFFrame.translated( QPointF( +425.0, +515.0 ) ), 10.0, 10.0 );
254  __qPainter.drawText( __qRectFText.translated( QPointF( +440.0, +540.0 ) ), Qt::AlignRight, CUnitTimeZone::toSymbol( _eUnit ) );
255  }
256 }
257 
259 {
260  double __fdTimeConverted = CUnitTime::toValue( _fdTime, _eUnit );
261 
262  // Widget geometry
263  QPointF __qPointFCenter = QPointF( QRectF( QWidget::rect() ).center() );
264  double __fdSizeFactor = ( QWidget::width() < QWidget::height() ? (double)QWidget::width() : (double)QWidget::height() ) / 1200.0;
265  QTransform __qTransform;
266  __qTransform.translate( __qPointFCenter.x(), __qPointFCenter.y() );
267  __qTransform.scale( __fdSizeFactor, __fdSizeFactor );
268 
269  // Painter and resources
271  QPainter __qPainter( &qPixmapBuffer );
272  QPen __qPen;
273  QFont __qFont;
274  __qPainter.setRenderHints( QPainter::Antialiasing | QPainter::TextAntialiasing );
275 
276  // Draw
277  __qPainter.setWorldTransform( __qTransform );
278 
279  // ... hours
280  __qPen.setColor( Qt::black );
281  __qPen.setWidth( 0 );
282  __qPainter.setPen( __qPen );
283  __qPainter.setBrush( QBrush( Qt::white ) );
284  __qPainter.rotate( __fdTimeConverted/120.0 );
285  {
286  static const QPointF __pqPointFPolygon[5] =
287  {
288  QPointF( -25.0, -10.0 ),
289  QPointF( -25.0, -250.0 ),
290  QPointF( 0.0, -300.0 ),
291  QPointF( +25.0, -250.0 ),
292  QPointF( +25.0, -10.0 ),
293  };
294  __qPainter.drawConvexPolygon( __pqPointFPolygon, 5 );
295  }
296 
297  // ... minutes
298  __qPainter.setWorldTransform( __qTransform );
299  __qPainter.rotate( __fdTimeConverted/10.0 );
300  {
301  static const QPointF __pqPointFPolygon[5] =
302  {
303  QPointF( -15.0, -10.0 ),
304  QPointF( -15.0, -370.0 ),
305  QPointF( 0.0, -400.0 ),
306  QPointF( +15.0, -370.0 ),
307  QPointF( +15.0, -10.0 ),
308  };
309  __qPainter.drawConvexPolygon( __pqPointFPolygon, 5 );
310  }
311 
312  // ... seconds
313  __qPen.setColor( QColor( 255, 128, 0 ) );
314  __qPen.setWidth( 10 );
315  __qPainter.setPen( __qPen );
316  __qPainter.setWorldTransform( __qTransform );
317  __qPainter.rotate( __fdTimeConverted*6.0 );
318  __qPainter.drawLine( QPointF( 0, 0), QPointF( 0, -460 ) );
319 
320  // ... center mask
321  __qPen.setColor( Qt::black );
322  __qPen.setWidth( 0 );
323  __qPainter.setPen( __qPen );
324  __qPainter.setWorldTransform( __qTransform );
325  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 40.0, 40.0 );
326  __qPainter.setBrush( QBrush( Qt::black ) );
327  __qPainter.drawEllipse( QPointF( 0.0, 0.0 ), 30.0, 30.0 );
328 
329  // ... data
330  __qPen.setColor( Qt::white );
331  __qPen.setWidth( 0 );
332  __qPainter.setPen( __qPen );
333  __qFont.setPixelSize( 50.0 );
334  __qFont.setBold( false );
335  __qPainter.setFont( __qFont );
336  {
337  QRectF __qRectFText( QPointF( -125.0, -30.0 ), QSizeF( 250.0, 60.0 ) );
338  __qPainter.drawText( __qRectFText.translated( QPointF( -425.0, -490.0 ) ), Qt::AlignCenter, CUnitTimeDelta::toString( fdSW1TimeAccumulated + ( fdSW1TimeStarted ? microtime()-fdSW1TimeStarted : 0.0 ), CUnitTimeDelta::HMS, 0 ) );
339  __qPainter.drawText( __qRectFText.translated( QPointF( +425.0, -490.0 ) ), Qt::AlignCenter, CUnitTimeDelta::toString( fdSW2TimeAccumulated + ( fdSW2TimeStarted ? microtime()-fdSW2TimeStarted : 0.0 ), CUnitTimeDelta::HMS, 0 ) );
340  __qPainter.drawText( __qRectFText.translated( QPointF( +425.0, +490.0 ) ), Qt::AlignCenter, CUnitTime::toString( _fdTime, _eUnit, CUnitTime::HMS, 0 ) );
341  }
342 }
QPixmap qPixmapBufferBackground
Pixmap buffer used to render and cache the instrument's (static) background.
virtual void draw()
Draws the instrument (resets if the vessel is undefined)
double fdSW2TimeStarted
Stop-watch 2 last started time (stopped if 0)
double fdSW2TimeAccumulated
Stop-watch 2 accumulated time.
double fdSW1TimeAccumulated
Stop-watch 1 accumulated time.
QPixmap qPixmapBuffer
Pixmap buffer used to render and cache the instrument.
virtual void mouseReleaseEvent(QMouseEvent *_pqMouseEvent)
double fdSW1TimeStarted
Stop-watch 1 last started time (stopped if 0)
CUnitTimeZone::EUnit eUnit
Unit for which the last rendering was achieved.
void drawStatic(CUnitTimeZone::EUnit _eUnit)
bool bForceRedraw
Forces the redraw of the instrument (not matter its cache content)
void drawDynamic(CUnitTimeZone::EUnit _eUnit, double _fdTime)
CInstrumentGAChronograph(CVesselCockpit *_poVesselCockpit)
double fdTime
Time at which the last rendering was achieved.
virtual void mouseDoubleClickEvent(QMouseEvent *_pqMouseEvent)
Generic instrument.
Definition: CInstrument.hpp:39
CUnitTimeZone::EUnit getUnitTimeZone()
[Unit] Returns the timezone format/unit
Definition: CSettings.hpp:345
static QString toString(double _fdValue, EUnit _eUnit, int _iPrecision=0)
Returns the formatted represention of the given value, using the specified format/unit and decimal pr...
Time zone (UTC, local) selection class.
static QString toSymbol(EUnit _eUnit)
Returns the human-readable symbol corresponding to the given format/unit ID.
EUnit
Format/unit ID.
static QString toString(double _fdValue, CUnitTimeZone::EUnit _eUnitTimeZone, EUnit _eUnit, int _iPrecision=0)
Returns the formatted represention of the given value, using the specified format/unit and decimal pr...
Definition: CUnitTime.cpp:79
@ HMS
HH:MM:SS.
Definition: CUnitTime.hpp:48
static double toValue(double _fdValue, CUnitTimeZone::EUnit _eUnitTimeZone)
Returns the converted value, using the specified format/unit.
Definition: CUnitTime.cpp:71
[UI] Generic vessel's cockpit view (window)
static CSettings * useSettings()
static constexpr double PI
Definition: QVCT.hpp:45
double microtime()
Returns the system time with microseconds resolution, in seconds.
Definition: main.cpp:30