00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <qdatetime.h>
00026 #include <qpaintdevicemetrics.h>
00027 #include <qpainter.h>
00028 #include <qmap.h>
00029
00030 #include <kglobal.h>
00031 #include <kdebug.h>
00032 #include <klocale.h>
00033 #include <event.h>
00034
00035 #include "karmutility.h"
00036 #include "timekard.h"
00037 #include "task.h"
00038 #include "taskview.h"
00039 #include <assert.h>
00040
00041 const int taskWidth = 40;
00042 const int timeWidth = 6;
00043 const int totalTimeWidth = 7;
00044 const int reportWidth = taskWidth + timeWidth;
00045
00046 const QString cr = QString::fromLatin1("\n");
00047
00048 QString TimeKard::totalsAsText(TaskView* taskview, bool justThisTask, WhichTime which)
00049
00050 {
00051 kdDebug(5970) << "Entering TimeKard::totalsAsText" << endl;
00052 QString retval;
00053 QString line;
00054 QString buf;
00055 long sum;
00056
00057 line.fill('-', reportWidth);
00058 line += cr;
00059
00060
00061 retval += i18n("Task Totals") + cr;
00062 retval += KGlobal::locale()->formatDateTime(QDateTime::currentDateTime());
00063 retval += cr + cr;
00064 retval += QString(QString::fromLatin1("%1 %2"))
00065 .arg(i18n("Time"), timeWidth)
00066 .arg(i18n("Task"));
00067 retval += cr;
00068 retval += line;
00069
00070
00071 if (taskview->current_item())
00072 {
00073 if (justThisTask)
00074 {
00075
00076 sum = which == TotalTime ? taskview->current_item()->totalTime() : taskview->current_item()->sessionTime();
00077 printTask(taskview->current_item(), retval, 0, which);
00078 }
00079 else
00080 {
00081 sum = 0;
00082 for (Task* task= taskview->item_at_index(0); task;
00083 task= task->nextSibling())
00084 {
00085 kdDebug(5970) << "Copying task " << task->name() << endl;
00086 int time = which == TotalTime ? task->totalTime() : task->totalSessionTime();
00087 sum += time;
00088 if ( time || task->firstChild() )
00089 printTask(task, retval, 0, which);
00090 }
00091 }
00092
00093
00094 buf.fill('-', reportWidth);
00095 retval += QString(QString::fromLatin1("%1")).arg(buf, timeWidth) + cr;
00096 retval += QString(QString::fromLatin1("%1 %2"))
00097 .arg(formatTime(sum),timeWidth)
00098 .arg(i18n("Total"));
00099 }
00100 else
00101 retval += i18n("No tasks.");
00102
00103 return retval;
00104 }
00105
00106
00107 void TimeKard::printTask(Task *task, QString &s, int level, WhichTime which)
00108 {
00109 QString buf;
00110
00111 s += buf.fill(' ', level);
00112 s += QString(QString::fromLatin1("%1 %2"))
00113 .arg(formatTime(which == TotalTime?task->totalTime():task->totalSessionTime()), timeWidth)
00114 .arg(task->name());
00115 s += cr;
00116
00117 for (Task* subTask = task->firstChild();
00118 subTask;
00119 subTask = subTask->nextSibling())
00120 {
00121 int time = which == TotalTime ? subTask->totalTime() : subTask->totalSessionTime();
00122 if (time)
00123 printTask(subTask, s, level+1, which);
00124 }
00125 }
00126
00127 void TimeKard::printTaskHistory(const Task *task,
00128 const QMap<QString,long>& taskdaytotals,
00129 QMap<QString,long>& daytotals,
00130 const QDate& from,
00131 const QDate& to,
00132 const int level, QString& s, bool totalsOnly)
00133 {
00134 long sectionsum = 0;
00135 for ( QDate day = from; day <= to; day = day.addDays(1) )
00136 {
00137 QString daykey = day.toString(QString::fromLatin1("yyyyMMdd"));
00138 QString daytaskkey = QString::fromLatin1("%1_%2")
00139 .arg(daykey)
00140 .arg(task->uid());
00141
00142 if (taskdaytotals.contains(daytaskkey))
00143 {
00144 if ( !totalsOnly )
00145 {
00146 s += QString::fromLatin1("%1")
00147 .arg(formatTime(taskdaytotals[daytaskkey]/60), timeWidth);
00148 }
00149 sectionsum += taskdaytotals[daytaskkey];
00150
00151 if (daytotals.contains(daykey))
00152 daytotals.replace(daykey, daytotals[daykey] + taskdaytotals[daytaskkey]);
00153 else
00154 daytotals.insert(daykey, taskdaytotals[daytaskkey]);
00155 }
00156 else if ( !totalsOnly )
00157 {
00158 QString buf;
00159 buf.fill(' ', timeWidth);
00160 s += buf;
00161 }
00162 }
00163
00164
00165 s += QString::fromLatin1("%1").arg(formatTime(sectionsum/60), totalTimeWidth);
00166
00167
00168 QString buf;
00169 s += buf.fill(' ', level + 1);
00170 s += QString::fromLatin1("%1").arg(task->name());
00171 s += cr;
00172
00173 for (Task* subTask = task->firstChild();
00174 subTask;
00175 subTask = subTask->nextSibling())
00176 {
00177
00178 printTaskHistory(subTask, taskdaytotals, daytotals, from, to, level+1, s, totalsOnly);
00179 }
00180 }
00181
00182 QString TimeKard::sectionHistoryAsText(
00183 TaskView* taskview,
00184 const QDate& sectionFrom, const QDate& sectionTo,
00185 const QDate& from, const QDate& to,
00186 const QString& name,
00187 bool justThisTask, bool totalsOnly)
00188 {
00189
00190 const int sectionReportWidth = taskWidth + ( totalsOnly ? 0 : sectionFrom.daysTo(sectionTo) * timeWidth ) + totalTimeWidth;
00191 assert( sectionReportWidth > 0 );
00192 QString line;
00193 line.fill('-', sectionReportWidth);
00194 line += cr;
00195
00196 QValueList<HistoryEvent> events;
00197 if ( sectionFrom < from && sectionTo > to)
00198 {
00199 events = taskview->getHistory(from, to);
00200 }
00201 else if ( sectionFrom < from )
00202 {
00203 events = taskview->getHistory(from, sectionTo);
00204 }
00205 else if ( sectionTo > to)
00206 {
00207 events = taskview->getHistory(sectionFrom, to);
00208 }
00209 else
00210 {
00211 events = taskview->getHistory(sectionFrom, sectionTo);
00212 }
00213
00214 QMap<QString, long> taskdaytotals;
00215 QMap<QString, long> daytotals;
00216
00217
00218
00219
00220
00221
00222 for (QValueList<HistoryEvent>::iterator event = events.begin(); event != events.end(); ++event)
00223 {
00224 QString daykey = (*event).start().date().toString(QString::fromLatin1("yyyyMMdd"));
00225 QString daytaskkey = QString::fromLatin1("%1_%2")
00226 .arg(daykey)
00227 .arg((*event).todoUid());
00228
00229 if (taskdaytotals.contains(daytaskkey))
00230 taskdaytotals.replace(daytaskkey,
00231 taskdaytotals[daytaskkey] + (*event).duration());
00232 else
00233 taskdaytotals.insert(daytaskkey, (*event).duration());
00234 }
00235
00236 QString retval;
00237
00238 retval += cr + cr;
00239 QString buf;
00240 if ( name.length() < (unsigned int)sectionReportWidth )
00241 buf.fill(' ', int((sectionReportWidth - name.length()) / 2));
00242 retval += buf + name + cr;
00243
00244 if ( !totalsOnly )
00245 {
00246
00247 for (QDate day = sectionFrom; day <= sectionTo; day = day.addDays(1))
00248 {
00249 retval += QString::fromLatin1("%1").arg(day.day(), timeWidth);
00250 }
00251 retval += cr;
00252 retval += line;
00253 }
00254
00255
00256 if (events.empty())
00257 {
00258 retval += " ";
00259 retval += i18n("No hours logged.");
00260 }
00261 else
00262 {
00263 if (justThisTask)
00264 {
00265 printTaskHistory(taskview->current_item(), taskdaytotals, daytotals,
00266 sectionFrom, sectionTo, 0, retval, totalsOnly);
00267 }
00268 else
00269 {
00270 for (Task* task= taskview->current_item(); task;
00271 task= task->nextSibling())
00272 {
00273 printTaskHistory(task, taskdaytotals, daytotals,
00274 sectionFrom, sectionTo, 0, retval, totalsOnly);
00275 }
00276 }
00277 retval += line;
00278
00279
00280 long sum = 0;
00281 for (QDate day = sectionFrom; day <= sectionTo; day = day.addDays(1))
00282 {
00283 QString daykey = day.toString(QString::fromLatin1("yyyyMMdd"));
00284
00285 if (daytotals.contains(daykey))
00286 {
00287 if ( !totalsOnly )
00288 {
00289 retval += QString::fromLatin1("%1")
00290 .arg(formatTime(daytotals[daykey]/60), timeWidth);
00291 }
00292 sum += daytotals[daykey];
00293 }
00294 else if ( !totalsOnly )
00295 {
00296 buf.fill(' ', timeWidth);
00297 retval += buf;
00298 }
00299 }
00300
00301 retval += QString::fromLatin1("%1 %2")
00302 .arg(formatTime(sum/60), totalTimeWidth)
00303 .arg(i18n("Total"));
00304 }
00305 return retval;
00306 }
00307
00308 QString TimeKard::historyAsText(TaskView* taskview, const QDate& from,
00309 const QDate& to, bool justThisTask, bool perWeek, bool totalsOnly)
00310 {
00311
00312 QString retval;
00313 retval += totalsOnly ? i18n("Task Totals") : i18n("Task History");
00314 retval += cr;
00315 retval += i18n("From %1 to %2")
00316 .arg(KGlobal::locale()->formatDate(from))
00317 .arg(KGlobal::locale()->formatDate(to));
00318 retval += cr;
00319 retval += i18n("Printed on: %1")
00320 .arg(KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()));
00321
00322 if ( perWeek )
00323 {
00324
00325 QValueList<Week> weeks = Week::weeksFromDateRange(from, to);
00326 for (QValueList<Week>::iterator week = weeks.begin(); week != weeks.end(); ++week)
00327 {
00328 retval += sectionHistoryAsText( taskview, (*week).start(), (*week).end(), from, to, (*week).name(), justThisTask, totalsOnly );
00329 }
00330 } else
00331 {
00332 retval += sectionHistoryAsText( taskview, from, to, from, to, "", justThisTask, totalsOnly );
00333 }
00334 return retval;
00335 }
00336
00337 Week::Week() {}
00338
00339 Week::Week(QDate from)
00340 {
00341 _start = from;
00342 }
00343
00344 QDate Week::start() const
00345 {
00346 return _start;
00347 }
00348
00349 QDate Week::end() const
00350 {
00351 return _start.addDays(6);
00352 }
00353
00354 QString Week::name() const
00355 {
00356 return i18n("Week of %1").arg(KGlobal::locale()->formatDate(start()));
00357 }
00358
00359 QValueList<Week> Week::weeksFromDateRange(const QDate& from, const QDate& to)
00360 {
00361 QDate start;
00362 QValueList<Week> weeks;
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 start = from.addDays(
00375 -((7 - KGlobal::locale()->weekStartDay() + from.dayOfWeek()) % 7));
00376
00377 for (QDate d = start; d <= to; d = d.addDays(7))
00378 weeks.append(Week(d));
00379
00380 return weeks;
00381 }
00382