Two little bugfixes, first is that formatTime() should not be called with true for...
[rsibreak.git] / src / rsistats.cpp
blob8229fb81bb04cbe9a8729f32bcc39d299cba5aaf
1 /* This file is part of the KDE project
2 Copyright (C) 2006 Bram Schoenmakers <bramschoenmakers@kde.nl>
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #include <qwhatsthis.h>
21 #include <kdebug.h>
22 #include <kglobal.h>
23 #include <klocale.h>
25 #include "rsistats.h"
26 #include "rsistatitem.h"
28 RSIStats::RSIStats()
30 m_statistics.insert( TOTAL_TIME, new RSIStatItem(i18n("Total recorded time") ) );
31 m_statistics[TOTAL_TIME]->addDerivedItem( ACTIVITY_PERC );
33 m_statistics.insert( ACTIVITY, new RSIStatItem(i18n("Total time of activity") ) );
34 m_statistics[ACTIVITY]->addDerivedItem( ACTIVITY_PERC );
35 m_statistics[ACTIVITY]->addDerivedItem( ACTIVITY_PERC_MINUTE );
36 m_statistics[ACTIVITY]->addDerivedItem( ACTIVITY_PERC_HOUR );
37 m_statistics[ACTIVITY]->addDerivedItem( ACTIVITY_PERC_6HOUR );
39 m_statistics.insert( IDLENESS, new RSIStatItem(i18n("Total time being idle") ) );
40 m_statistics[IDLENESS]->addDerivedItem( ACTIVITY_PERC_MINUTE );
41 m_statistics[IDLENESS]->addDerivedItem( ACTIVITY_PERC_HOUR );
42 m_statistics[IDLENESS]->addDerivedItem( ACTIVITY_PERC_6HOUR );
44 m_statistics.insert( ACTIVITY_PERC, new RSIStatItem(i18n("Percentage of activity"), 0 ) );
46 m_statistics.insert( MAX_IDLENESS, new RSIStatItem(i18n("Maximum idle period") ) );
47 m_statistics[MAX_IDLENESS]->addDerivedItem( IDLENESS );
49 m_statistics.insert( CURRENT_IDLE_TIME, new RSIStatItem(i18n("Current idle period") ) );
51 m_statistics.insert( TINY_BREAKS, new RSIStatItem(i18n("Total number of short breaks") ) );
52 m_statistics[TINY_BREAKS]->addDerivedItem( PAUSE_SCORE );
53 m_statistics[TINY_BREAKS]->addDerivedItem( LAST_TINY_BREAK );
55 QDateTime dt( QDate( -1, -1, -1 ), QTime( -1, -1, -1 ) );
56 m_statistics.insert( LAST_TINY_BREAK, new RSIStatItem(i18n("Last short break"), dt ) );
58 m_statistics.insert( TINY_BREAKS_SKIPPED,
59 new RSIStatItem(i18n("Number of skipped short breaks (user)") ) );
60 m_statistics[TINY_BREAKS_SKIPPED]->addDerivedItem( PAUSE_SCORE );
63 m_statistics.insert( IDLENESS_CAUSED_SKIP_TINY,
64 new RSIStatItem(i18n("Number of skipped short breaks (idle)") ) );
66 m_statistics.insert( BIG_BREAKS, new RSIStatItem(i18n("Total number of long breaks") ) );
67 m_statistics[BIG_BREAKS]->addDerivedItem( PAUSE_SCORE );
68 m_statistics[BIG_BREAKS]->addDerivedItem( LAST_BIG_BREAK );
70 m_statistics.insert( LAST_BIG_BREAK, new RSIStatItem(i18n("Last long break"), dt ) );
72 m_statistics.insert( BIG_BREAKS_SKIPPED,
73 new RSIStatItem(i18n("Number of skipped long breaks (user)") ) );
74 m_statistics[BIG_BREAKS_SKIPPED]->addDerivedItem( PAUSE_SCORE );
76 m_statistics.insert( IDLENESS_CAUSED_SKIP_BIG,
77 new RSIStatItem(i18n("Number of skipped long breaks (idle)") ) );
79 m_statistics.insert( PAUSE_SCORE, new RSIStatItem(i18n("Pause score"), 100 ) );
81 m_statistics.insert( ACTIVITY_PERC_MINUTE, new RSIStatBitArrayItem( i18n("Percentage of activity last minute:"), QVariant( 0 ), 60 ) );
82 m_statistics.insert( ACTIVITY_PERC_HOUR, new RSIStatBitArrayItem( i18n("Percentage of activity last hour:"), QVariant( 0 ), 3600 ) );
83 m_statistics.insert( ACTIVITY_PERC_6HOUR, new RSIStatBitArrayItem( i18n("Percentage of activity last 6 hours:"), QVariant( 0 ), 6 * 3600 ) );
85 // initialise labels
86 QMap<RSIStat,RSIStatItem *>::Iterator it;
87 for ( it = m_statistics.begin(); it != m_statistics.end(); ++it )
89 m_labels[it.key()] = new QLabel( 0 );
90 QWhatsThis::add( m_labels[it.key()], getWhatsThisText( it.key() ) );
91 QWhatsThis::add( m_statistics[it.key()]->getDescription(), getWhatsThisText( it.key() ) );
94 // initialise statistics
95 updateLabels();
96 reset();
99 RSIStats::~RSIStats()
101 QMap<RSIStat,QLabel *>::Iterator it;
102 for ( it = m_labels.begin() ; it != m_labels.end(); ++it )
104 delete it.data();
105 it.data() = 0L;
108 QMap<RSIStat,RSIStatItem *>::Iterator it2;
109 for ( it2 = m_statistics.begin() ; it2 != m_statistics.end(); ++it2 )
111 QLabel *l = it2.data()->getDescription();
112 delete l;
113 l = 0L;
114 delete it2.data();
118 void RSIStats::reset()
120 QMap<RSIStat,RSIStatItem *>::ConstIterator it;
121 for( it = m_statistics.begin(); it != m_statistics.end(); ++it )
123 m_statistics[ it.key() ]->reset();
124 updateStat( it.key(), /* update derived stats */ false );
128 void RSIStats::increaseStat( RSIStat stat, int delta )
130 QVariant v = m_statistics[stat]->getValue();
132 if ( v.type() == QVariant::Int )
133 m_statistics[stat]->setValue( v.toInt() + delta );
134 else if ( v.type() == QVariant::Double )
135 m_statistics[stat]->setValue( v.toDouble() + (double)delta );
136 else if ( v.type() == QVariant::DateTime )
137 m_statistics[stat]->setValue(
138 QDateTime(v.toDateTime()).addSecs( delta ));
140 updateStat( stat );
143 void RSIStats::setStat( RSIStat stat, QVariant val, bool ifmax )
145 QVariant v = m_statistics[stat]->getValue();
147 if ( !ifmax ||
148 (v.type() == QVariant::Int && val.toInt()>v.toInt()) ||
149 (v.type() == QVariant::Double && val.toDouble()>v.toDouble()) ||
150 (v.type() == QVariant::DateTime && val.toDateTime()>v.toDateTime()))
151 m_statistics[stat]->setValue( val );
153 // WATCH OUT: IDLENESS is derived from MAX_IDLENESS and needs to be
154 // updated regardless if a new value is set.
155 updateStat( stat );
158 void RSIStats::updateDependentStats( RSIStat stat )
160 QValueList<RSIStat> stats = m_statistics[ stat ]->getDerivedItems();
161 QValueList<RSIStat>::ConstIterator it;
162 for( it = stats.begin() ; it != stats.end(); ++it )
164 switch( (*it) )
166 case PAUSE_SCORE:
168 double a = m_statistics[ TINY_BREAKS_SKIPPED ]->getValue().toDouble();
169 double b = m_statistics[ BIG_BREAKS_SKIPPED ]->getValue().toDouble();
170 double c = m_statistics[ IDLENESS_CAUSED_SKIP_TINY ]->getValue().toDouble();
171 double d = m_statistics[ IDLENESS_CAUSED_SKIP_BIG ]->getValue().toDouble();
173 RSIGlobals *glbl = RSIGlobals::instance();
174 double ratio = (double)(glbl->intervals()["big_maximized"]) /
175 (double)(glbl->intervals()["tiny_maximized"]);
177 double skipped = a - c + ratio * ( b - d );
178 skipped = skipped < 0 ? 0 : skipped;
180 double total = m_statistics[ TINY_BREAKS ]->getValue().toDouble();
181 total += ratio * m_statistics[ BIG_BREAKS ]->getValue().toDouble();
183 if ( total > 0 )
184 m_statistics[ *it ]->setValue( 100 - ( ( skipped / total ) * 100 ) );
185 else
186 m_statistics[ *it ]->setValue( 0 );
188 updateStat( *it );
189 break;
192 case IDLENESS:
194 increaseStat( IDLENESS );
195 break;
198 case ACTIVITY_PERC:
201 seconds of activity
202 activity_percentage = 100 - -------------------
203 total seconds
206 double activity = m_statistics[ ACTIVITY ]->getValue().toDouble();
207 double total = m_statistics[TOTAL_TIME]->getValue().toDouble();
209 if ( total > 0 )
210 m_statistics[ *it ]->setValue( (activity / total) * 100 );
211 else
212 m_statistics[ *it ]->setValue( 0 );
214 updateStat( *it );
215 break;
218 case ACTIVITY_PERC_MINUTE:
219 case ACTIVITY_PERC_HOUR:
220 case ACTIVITY_PERC_6HOUR:
222 if ( stat == ACTIVITY )
223 static_cast<RSIStatBitArrayItem *>(m_statistics[*it])->setActivity();
224 else
225 static_cast<RSIStatBitArrayItem *>(m_statistics[*it])->setIdle();
227 updateStat( *it );
228 break;
231 case LAST_BIG_BREAK:
233 setStat( LAST_BIG_BREAK, QDateTime::currentDateTime() );
234 break;
237 case LAST_TINY_BREAK:
239 setStat( LAST_TINY_BREAK, QDateTime::currentDateTime() );
240 break;
243 default: ;// nada
248 void RSIStats::updateStat( RSIStat stat, bool updateDerived )
250 if ( updateDerived )
251 updateDependentStats( stat );
252 updateLabel( stat );
255 void RSIStats::updateLabel( RSIStat stat )
257 QLabel *l = m_labels[ stat ];
258 QColor c;
259 double v;
261 switch ( stat )
263 // integer values representing a time
264 case TOTAL_TIME:
265 case ACTIVITY:
266 case IDLENESS:
267 case MAX_IDLENESS:
268 case CURRENT_IDLE_TIME:
269 l->setText( RSIGlobals::instance()->formatSeconds(
270 m_statistics[ stat ]->getValue().toInt() ) );
271 break;
273 // plain integer values
274 case TINY_BREAKS:
275 case TINY_BREAKS_SKIPPED:
276 case IDLENESS_CAUSED_SKIP_TINY:
277 case BIG_BREAKS:
278 case BIG_BREAKS_SKIPPED:
279 case IDLENESS_CAUSED_SKIP_BIG:
280 l->setText( QString::number(
281 m_statistics[ stat ]->getValue().toInt() ) );
282 break;
284 // doubles
285 case PAUSE_SCORE:
286 v = m_statistics[ stat ]->getValue().toDouble();
287 setColor( stat, QColor( (int)(255 - 2.55 * v), (int)(1.60 * v), 0 ) );
288 l->setText( QString::number(
289 m_statistics[ stat ]->getValue().toDouble(), 'f', 1 ) );
290 break;
291 case ACTIVITY_PERC:
292 case ACTIVITY_PERC_MINUTE:
293 case ACTIVITY_PERC_HOUR:
294 case ACTIVITY_PERC_6HOUR:
295 v = m_statistics[stat]->getValue().toDouble();
296 setColor( stat, QColor( (int)(2.55 * v), (int)(160 - 1.60 * v), 0 ) );
297 l->setText( QString::number(
298 m_statistics[ stat ]->getValue().toDouble(), 'f', 1 ) );
299 break;
301 // datetimes
302 case LAST_BIG_BREAK:
303 case LAST_TINY_BREAK:
305 KLocale *localize = KGlobal::locale();
306 QTime when( m_statistics[ stat ]->getValue().asTime() );
307 when.isValid() ? l->setText( localize->formatTime(when, true, false) )
308 : l->setText( QString::null );
309 break;
312 default: ; // nada
315 // some stats need a %
316 if ( stat == PAUSE_SCORE || stat == ACTIVITY_PERC || stat == ACTIVITY_PERC_MINUTE ||
317 stat == ACTIVITY_PERC_HOUR || stat == ACTIVITY_PERC_6HOUR )
318 l->setText( l->text() + '%' );
321 void RSIStats::updateLabels()
323 QMapConstIterator<RSIStat,RSIStatItem *> it;
324 for ( it = m_statistics.begin() ; it != m_statistics.end() ; ++it )
325 updateLabel( it.key() );
328 QVariant RSIStats::getStat( RSIStat stat ) const
330 return m_statistics[ stat ]->getValue();
333 QLabel *RSIStats::getLabel( RSIStat stat ) const
335 return m_labels[ stat ];
338 QLabel *RSIStats::getDescription( RSIStat stat ) const
340 return m_statistics[stat]->getDescription();
343 QString RSIStats::getWhatsThisText( RSIStat stat ) const
345 switch ( stat )
347 case TOTAL_TIME: return i18n("This is the total time RSIBreak has been running.");
348 case ACTIVITY: return i18n("This is the total amount of time you used the "
349 "keyboard or mouse.");
350 case IDLENESS: return i18n("This is the total amount of time you did not use "
351 "the keyboard or mouse.");
352 case ACTIVITY_PERC: return i18n("This is a percentage of activity, based on the "
353 "periods of activity vs. the total time RSIBreak has been running."
354 "The color indicates the level of your activity. When the color is"
355 "close to full red it's recommended to lower your work pace.");
356 case MAX_IDLENESS: return i18n("This is the longest period of inactivity measured "
357 "while RSIBreak has been running.");
358 case TINY_BREAKS: return i18n("This is the total number of short breaks");
359 case LAST_TINY_BREAK: return i18n("This is the time of the last finished short break."
360 "The color of this texts gradually turns from green to red,"
361 "indicating when you can expect the next tiny break.");
362 case TINY_BREAKS_SKIPPED: return i18n("This is the total number of short breaks "
363 "which you skipped.");
364 case IDLENESS_CAUSED_SKIP_TINY: return i18n("This is the total number of short breaks "
365 "which were skipped because you were idle.");
366 case BIG_BREAKS: return i18n("This is the total number of long breaks.");
367 case LAST_BIG_BREAK: return i18n("This is the time of the last finished long break."
368 "The color of this texts gradually turns from green to red,"
369 "indicating when you can expect the next big break.");
370 case BIG_BREAKS_SKIPPED: return i18n("This is the total number of long breaks "
371 "which you skipped.");
372 case IDLENESS_CAUSED_SKIP_BIG: return i18n("This is the total number of long breaks "
373 "which were skipped because you were idle." );
374 case PAUSE_SCORE: return i18n("This is an indication of how well you behaved "
375 "with the breaks. It decreases everytime you skip a break.");
376 case CURRENT_IDLE_TIME: return i18n("This is the current idle time.");
377 case ACTIVITY_PERC_MINUTE: return i18n("This is a percentage of activity during the last minute."
378 "The color indicates the level of your activity. When the color is"
379 "close to full red it's recommended to lower your work pace.");
380 case ACTIVITY_PERC_HOUR: return i18n("This is a percentage of activity during the last hour."
381 "The color indicates the level of your activity. When the color is"
382 "close to full red it's recommended to lower your work pace.");
383 case ACTIVITY_PERC_6HOUR: return i18n("This is a percentage of activity during the last 6 hours."
384 "The color indicates the level of your activity. When the color is"
385 "close to full red it's recommended to lower your work pace.");
386 default: ;
389 return QString::null;
392 void RSIStats::setColor( RSIStat stat, QColor color )
394 m_statistics[ stat ]->getDescription()->setPaletteForegroundColor( color );
395 m_labels[ stat ]->setPaletteForegroundColor( color );