taskjuggler 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. data/CHANGELOG +44 -0
  2. data/bin/tj3webd +4 -0
  3. data/data/css/tjreport.css +14 -5
  4. data/data/tjp.vim +22 -7
  5. data/examples/Fedora-20/reports.tji +2 -4
  6. data/examples/Scrum/Product Burndown.csv +26 -0
  7. data/examples/Scrum/Sprint 1 Burndown.csv +26 -0
  8. data/examples/Scrum/Sprint 2 Burndown.csv +26 -0
  9. data/examples/Scrum/Sprint 3 Burndown.csv +26 -0
  10. data/examples/Scrum/scrum.tjp +141 -0
  11. data/examples/Tutorial/tutorial.tjp +13 -7
  12. data/lib/taskjuggler/Attributes.rb +2 -3
  13. data/lib/taskjuggler/HTMLDocument.rb +25 -18
  14. data/lib/taskjuggler/Journal.rb +85 -65
  15. data/lib/taskjuggler/KeywordDocumentation.rb +25 -13
  16. data/lib/taskjuggler/LeaveList.rb +1 -1
  17. data/lib/taskjuggler/Limits.rb +3 -5
  18. data/lib/taskjuggler/MessageHandler.rb +173 -19
  19. data/lib/taskjuggler/Painter.rb +75 -0
  20. data/lib/taskjuggler/Painter/BasicShapes.rb +76 -0
  21. data/lib/taskjuggler/Painter/Color.rb +273 -0
  22. data/lib/taskjuggler/Painter/Element.rb +56 -0
  23. data/lib/taskjuggler/Painter/FontData.rb +221 -0
  24. data/lib/taskjuggler/Painter/FontMetrics.rb +125 -0
  25. data/lib/taskjuggler/Painter/FontMetricsData.rb +151 -0
  26. data/lib/taskjuggler/Painter/Group.rb +77 -0
  27. data/lib/taskjuggler/Painter/Points.rb +47 -0
  28. data/lib/taskjuggler/Painter/Primitives.rb +100 -0
  29. data/lib/taskjuggler/Painter/SVGSupport.rb +36 -0
  30. data/lib/taskjuggler/Painter/Text.rb +36 -0
  31. data/lib/taskjuggler/Project.rb +46 -29
  32. data/lib/taskjuggler/ProjectFileParser.rb +24 -22
  33. data/lib/taskjuggler/ProjectFileScanner.rb +2 -2
  34. data/lib/taskjuggler/PropertyTreeNode.rb +26 -34
  35. data/lib/taskjuggler/Query.rb +8 -5
  36. data/lib/taskjuggler/RealFormat.rb +3 -0
  37. data/lib/taskjuggler/Resource.rb +3 -5
  38. data/lib/taskjuggler/ResourceScenario.rb +19 -7
  39. data/lib/taskjuggler/RichText.rb +4 -6
  40. data/lib/taskjuggler/RichText/FunctionExample.rb +1 -1
  41. data/lib/taskjuggler/RichText/FunctionHandler.rb +5 -6
  42. data/lib/taskjuggler/RichText/Parser.rb +4 -6
  43. data/lib/taskjuggler/RichText/RTFNavigator.rb +1 -1
  44. data/lib/taskjuggler/RichText/RTFQuery.rb +2 -3
  45. data/lib/taskjuggler/RichText/RTFReport.rb +1 -1
  46. data/lib/taskjuggler/RichText/RTFReportLink.rb +1 -2
  47. data/lib/taskjuggler/RichText/RTFWithQuerySupport.rb +1 -1
  48. data/lib/taskjuggler/RichText/Scanner.rb +6 -6
  49. data/lib/taskjuggler/RichText/Snip.rb +1 -2
  50. data/lib/taskjuggler/RuntimeConfig.rb +9 -6
  51. data/lib/taskjuggler/ScenarioData.rb +4 -3
  52. data/lib/taskjuggler/Scoreboard.rb +6 -0
  53. data/lib/taskjuggler/SheetHandlerBase.rb +25 -8
  54. data/lib/taskjuggler/SimpleQueryExpander.rb +14 -5
  55. data/lib/taskjuggler/SyntaxReference.rb +1 -2
  56. data/lib/taskjuggler/TableColumnSorter.rb +84 -0
  57. data/lib/taskjuggler/Task.rb +3 -5
  58. data/lib/taskjuggler/TaskJuggler.rb +36 -29
  59. data/lib/taskjuggler/TaskScenario.rb +154 -66
  60. data/lib/taskjuggler/TextParser.rb +24 -17
  61. data/lib/taskjuggler/TextParser/Scanner.rb +16 -11
  62. data/lib/taskjuggler/TextParser/SourceFileInfo.rb +20 -15
  63. data/lib/taskjuggler/TimeSheets.rb +6 -12
  64. data/lib/taskjuggler/Tj3AppBase.rb +35 -16
  65. data/lib/taskjuggler/Tj3Config.rb +1 -1
  66. data/lib/taskjuggler/TjpSyntaxRules.rb +239 -49
  67. data/lib/taskjuggler/XMLElement.rb +9 -2
  68. data/lib/taskjuggler/apps/Tj3.rb +43 -37
  69. data/lib/taskjuggler/apps/Tj3Client.rb +62 -112
  70. data/lib/taskjuggler/apps/Tj3Daemon.rb +66 -29
  71. data/lib/taskjuggler/apps/Tj3Man.rb +5 -5
  72. data/lib/taskjuggler/apps/Tj3SsReceiver.rb +10 -13
  73. data/lib/taskjuggler/apps/Tj3SsSender.rb +13 -16
  74. data/lib/taskjuggler/apps/Tj3TsReceiver.rb +10 -13
  75. data/lib/taskjuggler/apps/Tj3TsSender.rb +12 -15
  76. data/lib/taskjuggler/apps/Tj3TsSummary.rb +12 -15
  77. data/lib/taskjuggler/apps/Tj3WebD.rb +99 -0
  78. data/lib/taskjuggler/daemon/Daemon.rb +50 -10
  79. data/lib/taskjuggler/daemon/DaemonConnector.rb +127 -0
  80. data/lib/taskjuggler/daemon/ProcessIntercom.rb +36 -21
  81. data/lib/taskjuggler/daemon/ProjectBroker.rb +122 -112
  82. data/lib/taskjuggler/daemon/ProjectServer.rb +78 -46
  83. data/lib/taskjuggler/daemon/ReportServer.rb +52 -28
  84. data/lib/taskjuggler/daemon/ReportServlet.rb +92 -21
  85. data/lib/taskjuggler/daemon/WebServer.rb +75 -22
  86. data/lib/taskjuggler/daemon/WelcomePage.rb +1 -0
  87. data/lib/taskjuggler/reports/AccountListRE.rb +3 -3
  88. data/lib/taskjuggler/reports/CSVFile.rb +9 -2
  89. data/lib/taskjuggler/reports/ChartPlotter.rb +453 -0
  90. data/lib/taskjuggler/reports/Navigator.rb +1 -0
  91. data/lib/taskjuggler/reports/NikuReport.rb +4 -4
  92. data/lib/taskjuggler/reports/Report.rb +6 -18
  93. data/lib/taskjuggler/reports/ReportBase.rb +9 -9
  94. data/lib/taskjuggler/reports/ReportContext.rb +2 -2
  95. data/lib/taskjuggler/reports/StatusSheetReport.rb +6 -6
  96. data/lib/taskjuggler/reports/TableReport.rb +24 -15
  97. data/lib/taskjuggler/reports/TimeSheetReport.rb +5 -5
  98. data/lib/taskjuggler/reports/TraceReport.rb +251 -0
  99. data/lib/tj3webd.rb +17 -0
  100. data/manual/Day_To_Day_Juggling +10 -3
  101. data/manual/Installation +38 -19
  102. data/manual/Software +25 -19
  103. data/manual/Tutorial +119 -110
  104. data/manual/html/Day_To_Day_Juggling.html +7 -5
  105. data/manual/html/Getting_Started.html +4 -4
  106. data/manual/html/How_To_Contribute.html +4 -4
  107. data/manual/html/Installation.html +19 -11
  108. data/manual/html/Intro.html +4 -4
  109. data/manual/html/Reporting_Bugs.html +4 -4
  110. data/manual/html/Rich_Text_Attributes.html +4 -4
  111. data/manual/html/Software.html +15 -11
  112. data/manual/html/TaskJuggler_2x_Migration.html +4 -4
  113. data/manual/html/TaskJuggler_Internals.html +4 -4
  114. data/manual/html/The_TaskJuggler_Syntax.html +4 -4
  115. data/manual/html/Tutorial.html +41 -32
  116. data/manual/html/account.html +4 -4
  117. data/manual/html/account.task.html +4 -4
  118. data/manual/html/accountprefix.html +4 -4
  119. data/manual/html/accountreport.html +27 -9
  120. data/manual/html/accountroot.html +5 -5
  121. data/manual/html/active.html +4 -4
  122. data/manual/html/adopt.task.html +4 -4
  123. data/manual/html/aggregate.html +4 -4
  124. data/manual/html/alert.html +4 -4
  125. data/manual/html/alertlevels.html +4 -4
  126. data/manual/html/allocate.html +5 -5
  127. data/manual/html/alphabet.html +4 -4
  128. data/manual/html/alternative.html +4 -4
  129. data/manual/html/author.html +4 -4
  130. data/manual/html/balance.html +5 -5
  131. data/manual/html/booking.resource.html +4 -4
  132. data/manual/html/booking.task.html +4 -4
  133. data/manual/html/caption.html +5 -5
  134. data/manual/html/cellcolor.column.html +43 -8
  135. data/manual/html/celltext.column.html +4 -4
  136. data/manual/html/center.html +5 -5
  137. data/manual/html/charge.html +4 -4
  138. data/manual/html/chargeset.html +4 -4
  139. data/manual/html/columnid.html +27 -15
  140. data/manual/html/columns.html +5 -5
  141. data/manual/html/complete.html +4 -4
  142. data/manual/html/copyright.html +4 -4
  143. data/manual/html/credits.html +4 -4
  144. data/manual/html/css/tjreport.css +14 -5
  145. data/manual/html/currency.html +4 -4
  146. data/manual/html/currencyformat.html +5 -5
  147. data/manual/html/dailymax.html +5 -5
  148. data/manual/html/dailymin.html +5 -5
  149. data/manual/html/dailyworkinghours.html +4 -4
  150. data/manual/html/date.extend.html +4 -4
  151. data/manual/html/date.html +5 -5
  152. data/manual/html/definitions.html +4 -4
  153. data/manual/html/depends.html +4 -4
  154. data/manual/html/details.html +4 -4
  155. data/manual/html/disabled.html +4 -4
  156. data/manual/html/duration.html +4 -4
  157. data/manual/html/efficiency.html +4 -4
  158. data/manual/html/effort.html +4 -4
  159. data/manual/html/email.html +4 -4
  160. data/manual/html/enabled.html +4 -4
  161. data/manual/html/end.column.html +4 -4
  162. data/manual/html/end.html +4 -4
  163. data/manual/html/end.limit.html +4 -4
  164. data/manual/html/end.report.html +5 -5
  165. data/manual/html/end.timesheet.html +4 -4
  166. data/manual/html/endcredit.html +4 -4
  167. data/manual/html/epilog.html +5 -5
  168. data/manual/html/export.html +4 -4
  169. data/manual/html/extend.html +4 -4
  170. data/manual/html/fail.html +43 -8
  171. data/manual/html/fdl.html +4 -4
  172. data/manual/html/flags.account.html +4 -4
  173. data/manual/html/flags.html +4 -4
  174. data/manual/html/flags.journalentry.html +4 -4
  175. data/manual/html/flags.report.html +5 -5
  176. data/manual/html/flags.resource.html +4 -4
  177. data/manual/html/flags.statussheet.html +4 -4
  178. data/manual/html/flags.task.html +4 -4
  179. data/manual/html/flags.timesheet.html +4 -4
  180. data/manual/html/fontcolor.column.html +43 -8
  181. data/manual/html/footer.html +5 -5
  182. data/manual/html/formats.html +5 -5
  183. data/manual/html/functions.html +4 -4
  184. data/manual/html/gapduration.html +4 -4
  185. data/manual/html/gaplength.html +4 -4
  186. data/manual/html/halign.center.html +4 -4
  187. data/manual/html/halign.column.html +43 -8
  188. data/manual/html/halign.left.html +4 -4
  189. data/manual/html/halign.right.html +4 -4
  190. data/manual/html/hasalert.html +4 -4
  191. data/manual/html/header.html +5 -5
  192. data/manual/html/headline.html +7 -7
  193. data/manual/html/height.html +72 -0
  194. data/manual/html/hideaccount.html +46 -11
  195. data/manual/html/hidejournalentry.html +5 -5
  196. data/manual/html/hidereport.html +43 -8
  197. data/manual/html/hideresource.html +44 -9
  198. data/manual/html/hidetask.html +44 -9
  199. data/manual/html/icalreport.html +4 -4
  200. data/manual/html/include.macro.html +4 -4
  201. data/manual/html/include.project.html +4 -4
  202. data/manual/html/include.properties.html +4 -4
  203. data/manual/html/index.html +2 -1
  204. data/manual/html/inherit.extend.html +4 -4
  205. data/manual/html/interval1.html +4 -4
  206. data/manual/html/interval2.html +4 -4
  207. data/manual/html/interval3.html +4 -4
  208. data/manual/html/interval4.html +4 -4
  209. data/manual/html/isactive.html +4 -4
  210. data/manual/html/ischildof.html +4 -4
  211. data/manual/html/isdependencyof.html +4 -4
  212. data/manual/html/isdutyof.html +4 -4
  213. data/manual/html/isfeatureof.html +4 -4
  214. data/manual/html/isleaf.html +4 -4
  215. data/manual/html/ismilestone.html +4 -4
  216. data/manual/html/isongoing.html +4 -4
  217. data/manual/html/isresource.html +4 -4
  218. data/manual/html/isresponsibilityof.html +4 -4
  219. data/manual/html/istask.html +4 -4
  220. data/manual/html/journalattributes.html +11 -7
  221. data/manual/html/journalentry.html +4 -4
  222. data/manual/html/journalmode.html +5 -5
  223. data/manual/html/leaveallowance.html +5 -5
  224. data/manual/html/leaves.html +5 -6
  225. data/manual/html/left.html +5 -5
  226. data/manual/html/length.html +4 -4
  227. data/manual/html/limits.allocate.html +4 -4
  228. data/manual/html/limits.html +4 -4
  229. data/manual/html/limits.resource.html +4 -4
  230. data/manual/html/limits.task.html +4 -4
  231. data/manual/html/listitem.column.html +4 -4
  232. data/manual/html/listtype.column.html +4 -4
  233. data/manual/html/loadunit.html +5 -5
  234. data/manual/html/logicalexpression.html +8 -44
  235. data/manual/html/logicalflagexpression.html +4 -4
  236. data/manual/html/macro.html +4 -4
  237. data/manual/html/managers.html +4 -4
  238. data/manual/html/mandatory.html +4 -4
  239. data/manual/html/maxend.html +4 -4
  240. data/manual/html/maximum.html +5 -5
  241. data/manual/html/maxstart.html +4 -4
  242. data/manual/html/milestone.html +4 -4
  243. data/manual/html/minend.html +4 -4
  244. data/manual/html/minimum.html +5 -5
  245. data/manual/html/minstart.html +4 -4
  246. data/manual/html/monthlymax.html +5 -5
  247. data/manual/html/monthlymin.html +5 -5
  248. data/manual/html/navbar.html +10 -4
  249. data/manual/html/navigator.html +4 -4
  250. data/manual/html/newtask.html +4 -4
  251. data/manual/html/nikureport.html +4 -4
  252. data/manual/html/note.task.html +4 -4
  253. data/manual/html/now.html +4 -4
  254. data/manual/html/numberformat.html +5 -5
  255. data/manual/html/onend.html +4 -4
  256. data/manual/html/onstart.html +4 -4
  257. data/manual/html/opennodes.html +5 -5
  258. data/manual/html/overtime.booking.html +4 -4
  259. data/manual/html/period.column.html +4 -4
  260. data/manual/html/period.limit.html +4 -4
  261. data/manual/html/period.report.html +5 -5
  262. data/manual/html/period.task.html +4 -4
  263. data/manual/html/persistent.html +4 -4
  264. data/manual/html/precedes.html +4 -4
  265. data/manual/html/priority.html +4 -4
  266. data/manual/html/priority.timesheet.html +4 -4
  267. data/manual/html/project.html +4 -4
  268. data/manual/html/projectid.html +4 -4
  269. data/manual/html/projectid.task.html +4 -4
  270. data/manual/html/projectids.html +4 -4
  271. data/manual/html/projection.html +5 -7
  272. data/manual/html/prolog.html +5 -5
  273. data/manual/html/properties.html +11 -5
  274. data/manual/html/purge.html +5 -5
  275. data/manual/html/rate.html +4 -4
  276. data/manual/html/rate.resource.html +4 -4
  277. data/manual/html/reference.extend.html +4 -4
  278. data/manual/html/remaining.html +4 -4
  279. data/manual/html/replace.html +4 -4
  280. data/manual/html/reportprefix.html +4 -4
  281. data/manual/html/resource.html +4 -10
  282. data/manual/html/resourceattributes.html +4 -4
  283. data/manual/html/resourceprefix.html +4 -4
  284. data/manual/html/resourcereport.html +28 -10
  285. data/manual/html/resourceroot.html +5 -5
  286. data/manual/html/resources.limit.html +4 -4
  287. data/manual/html/responsible.html +4 -4
  288. data/manual/html/richtext.extend.html +4 -4
  289. data/manual/html/right.html +5 -5
  290. data/manual/html/rollupaccount.html +44 -9
  291. data/manual/html/rollupresource.html +44 -9
  292. data/manual/html/rolluptask.html +44 -9
  293. data/manual/html/scale.column.html +4 -4
  294. data/manual/html/scenario.html +4 -22
  295. data/manual/html/scenario.ical.html +4 -4
  296. data/manual/html/scenarios.export.html +4 -4
  297. data/manual/html/scenarios.html +5 -5
  298. data/manual/html/scenariospecific.extend.html +4 -4
  299. data/manual/html/scheduled.html +4 -4
  300. data/manual/html/scheduling.html +4 -4
  301. data/manual/html/select.html +4 -4
  302. data/manual/html/selfcontained.html +5 -5
  303. data/manual/html/shift.allocate.html +4 -4
  304. data/manual/html/shift.html +4 -4
  305. data/manual/html/shift.resource.html +5 -5
  306. data/manual/html/shift.task.html +4 -4
  307. data/manual/html/shift.timesheet.html +4 -4
  308. data/manual/html/shifts.allocate.html +4 -4
  309. data/manual/html/shifts.resource.html +4 -4
  310. data/manual/html/shifts.task.html +4 -4
  311. data/manual/html/shorttimeformat.html +4 -4
  312. data/manual/html/sloppy.booking.html +4 -4
  313. data/manual/html/sloppy.projection.html +5 -5
  314. data/manual/html/sortaccounts.html +5 -5
  315. data/manual/html/sortjournalentries.html +5 -5
  316. data/manual/html/sortresources.html +5 -5
  317. data/manual/html/sorttasks.html +5 -5
  318. data/manual/html/start.column.html +4 -4
  319. data/manual/html/start.html +4 -4
  320. data/manual/html/start.limit.html +4 -4
  321. data/manual/html/start.report.html +5 -5
  322. data/manual/html/startcredit.html +4 -4
  323. data/manual/html/status.statussheet.html +4 -4
  324. data/manual/html/status.timesheet.html +4 -4
  325. data/manual/html/statussheet.html +4 -4
  326. data/manual/html/statussheetreport.html +4 -4
  327. data/manual/html/strict.projection.html +5 -5
  328. data/manual/html/summary.html +4 -4
  329. data/manual/html/supplement.html +4 -4
  330. data/manual/html/supplement.resource.html +4 -10
  331. data/manual/html/supplement.task.html +4 -28
  332. data/manual/html/tagfile.html +4 -4
  333. data/manual/html/task.html +4 -28
  334. data/manual/html/task.statussheet.html +4 -4
  335. data/manual/html/task.timesheet.html +4 -4
  336. data/manual/html/taskattributes.html +4 -4
  337. data/manual/html/taskprefix.html +4 -4
  338. data/manual/html/taskreport.html +28 -10
  339. data/manual/html/taskroot.html +5 -5
  340. data/manual/html/text.extend.html +4 -4
  341. data/manual/html/textreport.html +27 -9
  342. data/manual/html/timeformat.html +5 -5
  343. data/manual/html/timeoff.nikureport.html +4 -4
  344. data/manual/html/timesheet.html +4 -4
  345. data/manual/html/timesheetreport.html +23 -5
  346. data/manual/html/timezone.export.html +4 -4
  347. data/manual/html/timezone.html +4 -4
  348. data/manual/html/timezone.report.html +5 -5
  349. data/manual/html/timezone.shift.html +4 -4
  350. data/manual/html/timingresolution.html +4 -4
  351. data/manual/html/title.column.html +4 -4
  352. data/manual/html/title.html +5 -5
  353. data/manual/html/toc.html +207 -179
  354. data/manual/html/tooltip.column.html +45 -10
  355. data/manual/html/tracereport.html +405 -0
  356. data/manual/html/trackingscenario.html +6 -6
  357. data/manual/html/treelevel.html +4 -4
  358. data/manual/html/vacation.html +4 -4
  359. data/manual/html/vacation.resource.html +4 -4
  360. data/manual/html/vacation.shift.html +4 -4
  361. data/manual/html/warn.html +43 -8
  362. data/manual/html/weeklymax.html +5 -5
  363. data/manual/html/weeklymin.html +5 -5
  364. data/manual/html/weekstartsmonday.html +4 -4
  365. data/manual/html/weekstartssunday.html +6 -6
  366. data/manual/html/width.column.html +6 -6
  367. data/manual/html/width.html +72 -0
  368. data/manual/html/work.html +4 -4
  369. data/manual/html/workinghours.project.html +4 -4
  370. data/manual/html/workinghours.resource.html +4 -4
  371. data/manual/html/workinghours.shift.html +4 -4
  372. data/manual/html/yearlyworkingdays.html +4 -4
  373. data/spec/Color_spec.rb +60 -0
  374. data/spec/ProjectBroker_spec.rb +3 -2
  375. data/spec/StatusSheets_spec.rb +5 -4
  376. data/spec/TableColumnSorter_spec.rb +78 -0
  377. data/spec/TimeSheets_spec.rb +6 -2
  378. data/spec/Tj3Daemon_spec.rb +2 -2
  379. data/spec/TraceReport_spec.rb +117 -0
  380. data/taskjuggler.gemspec +1 -1
  381. data/test/MessageChecker.rb +3 -1
  382. data/test/ReferenceGenerator.rb +1 -1
  383. data/test/TestSuite/CSV-Reports/Leave.tjp +1 -1
  384. data/test/TestSuite/CSV-Reports/refs/resourcereport_with_tasks.csv +3 -0
  385. data/test/TestSuite/CSV-Reports/refs/taskcounter.csv +9 -0
  386. data/test/TestSuite/CSV-Reports/refs/taskreport_with_resources.csv +19 -16
  387. data/test/TestSuite/CSV-Reports/refs/weekly.csv +1 -0
  388. data/test/TestSuite/Export-Reports/refs/LogicalExpression.tjp +14 -2
  389. data/test/TestSuite/Export-Reports/refs/tutorial.tjp +98 -86
  390. data/test/TestSuite/Scheduler/Correct/Leaves.tjp +25 -0
  391. data/test/TestSuite/Syntax/Correct/Leave.tjp +1 -1
  392. data/test/TestSuite/Syntax/Correct/LogicalExpression.tjp +9 -1
  393. data/test/TestSuite/Syntax/Correct/TraceReport.tjp +10 -0
  394. data/test/TestSuite/Syntax/Correct/tutorial.tjp +10 -4
  395. data/test/test_CSV-Reports.rb +3 -3
  396. data/test/test_Export-Reports.rb +91 -86
  397. data/test/test_Journal.rb +15 -12
  398. data/test/test_Limits.rb +3 -3
  399. data/test/test_Project.rb +1 -2
  400. data/test/test_ProjectFileScanner.rb +1 -1
  401. data/test/test_PropertySet.rb +1 -1
  402. data/test/test_Query.rb +5 -6
  403. data/test/test_ReportGenerator.rb +15 -7
  404. data/test/test_RichText.rb +4 -3
  405. data/test/test_Scheduler.rb +19 -7
  406. data/test/test_ShiftAssignments.rb +2 -2
  407. data/test/test_SimpleQueryExpander.rb +29 -2
  408. data/test/test_Syntax.rb +14 -5
  409. metadata +49 -10
  410. data/lib/taskjuggler/LogFile.rb +0 -73
@@ -24,7 +24,7 @@ class TaskJuggler
24
24
 
25
25
  def initialize(project, sourceFileInfo = nil)
26
26
  @project = project
27
- super(project.messageHandler, 'navigator', sourceFileInfo)
27
+ super('navigator', sourceFileInfo)
28
28
  @blockFunction = true
29
29
  end
30
30
 
@@ -23,7 +23,7 @@ class TaskJuggler
23
23
 
24
24
  def initialize(project, sourceFileInfo = nil)
25
25
  @project = project
26
- super(project.messageHandler, 'query', sourceFileInfo)
26
+ super('query', sourceFileInfo)
27
27
  @blockMode = false
28
28
  end
29
29
 
@@ -83,8 +83,7 @@ class TaskJuggler
83
83
  return nil
84
84
  end
85
85
  expandedArgs[arg] =
86
- SimpleQueryExpander.new(value, @query, @messageHandler,
87
- @sourceFileInfo).expand
86
+ SimpleQueryExpander.new(value, @query, @sourceFileInfo).expand
88
87
  end
89
88
 
90
89
  if (expandedArgs['property'] || expandedArgs['scopeproperty']) &&
@@ -22,7 +22,7 @@ class TaskJuggler
22
22
 
23
23
  def initialize(project, sourceFileInfo = nil)
24
24
  @project = project
25
- super(project.messageHandler, 'report', sourceFileInfo)
25
+ super('report', sourceFileInfo)
26
26
  @blockFunction = true
27
27
  end
28
28
 
@@ -24,7 +24,7 @@ class TaskJuggler
24
24
 
25
25
  def initialize(project, sourceFileInfo = nil)
26
26
  @project = project
27
- super(project.messageHandler, 'reportlink', sourceFileInfo)
27
+ super('reportlink', sourceFileInfo)
28
28
  @blockFunction = false
29
29
  @query = nil
30
30
  end
@@ -54,7 +54,6 @@ class TaskJuggler
54
54
 
55
55
  if args['attributes']
56
56
  qEx = SimpleQueryExpander.new(args['attributes'], @query,
57
- @project.messageHandler,
58
57
  @sourceFileInfo)
59
58
  url += ";attributes=" + URLParameter.encode(qEx.expand)
60
59
  end
@@ -17,7 +17,7 @@ class TaskJuggler
17
17
 
18
18
  class RTFWithQuerySupport < RichTextFunctionHandler
19
19
 
20
- def initialize(messageHandler, type, sourceFileInfo = nil)
20
+ def initialize(type, sourceFileInfo = nil)
21
21
  super
22
22
  @query = nil
23
23
  end
@@ -30,7 +30,7 @@ class TaskJuggler
30
30
  # :func : inside of a block <[ .. ]> or inline <- .. -> function
31
31
  class RichTextScanner < TextParser::Scanner
32
32
 
33
- def initialize(masterFile, messageHandler, log)
33
+ def initialize(masterFile, log)
34
34
  tokenPatterns = [
35
35
  # :bol mode rules
36
36
  [ :LINEBREAK, /\s*\n/, :bol, method('linebreak') ],
@@ -49,8 +49,8 @@ class TaskJuggler
49
49
  [ :BLOCKFUNCSTART, /<\[/, [ :bop, :bol ], method('functionStart') ],
50
50
  [ ':TITLE*', /={2,5}/, [ :bop, :bol ], method('titleStart') ],
51
51
  [ 'TITLE*END', /={2,5}/, :inline, method('titleEnd') ],
52
- [ 'BULLET*', /\*{1,4} /, [ :bop, :bol ], method('bullet') ],
53
- [ 'NUMBER*', /\#{1,4} /, [ :bop, :bol ], method('number') ],
52
+ [ 'BULLET*', /\*{1,4}[ \t]+/, [ :bop, :bol ], method('bullet') ],
53
+ [ 'NUMBER*', /\#{1,4}[ \t]+/, [ :bop, :bol ], method('number') ],
54
54
  [ :HLINE, /----/, [ :bop, :bol ], method('inlineMode') ],
55
55
 
56
56
  # :bop, :bol and :inline mode rules
@@ -94,7 +94,7 @@ class TaskJuggler
94
94
  [ nil, /[ \t\n]+/, :func ],
95
95
  [ :LITERAL, /./, :func ]
96
96
  ]
97
- super(masterFile, messageHandler, log, tokenPatterns, :bop)
97
+ super(masterFile, log, tokenPatterns, :bop)
98
98
  end
99
99
 
100
100
  private
@@ -130,12 +130,12 @@ class TaskJuggler
130
130
 
131
131
  def bullet(type, match)
132
132
  self.mode = :inline
133
- [ "BULLET#{match.length - 1}".intern, match ]
133
+ [ "BULLET#{match.count('*')}".intern, match ]
134
134
  end
135
135
 
136
136
  def number(type, match)
137
137
  self.mode = :inline
138
- [ "NUMBER#{match.length - 1}".intern, match ]
138
+ [ "NUMBER#{match.count('#')}".intern, match ]
139
139
  end
140
140
 
141
141
  def fontColorStart(type, match)
@@ -40,8 +40,7 @@ class TaskJuggler
40
40
  File.open(fileName) do |file|
41
41
  file.each_line { |line| text += line }
42
42
  end
43
- rText = RichText.new(text, @document.functionHandlers,
44
- MessageHandler.new(true))
43
+ rText = RichText.new(text, @document.functionHandlers)
45
44
  unless (@richText = rText.generateIntermediateFormat(sectionCounter))
46
45
  exit
47
46
  end
@@ -29,8 +29,7 @@ class RuntimeConfig
29
29
  if configFile
30
30
  # Read user specified config file.
31
31
  unless loadConfigFile(configFile)
32
- $stderr.puts "Config file #{configFile} not found!"
33
- exit 1
32
+ error("Config file #{configFile} not found!")
34
33
  end
35
34
  else
36
35
  # Search config files in certain directories.
@@ -71,14 +70,13 @@ class RuntimeConfig
71
70
 
72
71
  def loadConfigFile(fileName)
73
72
  if File.exist?(fileName)
73
+ debug("Loading #{fileName}")
74
74
  begin
75
- debug("Loading #{fileName}")
76
75
  @config = YAML::load(File.read(fileName))
77
- debug(@config.to_s)
78
76
  rescue
79
- $stderr.puts "Error in config file #{fileName}: #{$!}"
80
- exit 1
77
+ error("Error in config file #{fileName}: #{$!}")
81
78
  end
79
+ debug(@config.to_s)
82
80
  return true
83
81
  end
84
82
  false
@@ -90,5 +88,10 @@ class RuntimeConfig
90
88
  puts message
91
89
  end
92
90
 
91
+ def error(message)
92
+ $stderr.puts message
93
+ exit 1
94
+ end
95
+
93
96
  end
94
97
 
@@ -25,6 +25,7 @@ class TaskJuggler
25
25
  @project = property.project
26
26
  @scenarioIdx = idx
27
27
  @attributes = attributes
28
+ @messageHandler = MessageHandlerInstance.instance
28
29
 
29
30
  # Register the scenario with the Task.
30
31
  @property.data[idx] = self
@@ -42,21 +43,21 @@ class TaskJuggler
42
43
  end
43
44
 
44
45
  def error(id, text, sourceFileInfo = nil, property = nil)
45
- @project.messageHandler.error(
46
+ @messageHandler.error(
46
47
  id, text, sourceFileInfo || @property.sourceFileInfo, nil,
47
48
  property || @property,
48
49
  @project.scenario(@scenarioIdx))
49
50
  end
50
51
 
51
52
  def warning(id, text, sourceFileInfo = nil, property = nil)
52
- @project.messageHandler.warning(
53
+ @messageHandler.warning(
53
54
  id, text, sourceFileInfo || @property.sourceFileInfo, nil,
54
55
  property || @property,
55
56
  @project.scenario(@scenarioIdx))
56
57
  end
57
58
 
58
59
  def info(id, text, sourceFileInfo = nil, property = nil)
59
- @project.messageHandler.info(
60
+ @messageHandler.info(
60
61
  id, text, sourceFileInfo || @property.sourceFileInfo, nil,
61
62
  property || @property,
62
63
  @project.scenario(@scenarioIdx))
@@ -170,6 +170,12 @@ class TaskJuggler
170
170
  intervals
171
171
  end
172
172
 
173
+ def inspect
174
+ 0.upto(@sb.length - 1) do |i|
175
+ puts "#{idxToDate(i)}: #{@sb[i]}"
176
+ end
177
+ end
178
+
173
179
  end
174
180
 
175
181
  end
@@ -25,7 +25,8 @@ class TaskJuggler
25
25
  def initialize(appName)
26
26
  @appName = appName
27
27
  # User specific settings
28
- @smtpServer= nil
28
+ @emailDeliveryMethod = 'smtp'
29
+ @smtpServer = nil
29
30
  @senderEmail = nil
30
31
  @workingDir = nil
31
32
  @scmCommand = nil
@@ -87,7 +88,14 @@ class TaskJuggler
87
88
 
88
89
  def setWorkingDir
89
90
  # Make sure the user has provided a properly setup config file.
90
- error('\'smtpServer\' not configured') unless @smtpServer
91
+ case @emailDeliveryMethod
92
+ when 'smtp'
93
+ error('\'smtpServer\' not configured') unless @smtpServer
94
+ when 'sendmail'
95
+ # nothing to check
96
+ else
97
+ error("Unknown emailDeliveryMethod #{@emailDeliveryMethod}")
98
+ end
91
99
  error('\'senderEmail\' not configured') unless @senderEmail
92
100
 
93
101
  # Change into the specified working directory
@@ -156,11 +164,20 @@ class TaskJuggler
156
164
 
157
165
  def sendEmail(to, subject, message, attachment = nil, from = nil,
158
166
  inReplyTo = nil)
159
- Mail.defaults do
160
- delivery_method :smtp, {
161
- :address => @smtpServer,
162
- :port => 25
163
- }
167
+ case @emailDeliveryMethod
168
+ when 'smtp'
169
+ Mail.defaults do
170
+ delivery_method :smtp, {
171
+ :address => @smtpServer,
172
+ :port => 25
173
+ }
174
+ end
175
+ when 'sendmail'
176
+ Mail.defaults do
177
+ delivery_method :sendmail
178
+ end
179
+ else
180
+ raise "Unknown email delivery method: #{@emailDeliveryMethod}"
164
181
  end
165
182
 
166
183
  begin
@@ -202,7 +219,7 @@ class TaskJuggler
202
219
  puts "-- Email Start #{'-' * 60}\n#{mail.to_s}-- Email End #{'-' * 62}"
203
220
  log('INFO', "Show email '#{subject}' to #{to}")
204
221
  else
205
- # Actually send out the email via SMTP.
222
+ # Actually send out the email.
206
223
  begin
207
224
  mail.deliver
208
225
  rescue
@@ -12,6 +12,7 @@
12
12
  #
13
13
 
14
14
  require 'strscan'
15
+ require 'taskjuggler/MessageHandler'
15
16
 
16
17
  class TaskJuggler
17
18
 
@@ -22,20 +23,29 @@ class TaskJuggler
22
23
  # context of the query.
23
24
  class SimpleQueryExpander
24
25
 
26
+ include MessageHandler
27
+
25
28
  # _inputStr_ is the String with the embedded queries. _query_ is the Query
26
29
  # with that provides the evaluation context. _messageHandle_ is a
27
30
  # MessageHandler that will be used for error reporting. _sourceFileInfo_
28
31
  # is a SourceFileInfo reference used for error reporting.
29
- def initialize(inputStr, query, messageHandler, sourceFileInfo)
32
+ def initialize(inputStr, query, sourceFileInfo)
30
33
  @inputStr = inputStr
31
34
  @query = query.dup
32
- @messageHandler = messageHandler
33
35
  @sourceFileInfo = sourceFileInfo
34
36
  end
35
37
 
36
38
  def expand
37
39
  # Create a copy of the input string since we will modify it.
38
40
  str = @inputStr.dup
41
+
42
+ # The scenario name is not an attribute that can be queried. We need to
43
+ # handle this separately
44
+ if @query.scenarioIdx
45
+ str.gsub!(/<-scenario->/,
46
+ @query.project.scenario(@query.scenarioIdx).id)
47
+ end
48
+
39
49
  # Replace all occurences of <-name->.
40
50
  str.gsub!(/<-[a-zA-Z][_a-zA-Z]*->/) do |match|
41
51
  attribute = match[2..-3]
@@ -45,9 +55,8 @@ class TaskJuggler
45
55
  @query.to_s
46
56
  else
47
57
  # The query failed. We report an error.
48
- @messageHandler.error('sqe_expand_failed',
49
- "Unknown attribute #{attribute}",
50
- @sourceFileInfo)
58
+ error('sqe_expand_failed', "Unknown attribute #{attribute}",
59
+ @sourceFileInfo)
51
60
  end
52
61
  end
53
62
  str
@@ -35,8 +35,7 @@ class TaskJuggler
35
35
  # SyntaxReference.
36
36
  def initialize(manual = nil, ignoreOld = false)
37
37
  @manual = manual
38
- @messageHandler = MessageHandler.new(true)
39
- @parser = ProjectFileParser.new(@messageHandler)
38
+ @parser = ProjectFileParser.new
40
39
  @parser.updateParserTables
41
40
 
42
41
  # This hash stores all documented keywords using the keyword as
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby -w
2
+ # encoding: UTF-8
3
+ #
4
+ # = TableColumnSorter.rb -- The TaskJuggler III Project Management Software
5
+ #
6
+ # Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
7
+ # by Chris Schlaeger <chris@linux.com>
8
+ #
9
+ # This program is free software; you can redistribute it and/or modify
10
+ # it under the terms of version 2 of the GNU General Public License as
11
+ # published by the Free Software Foundation.
12
+ #
13
+
14
+ class TaskJuggler
15
+
16
+ # This class can rearrange the columns of a table according to a new order
17
+ # determined by an Array of table headers. The table is an Array of table
18
+ # lines. Each line is another Array. The first line of the table is an Array
19
+ # of the headers of the columns.
20
+ class TableColumnSorter
21
+
22
+ attr_reader :discontinuedColumns
23
+
24
+ # Register a new table for rearranging.
25
+ def initialize(table)
26
+ @oldTable = table
27
+ @discontinuedColumns = nil
28
+ end
29
+
30
+ # Rearrange the registered table. The old table won't be modified. The
31
+ # method returns a new table (Array of Arrays). _newHeaders_ is an Array
32
+ # that represents the new column headers. The columns that are not in the
33
+ # new header will be the last columns of the new table.
34
+ def sort(newHeaders)
35
+ # Maps old index to new index.
36
+ columnIdxMap = {}
37
+ newHeaderIndex = newHeaders.length
38
+ oldHeaders = @oldTable[0]
39
+ discontinuedHeaders = []
40
+ oldHeaders.length.times do |i|
41
+ if (ni = newHeaders.index(oldHeaders[i]))
42
+ # This old column is still in the new header
43
+ columnIdxMap[i] = ni
44
+ else
45
+ # This old column is no longer contained in the new header. We
46
+ # append it at the end.
47
+ columnIdxMap[i] = newHeaderIndex
48
+ discontinuedHeaders << oldHeaders[i]
49
+ newHeaderIndex += 1
50
+ end
51
+ end
52
+
53
+ # We construct a new table from scratch. All values from the old table
54
+ # are copied over. columns in the new table that were not contained in
55
+ # the old table will be filled with nil.
56
+ newTable = []
57
+ @oldTable.length.times do |lineIdx|
58
+ oldLine = @oldTable[lineIdx]
59
+ if lineIdx == 0
60
+ # Insert the new headers. The discontinued ones will be added below.
61
+ newTable[0] = newHeaders
62
+ else
63
+ # Add a line of nils to the new table.
64
+ newTable[lineIdx] = Array.new(newHeaderIndex, nil)
65
+ end
66
+
67
+ # Copy the old column to the new position.
68
+ columnIdxMap.each do |oldColIdx, newColIdx|
69
+ newTable[lineIdx][newColIdx] = oldLine[oldColIdx]
70
+ end
71
+ end
72
+
73
+ # Now we need to add the new column headers that were not in the old
74
+ # headers.
75
+ #newTable[0] += discontinuedHeaders
76
+
77
+ @discontinuedColumns = discontinuedHeaders.length
78
+ newTable
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
@@ -96,11 +96,9 @@ class TaskJuggler
96
96
 
97
97
  # Now convert the RichText markup String into RichTextIntermediate
98
98
  # format.
99
- unless (rti = RichText.new(rText, RTFHandlers.create(@project),
100
- @project.messageHandler).
101
- generateIntermediateFormat)
102
- @project.messageHandler.warning(
103
- 'task_journal_text', 'Syntax error in journal text')
99
+ unless (rti = RichText.new(rText, RTFHandlers.create(@project)).
100
+ generateIntermediateFormat)
101
+ warning('task_journal_text', 'Syntax error in journal text')
104
102
  return nil
105
103
  end
106
104
 
@@ -23,17 +23,19 @@ require 'taskjuggler/Log'
23
23
  # files, schedule them and generate the reports.
24
24
  class TaskJuggler
25
25
 
26
- attr_reader :project, :messageHandler
27
- attr_accessor :maxCpuCores, :warnTsDeltas
26
+ include MessageHandler
27
+
28
+ attr_reader :project
29
+ attr_accessor :maxCpuCores, :warnTsDeltas, :generateTraces
28
30
 
29
31
  # Create a new TaskJuggler object. _console_ is a boolean that determines
30
32
  # whether or not messsages can be written to $stderr.
31
- def initialize(console)
33
+ def initialize
32
34
  @project = nil
33
35
  @parser = nil
34
- @messageHandler = MessageHandler.new(console)
35
36
  @maxCpuCores = 1
36
37
  @warnTsDeltas = false
38
+ @generateTraces = false
37
39
  TjTime.setTimeZone('UTC')
38
40
  end
39
41
 
@@ -41,18 +43,21 @@ class TaskJuggler
41
43
  # construct a Project object. In case of success true is returned.
42
44
  # Otherwise false.
43
45
  def parse(files, keepParser = false)
46
+ # Reset the MessageHandler to clear all errors.
47
+ MessageHandlerInstance.instance.clear
48
+
44
49
  Log.enter('parser', 'Parsing files ...')
45
50
  master = true
46
51
  @project = nil
47
52
 
48
53
  #RubyProf.start
49
- @parser = ProjectFileParser.new(@messageHandler)
54
+ @parser = ProjectFileParser.new
50
55
  files.each do |file|
51
56
  begin
52
57
  @parser.open(file, master)
53
58
  rescue TjException => msg
54
59
  if msg.message && !msg.message.empty?
55
- @messageHandler.critical('parse', msg.message)
60
+ critical('parse', msg.message)
56
61
  end
57
62
  Log.exit('parser')
58
63
  return false
@@ -91,7 +96,7 @@ class TaskJuggler
91
96
  @parser = nil unless keepParser
92
97
 
93
98
  Log.exit('parser')
94
- @messageHandler.errors == 0
99
+ MessageHandlerInstance.instance.errors == 0
95
100
  end
96
101
 
97
102
  # Parse a file and add the content to the existing project. _fileName_ is
@@ -102,7 +107,7 @@ class TaskJuggler
102
107
  @project.inputFiles << fileName
103
108
  rescue TjException => msg
104
109
  if msg.message && !msg.message.empty?
105
- @messageHandler.critical('parse_file', msg.message)
110
+ critical('parse_file', msg.message)
106
111
  end
107
112
  return nil
108
113
  end
@@ -125,11 +130,13 @@ class TaskJuggler
125
130
  res = @project.schedule
126
131
  rescue TjException => msg
127
132
  if msg.message && !msg.message.empty?
128
- @messageHandler.critical('scheduling_error', msg.message)
133
+ critical('scheduling_error', msg.message)
129
134
  end
130
135
  return false
131
136
  end
132
137
 
138
+ @project.enableTraceReports(@generateTraces)
139
+
133
140
  Log.exit('scheduler')
134
141
  res
135
142
  end
@@ -157,7 +164,7 @@ class TaskJuggler
157
164
  #end
158
165
  rescue TjException => msg
159
166
  if msg.message && !msg.message.empty?
160
- @messageHandler.critical('generate_reports', msg.message)
167
+ critical('generate_reports', msg.message)
161
168
  end
162
169
  return false
163
170
  end
@@ -179,7 +186,7 @@ class TaskJuggler
179
186
  @project.generateReport(reportId, regExpMode, formats, dynamicAttributes)
180
187
  rescue TjException => msg
181
188
  if msg.message && !msg.message.empty?
182
- @messageHandler.critical('generate_report', msg.message)
189
+ critical('generate_report', msg.message)
183
190
  end
184
191
  Log.exit('generateReport')
185
192
  return false
@@ -196,7 +203,7 @@ class TaskJuggler
196
203
  @project.listReports(reportId, regExpMode)
197
204
  rescue TjException => msg
198
205
  if msg.message && !msg.message.empty?
199
- @messageHandler.critical('list_reports', msg.message)
206
+ critical('list_reports', msg.message)
200
207
  end
201
208
  Log.exit('listReports')
202
209
  return false
@@ -210,9 +217,9 @@ class TaskJuggler
210
217
  begin
211
218
  # Check the master file is really a file and not stdin.
212
219
  unless (masterFile = @project.inputFiles.masterFile)
213
- @messageHandler.error('cannot_freeze_stdin',
214
- "The project freeze feature only when the " +
215
- "master file is a real file, not standard input.")
220
+ error('cannot_freeze_stdin',
221
+ "The project freeze feature only when the " +
222
+ "master file is a real file, not standard input.")
216
223
  end
217
224
 
218
225
  # Derive the file names for the header and bookings file from the base
@@ -223,10 +230,10 @@ class TaskJuggler
223
230
  bookingsFile = bookingsFileBase + '.tji'
224
231
 
225
232
  if !File.exists?(bookingsFile) || !File.exists?(headerFile)
226
- @messageHandler.info('incl_freeze_files',
227
- "Please make sure you include #{headerFile} at " +
228
- "the end of the project header and " +
229
- "#{bookingsFile} at the end of #{masterFile}.")
233
+ info('incl_freeze_files',
234
+ "Please make sure you include #{headerFile} at " +
235
+ "the end of the project header and " +
236
+ "#{bookingsFile} at the end of #{masterFile}.")
230
237
  end
231
238
 
232
239
  # Generate the project header include file with the new 'now' date.
@@ -235,9 +242,9 @@ class TaskJuggler
235
242
  f.puts("now #{freezeDate}")
236
243
  end
237
244
  rescue
238
- @messageHandler.error('write_header_incl',
239
- "Cannote write header include file " +
240
- "#{headerFile}")
245
+ error('write_header_incl',
246
+ "Cannote write header include file " +
247
+ "#{headerFile}")
241
248
  end
242
249
 
243
250
  # Generate an export report for the bookings.
@@ -248,8 +255,7 @@ class TaskJuggler
248
255
 
249
256
  # We export only the tracking scenario.
250
257
  unless (trackingScenarioIdx = @project['trackingScenarioIdx'])
251
- @messageHandler.error('no_tracking_scen',
252
- 'No trackingscenario defined')
258
+ error('no_tracking_scen', 'No trackingscenario defined')
253
259
  end
254
260
  report.set('scenarios', [ trackingScenarioIdx ])
255
261
 
@@ -304,8 +310,9 @@ class TaskJuggler
304
310
  'start' => ts.interval.start,
305
311
  'end' => ts.interval.end,
306
312
  'journalMode' => :journal,
307
- 'journalAttributes' => %w( alert property headline flags
308
- timesheet summary details ),
313
+ 'journalAttributes' => %w( alert property propertyid
314
+ headline flags timesheet
315
+ summary details ),
309
316
  'sortJournalEntries' => [ [ :seqno, 1 ] ],
310
317
  'timeFormat' => '%Y-%m-%d',
311
318
  'selfContained' => true }
@@ -313,7 +320,7 @@ class TaskJuggler
313
320
  puts ts.resource.query_journal(query).richText.inputText
314
321
  rescue TjException => msg
315
322
  if msg.message && !msg.message.empty?
316
- @messageHandler.critical('check_time_sheet', msg.message)
323
+ critical('check_time_sheet', msg.message)
317
324
  end
318
325
  Log.exit('checkTimeSheet')
319
326
  return false
@@ -349,7 +356,7 @@ class TaskJuggler
349
356
  puts ss[0].query_dashboard(query).richText.inputText
350
357
  rescue TjException => msg
351
358
  if msg.message && !msg.message.empty?
352
- @messageHandler.critical('check_status_sheet', msg.message)
359
+ critical('check_status_sheet', msg.message)
353
360
  end
354
361
  Log.exit('checkStatusSheet')
355
362
  return false
@@ -372,7 +379,7 @@ class TaskJuggler
372
379
 
373
380
  # Return the number of errors that had been reported during processing.
374
381
  def errors
375
- @project.messageHandler.errors
382
+ MessageHandlerInstance.instance.errors
376
383
  end
377
384
 
378
385
  end