2 * Report.cpp - TaskJuggler
4 * Copyright (c) 2001, 2002, 2003, 2004 by Chris Schlaeger <cs@kde.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
15 #include "TjMessageHandler.h"
16 #include "tjlib-internal.h"
20 #include "ExpressionTree.h"
21 #include "TaskTreeIterator.h"
22 #include "ResourceTreeIterator.h"
23 #include "AccountTreeIterator.h"
26 Report::Report(Project* p, const QString& f, const QString& df, int dl) :
34 weekStartsMonday(p->getWeekStartsMonday()),
38 maxDepthResourceList(1),
39 maxDepthAccountList(1),
43 timeFormat(p->getTimeFormat()),
44 shortTimeFormat(p->getShortTimeFormat()),
45 numberFormat(p->getNumberFormat()),
46 currencyFormat(p->getCurrencyFormat()),
48 resourceSortCriteria(),
49 accountSortCriteria(),
58 for (int i = 0; i < CoreAttributesList::maxSortingLevel; ++i)
60 taskSortCriteria[i] = CoreAttributesList::SequenceUp;
61 resourceSortCriteria[i] = CoreAttributesList::SequenceUp;
62 accountSortCriteria[i] = CoreAttributesList::SequenceUp;
75 delete rollUpResource;
83 if (fileName == "--" || fileName == ".")
85 if (!f.open(IO_WriteOnly, stdout))
87 TJMH.errorMessage(i18n("Cannout open stdout"));
93 QString fullFileName = getFullFileName();
94 f.setName(fullFileName);
96 if (!f.open(IO_WriteOnly))
99 (QString(i18n("Cannot open report file %1!\n"))
100 .arg(fullFileName.latin1()));
116 Report::getFullFileName() const
118 QString fullFileName = fileName;
119 // Check if the fileName is not an absolute file name.
120 if (fileName[0] != '/')
122 // Prepend the path of the file where the report was defined, so
123 // relative report file names are always interpreted relative to
126 if (defFileName[0] == '/')
127 path = defFileName.left(defFileName.findRev('/', -1) + 1);
128 fullFileName = path + fileName;
135 Report::setTaskSorting(int sc, int level)
137 if (level >= 0 && level < CoreAttributesList::maxSortingLevel)
139 if ((sc == CoreAttributesList::TreeMode && level > 0) ||
140 !TaskList::isSupportedSortingCriteria(sc & 0xFFFF))
142 taskSortCriteria[level] = sc;
150 Report::setResourceSorting(int sc, int level)
152 if (level >= 0 && level < CoreAttributesList::maxSortingLevel)
154 if ((sc == CoreAttributesList::TreeMode && level > 0) ||
155 !ResourceList::isSupportedSortingCriteria(sc & 0xFFFF))
157 resourceSortCriteria[level] = sc;
165 Report::setAccountSorting(int sc, int level)
167 if (level >= 0 && level < CoreAttributesList::maxSortingLevel)
169 if ((sc == CoreAttributesList::TreeMode && level > 0) ||
170 !AccountList::isSupportedSortingCriteria(sc & 0xFFFF))
172 accountSortCriteria[level] = sc;
180 Report::isHidden(const CoreAttributes* c, ExpressionTree* et) const
182 if (!taskRoot.isEmpty() && c->getType() == CA_Task &&
183 taskRoot != c->getId().left(taskRoot.length()))
191 et->clearSymbolTable();
192 QStringList allFlags = project->getAllowedFlags();
193 for (QStringList::Iterator ait = allFlags.begin(); ait != allFlags.end();
197 QStringList flags = c->getFlagList();
198 for (QStringList::Iterator it = flags.begin(); it != flags.end(); ++it)
201 et->registerSymbol(*it, 1);
206 et->registerSymbol(*ait, 0);
208 return et->evalAsInt(c) != 0;
212 Report::isRolledUp(const CoreAttributes* c, ExpressionTree* et) const
217 et->clearSymbolTable();
218 QStringList allFlags = project->getAllowedFlags();
219 for (QStringList::Iterator ait = allFlags.begin(); ait != allFlags.end();
223 QStringList flags = c->getFlagList();
224 for (QStringList::Iterator it = flags.begin(); it != flags.end(); ++it)
227 et->registerSymbol(*it, 1);
232 et->registerSymbol(*ait, 0);
234 return et->evalAsInt(c) != 0;
238 Report::setHideTask(ExpressionTree* et)
245 Report::setRollUpTask(ExpressionTree* et)
252 Report::setHideResource(ExpressionTree* et)
259 Report::setRollUpResource(ExpressionTree* et)
261 delete rollUpResource;
266 Report::setHideAccount(ExpressionTree* et)
273 Report::setRollUpAccount(ExpressionTree* et)
275 delete rollUpAccount;
280 Report::filterTaskList(TaskList& filteredList, const Resource* r,
281 ExpressionTree* hideExp, ExpressionTree* rollUpExp)
284 /* Create a new list that contains only those tasks that were not
286 filteredList.clear();
287 for (TaskListIterator tli(project->getTaskListIterator());
290 bool resourceLoadedInAnyScenario = false;
291 if (r != 0 && (*tli)->isLeaf())
293 QValueList<int>::const_iterator it;
294 for (it = scenarios.begin(); it != scenarios.end(); ++it)
295 if ((*tli)->isBookedResource(*it, r))
297 resourceLoadedInAnyScenario = true;
301 bool taskOverlapsInAnyScenario = false;
302 Interval iv(start, end);
303 QValueList<int>::const_iterator it;
304 for (it = scenarios.begin(); it != scenarios.end(); ++it)
305 if (iv.overlaps(Interval((*tli)->getStart(*it),
306 (*tli)->getEnd(*it) ==
307 (*tli)->getStart(*it) - 1 ?
308 (*tli)->getStart(*it) :
309 (*tli)->getEnd(*it))))
311 taskOverlapsInAnyScenario = true;
314 if (taskOverlapsInAnyScenario &&
315 (r == 0 || resourceLoadedInAnyScenario) &&
316 !isHidden(*tli, hideExp))
318 filteredList.append(tli);
320 if (hideExp && hideExp->getErrorFlag())
324 /* In tasktree sorting mode we need to make sure that we don't hide
325 * parents of shown tasks. */
326 TaskList list = filteredList;
327 if (taskSortCriteria[0] == CoreAttributesList::TreeMode)
329 for (TaskListIterator tli(filteredList); *tli != 0; ++tli)
331 // Do not add the taskRoot task or any of it's parents.
332 for (Task* p = (*tli)->getParent();
333 p != 0 && (p->getId() + "." != taskRoot);
335 if (list.containsRef(p) == 0)
344 /* Now we have to remove all sub tasks of rolled-up tasks
345 * from the filtered list */
346 for (TaskListIterator tli(project->getTaskListIterator());
349 if (isRolledUp(*tli, rollUpExp))
350 for (TaskTreeIterator tti(*tli, parentAfterLeaves);
353 filteredList.removeRef(*tti);
354 if (rollUpExp && rollUpExp->getErrorFlag())
362 Report::sortTaskList(TaskList& filteredList)
364 /* The sorting can only honor the first scenario. Other scenarios are
365 * ignort for the sorting. */
366 filteredList.setSortScenario(scenarios[0]);
368 for (int i = 0; i < CoreAttributesList::maxSortingLevel; i++)
369 filteredList.setSorting(taskSortCriteria[i], i);
374 Report::filterResourceList(ResourceList& filteredList, const Task* t,
375 ExpressionTree* hideExp, ExpressionTree* rollUpExp)
378 /* Create a new list that contains only those resources that were
380 filteredList.clear();
381 for (ResourceListIterator rli(project->getResourceListIterator());
384 bool taskLoadedInAnyScenario = false;
385 if (t != 0 && t->isLeaf())
387 QValueList<int>::const_iterator it;
388 for (it = scenarios.begin(); it != scenarios.end();
390 if ((*rli)->getEffectiveLoad(*it, Interval(start, end),
391 AllAccounts, t) > 0.0)
393 taskLoadedInAnyScenario = true;
397 if (!isHidden(*rli, hideExp) &&
398 (t == 0 || taskLoadedInAnyScenario))
400 filteredList.append(*rli);
402 if (hideExp && hideExp->getErrorFlag())
406 /* In resourcetree sorting mode we need to make sure that we don't
407 * hide parents of shown resources. */
408 ResourceList list = filteredList;
409 if (resourceSortCriteria[0] == CoreAttributesList::TreeMode)
411 for (ResourceListIterator rli(filteredList); *rli != 0; ++rli)
413 for (Resource* p = (*rli)->getParent(); p != 0; p = p->getParent())
414 if (list.containsRef(p) == 0)
423 /* Now we have to remove all sub resources of resource in the
424 * roll-up list from the filtered list */
425 for (ResourceListIterator rli(project->getResourceListIterator());
428 if (isRolledUp(*rli, rollUpExp))
429 for (ResourceTreeIterator rti(*rli, parentAfterLeaves);
432 filteredList.removeRef(*rti);
433 if (rollUpExp && rollUpExp->getErrorFlag())
441 Report::sortResourceList(ResourceList& filteredList)
443 for (int i = 0; i < CoreAttributesList::maxSortingLevel; i++)
444 filteredList.setSorting(resourceSortCriteria[i], i);
449 Report::filterAccountList(AccountList& filteredList, AccountType at,
450 ExpressionTree* hideExp, ExpressionTree* rollUpExp)
453 /* Create a new list that contains only those accounts that were not
455 filteredList.clear();
456 for (AccountListIterator ali(project->getAccountListIterator());
459 if (!isHidden(*ali, hideExp) &&
460 (at == AllAccounts || (*ali)->getAcctType() == at))
461 filteredList.append(*ali);
462 if (hideExp && hideExp->getErrorFlag())
466 /* In accounttree sorting mode we need to make sure that we don't hide
467 * parents of shown accounts. */
468 AccountList list = filteredList;
469 if (accountSortCriteria[0] == CoreAttributesList::TreeMode)
471 for (AccountListIterator ali(filteredList); *ali != 0; ++ali)
473 for (Account* p = (*ali)->getParent(); p != 0; p = p->getParent())
474 if (list.containsRef(p) == 0)
483 /* Now we have to remove all sub accounts of account in the roll-up list
484 * from the filtered list */
485 for (AccountListIterator ali(project->getAccountListIterator());
488 if (isRolledUp(*ali, rollUpExp))
489 for (AccountTreeIterator ati(*ali, parentAfterLeaves);
492 filteredList.removeRef(*ati);
493 if (rollUpExp && rollUpExp->getErrorFlag())
501 Report::sortAccountList(AccountList& filteredList)
503 for (int i = 0; i < CoreAttributesList::maxSortingLevel; i++)
504 filteredList.setSorting(accountSortCriteria[i], i);
507 maxDepthAccountList = filteredList.maxDepth();
511 Report::setLoadUnit(const QString& u)
513 if (u == KW("minutes"))
515 else if (u == KW("hours"))
517 else if (u == KW("days"))
519 else if (u == KW("weeks"))
521 else if (u == KW("months"))
523 else if (u == KW("years"))
525 else if (u == KW("shortauto"))
526 loadUnit = shortAuto;
527 else if (u == KW("longauto"))
536 Report::errorMessage(const QString& msg)
538 TJMH.errorMessage(msg, defFileName, defFileLine);
542 Report::stripTaskRoot(QString taskId) const
544 if (taskRoot == taskId.left(taskRoot.length()))
545 return taskId.right(taskId.length() - taskRoot.length());