1/*
2 Copyright (C) 2014 by Elvis Angelaccio <elvis.angelaccio@kdemail.net>
3
4 This file is part of Kronometer.
5
6 Kronometer is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 Kronometer is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Kronometer. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef STOPWATCH_H
21#define STOPWATCH_H
22
23#include <QObject>
24#include <QTime>
25#include <QElapsedTimer>
26
27class QTimerEvent;
28class QDataStream;
29class QDomElement;
30
31/**
32 * @brief A Stopwatch class written in Qt.
33 * Stopwatch is a simple QObject implementing a real stopwatch.
34 * The class provides public slots for start/pause/reset the timer.
35 * A slot for lap recording exists too, but the computing of lap times is not a task of this class:
36 * Stopwatch simply emits a signal, that the receiver can use to compute lap times.
37 */
38class Stopwatch : public QObject
39{
40 Q_OBJECT
41
42public:
43
44 enum Granularity
45 {
46 MILLISECONDS = 1, /**< Stopwatch refreshed every msec. */
47 HUNDREDTHS = 10, /**< Stopwatch refreshed every 10 msec. */
48 TENTHS = 100, /**< Stopwatch refreshed every 100 msec. */
49 SECONDS = 1000 /**< Stopwatch refreshed every sec. */
50 };
51
52 explicit Stopwatch(QObject *parent = nullptr);
53
54 /**
55 * Set the stopwatch refresh granularity
56 * @param g The granularity to be set.
57 */
58 void setGranularity(Granularity g);
59
60 /**
61 * Check if the stopwatch is running
62 * @return true if running, false otherwise
63 */
64 bool isRunning() const;
65
66 /**
67 * Check if the stopwatch is paused
68 * @return true if paused, false otherwise
69 */
70 bool isPaused() const;
71
72 /**
73 * Check if the stopwatch is inactive
74 * @return true if inactive, false otherwise
75 */
76 bool isInactive() const;
77
78 /**
79 * Serialize the stopwatch on the given output stream.
80 * Only a paused stopwatch is meant to be serialized.
81 * @param out The serialization output stream
82 * @return true if the serialization succeeds (i.e. the stopwatch is paused), false otherwise
83 */
84 bool serialize(QDataStream& out);
85
86 /**
87 * De-serialize the stopwatch from the given input stream.
88 * Only an inactive stopwatch is meant to be serialized.
89 * @param in The serialization input stream
90 * @return true if the deserialization succeeds (i.e. the stopwatch is inactive), false otherwise
91 */
92 bool deserialize(QDataStream& in);
93
94 /**
95 * Serialize the stopwatch on the given XML DOM element.
96 * The serialization is implemented by adding an attribute (with the given name) to the element.
97 * Only a paused stopwatch is meant to be serialized.
98 * @param element The XML DOM element to be used as serialization output.
99 * @param attributeName The name of the attribute to be added to the element.
100 * @return true if the serialization succeeds (i.e. the stopwatch is paused), false otherwise
101 */
102 bool serialize(QDomElement& element, const QString& attributeName);
103
104 /**
105 * De-serialize the stopwatch from the given XML DOM element.
106 * The deserialization is implemented by reading an attribute (with the given name) from the element.
107 * Only an inactive stopwatch is meant to be serialized.
108 * @param element The XML DOM element to be used as serialization input.
109 * @param attributeName The name of the attribute to be read.
110 * @return true if the deserialization succeeds (i.e. the stopwatch is inactive and the attribute is valid), false otherwise
111 */
112 bool deserialize(QDomElement& element, const QString& attributeName);
113
114public slots:
115
116 /**
117 * Start the stopwatch, if inactive or paused.
118 */
119 void onStart();
120
121 /**
122 * Pause the stopwatch, if running.
123 */
124 void onPause();
125
126 /**
127 * Reset the stopwatch to the inactive state.
128 */
129 void onReset();
130
131 /**
132 * Tells the stopwatch to emits a signal with the last lap time.
133 */
134 void onLap();
135
136signals:
137
138 /**
139 * Emits a signal with the last lap *absolute* time.
140 * This class does not compute *relatives* lap times.
141 * You can compute them simply by the difference between consecutives absolute times.
142 * @param lapTime The absolute time of the last lap.
143 */
144 void lap(const QTime& lapTime);
145
146 /**
147 * Emits a signal with the current stopwatch time.
148 * @param t Current stopwatch time.
149 */
150 void time(const QTime& t);
151
152protected:
153
154 void timerEvent(QTimerEvent *event);
155
156private:
157
158 enum class State
159 {
160 INACTIVE, /**< Inactive stopwatch. */
161 RUNNING, /**< Running stopwatch. */
162 PAUSED /**< Paused stopwatch. */
163 };
164
165 static const int INACTIVE_TIMER_ID = -1; /** Used for timerId initialization */
166
167 int timerId; /** ID for the QObject timer */
168 qint64 accumulator; /** milliseconds internal counter */
169 State state; /** Stopwatch current state */
170 Granularity granularity; /** Stopwatch current granularity */
171
172 const QTime zero; /** Empty time to be used to add elapsed milliseconds */
173 QElapsedTimer elapsedTimer; /** Stopwatch core class*/
174};
175
176
177
178#endif
179