taskjuggler 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (338) hide show
  1. data/CHANGELOG +35 -0
  2. data/data/tjp.vim +21 -7
  3. data/lib/taskjuggler/Allocation.rb +27 -3
  4. data/lib/taskjuggler/Attributes.rb +3 -2
  5. data/lib/taskjuggler/HTMLDocument.rb +3 -1
  6. data/lib/taskjuggler/KateSyntax.rb +213 -0
  7. data/lib/taskjuggler/Limits.rb +22 -0
  8. data/lib/taskjuggler/Log.rb +1 -1
  9. data/lib/taskjuggler/MessageHandler.rb +20 -10
  10. data/lib/taskjuggler/PTNProxy.rb +6 -1
  11. data/lib/taskjuggler/Project.rb +10 -4
  12. data/lib/taskjuggler/ProjectFileParser.rb +1 -2
  13. data/lib/taskjuggler/ProjectFileScanner.rb +41 -42
  14. data/lib/taskjuggler/ResourceScenario.rb +41 -1
  15. data/lib/taskjuggler/RichText/Element.rb +8 -0
  16. data/lib/taskjuggler/RichText/Parser.rb +1 -1
  17. data/lib/taskjuggler/RichText/RTFReportLink.rb +20 -10
  18. data/lib/taskjuggler/RichText/Scanner.rb +54 -38
  19. data/lib/taskjuggler/RichText/SyntaxRules.rb +12 -0
  20. data/lib/taskjuggler/SheetReceiver.rb +1 -1
  21. data/lib/taskjuggler/TableColumnDefinition.rb +5 -1
  22. data/lib/taskjuggler/TaskJuggler.rb +2 -2
  23. data/lib/taskjuggler/TaskScenario.rb +117 -33
  24. data/lib/taskjuggler/TextParser.rb +2 -4
  25. data/lib/taskjuggler/TextParser/MacroTable.rb +7 -0
  26. data/lib/taskjuggler/TextParser/Scanner.rb +10 -9
  27. data/lib/taskjuggler/Tj3Config.rb +1 -1
  28. data/lib/taskjuggler/TjTime.rb +5 -28
  29. data/lib/taskjuggler/TjpSyntaxRules.rb +85 -13
  30. data/lib/taskjuggler/UTF8String.rb +5 -0
  31. data/lib/taskjuggler/XMLElement.rb +2 -1
  32. data/lib/taskjuggler/apps/Tj3.rb +29 -5
  33. data/lib/taskjuggler/daemon/ProcessIntercom.rb +1 -1
  34. data/lib/taskjuggler/daemon/ProjectServer.rb +5 -2
  35. data/lib/taskjuggler/daemon/ReportServer.rb +7 -4
  36. data/lib/taskjuggler/reports/AccountListRE.rb +2 -0
  37. data/lib/taskjuggler/reports/CSVFile.rb +24 -2
  38. data/lib/taskjuggler/reports/GanttChart.rb +3 -2
  39. data/lib/taskjuggler/reports/GanttHeader.rb +18 -18
  40. data/lib/taskjuggler/reports/GanttLoadStack.rb +1 -1
  41. data/lib/taskjuggler/reports/MspXmlRE.rb +5 -1
  42. data/lib/taskjuggler/reports/Report.rb +29 -18
  43. data/lib/taskjuggler/reports/ReportTable.rb +5 -1
  44. data/lib/taskjuggler/reports/ReportTableCell.rb +16 -10
  45. data/lib/taskjuggler/reports/ResourceListRE.rb +2 -0
  46. data/lib/taskjuggler/reports/TableReport.rb +23 -16
  47. data/lib/taskjuggler/reports/TaskListRE.rb +2 -0
  48. data/lib/taskjuggler/reports/TraceReport.rb +1 -1
  49. data/manual/Installation +5 -1
  50. data/manual/Intro +1 -0
  51. data/manual/Rich_Text_Attributes +5 -0
  52. data/manual/TaskJuggler_Internals +82 -34
  53. data/manual/Tutorial +1 -1
  54. data/manual/html/Day_To_Day_Juggling.html +1 -1
  55. data/manual/html/Getting_Started.html +1 -1
  56. data/manual/html/How_To_Contribute.html +1 -1
  57. data/manual/html/Installation.html +3 -2
  58. data/manual/html/Intro.html +2 -1
  59. data/manual/html/Reporting_Bugs.html +1 -1
  60. data/manual/html/Rich_Text_Attributes.html +2 -1
  61. data/manual/html/Software.html +1 -1
  62. data/manual/html/TaskJuggler_2x_Migration.html +1 -1
  63. data/manual/html/TaskJuggler_Internals.html +15 -13
  64. data/manual/html/The_TaskJuggler_Syntax.html +1 -1
  65. data/manual/html/Tutorial.html +2 -2
  66. data/manual/html/account.html +1 -1
  67. data/manual/html/account.task.html +1 -1
  68. data/manual/html/accountprefix.html +1 -1
  69. data/manual/html/accountreport.html +14 -2
  70. data/manual/html/accountroot.html +1 -1
  71. data/manual/html/active.html +1 -1
  72. data/manual/html/adopt.task.html +1 -1
  73. data/manual/html/aggregate.html +1 -1
  74. data/manual/html/alert.html +1 -1
  75. data/manual/html/alertlevels.html +1 -1
  76. data/manual/html/allocate.html +1 -1
  77. data/manual/html/alphabet.html +1 -1
  78. data/manual/html/alternative.html +1 -1
  79. data/manual/html/author.html +3 -3
  80. data/manual/html/auxdir.html +69 -0
  81. data/manual/html/balance.html +3 -3
  82. data/manual/html/booking.resource.html +1 -1
  83. data/manual/html/booking.task.html +1 -1
  84. data/manual/html/caption.html +1 -1
  85. data/manual/html/cellcolor.column.html +1 -1
  86. data/manual/html/celltext.column.html +1 -1
  87. data/manual/html/center.html +1 -1
  88. data/manual/html/charge.html +1 -1
  89. data/manual/html/chargeset.html +1 -1
  90. data/manual/html/columnid.html +21 -9
  91. data/manual/html/columns.html +2 -2
  92. data/manual/html/complete.html +1 -1
  93. data/manual/html/copyright.html +1 -1
  94. data/manual/html/credits.html +1 -1
  95. data/manual/html/currency.html +1 -1
  96. data/manual/html/currencyformat.html +1 -1
  97. data/manual/html/dailymax.html +1 -1
  98. data/manual/html/dailymin.html +1 -1
  99. data/manual/html/dailyworkinghours.html +1 -1
  100. data/manual/html/date.extend.html +1 -1
  101. data/manual/html/date.html +1 -1
  102. data/manual/html/definitions.html +1 -1
  103. data/manual/html/depends.html +1 -1
  104. data/manual/html/details.html +1 -1
  105. data/manual/html/disabled.html +1 -1
  106. data/manual/html/duration.html +1 -1
  107. data/manual/html/efficiency.html +1 -1
  108. data/manual/html/effort.html +1 -1
  109. data/manual/html/email.html +1 -1
  110. data/manual/html/enabled.html +1 -1
  111. data/manual/html/end.column.html +1 -1
  112. data/manual/html/end.html +1 -1
  113. data/manual/html/end.limit.html +1 -1
  114. data/manual/html/end.report.html +1 -1
  115. data/manual/html/end.timesheet.html +1 -1
  116. data/manual/html/endcredit.html +1 -1
  117. data/manual/html/epilog.html +1 -1
  118. data/manual/html/export.html +1 -1
  119. data/manual/html/extend.html +1 -1
  120. data/manual/html/fail.html +1 -1
  121. data/manual/html/fdl.html +1 -1
  122. data/manual/html/flags.account.html +1 -1
  123. data/manual/html/flags.html +1 -1
  124. data/manual/html/flags.journalentry.html +1 -1
  125. data/manual/html/flags.report.html +1 -1
  126. data/manual/html/flags.resource.html +1 -1
  127. data/manual/html/flags.statussheet.html +1 -1
  128. data/manual/html/flags.task.html +1 -1
  129. data/manual/html/flags.timesheet.html +1 -1
  130. data/manual/html/fontcolor.column.html +1 -1
  131. data/manual/html/footer.html +1 -1
  132. data/manual/html/formats.export.html +1 -1
  133. data/manual/html/formats.html +1 -1
  134. data/manual/html/functions.html +1 -1
  135. data/manual/html/gapduration.html +1 -1
  136. data/manual/html/gaplength.html +1 -1
  137. data/manual/html/halign.center.html +1 -1
  138. data/manual/html/halign.column.html +1 -1
  139. data/manual/html/halign.left.html +1 -1
  140. data/manual/html/halign.right.html +1 -1
  141. data/manual/html/hasalert.html +1 -1
  142. data/manual/html/header.html +1 -1
  143. data/manual/html/headline.html +1 -1
  144. data/manual/html/height.html +1 -1
  145. data/manual/html/hideaccount.html +1 -1
  146. data/manual/html/hidejournalentry.html +1 -1
  147. data/manual/html/hidereport.html +1 -1
  148. data/manual/html/hideresource.html +1 -1
  149. data/manual/html/hidetask.html +1 -1
  150. data/manual/html/icalreport.html +1 -1
  151. data/manual/html/include.macro.html +1 -1
  152. data/manual/html/include.project.html +1 -1
  153. data/manual/html/include.properties.html +1 -1
  154. data/manual/html/index.html +1 -1
  155. data/manual/html/inherit.extend.html +1 -1
  156. data/manual/html/interval1.html +1 -1
  157. data/manual/html/interval2.html +1 -1
  158. data/manual/html/interval3.html +1 -1
  159. data/manual/html/interval4.html +1 -1
  160. data/manual/html/isactive.html +1 -1
  161. data/manual/html/ischildof.html +1 -1
  162. data/manual/html/isdependencyof.html +1 -1
  163. data/manual/html/isdutyof.html +1 -1
  164. data/manual/html/isfeatureof.html +1 -1
  165. data/manual/html/isleaf.html +1 -1
  166. data/manual/html/ismilestone.html +1 -1
  167. data/manual/html/isongoing.html +1 -1
  168. data/manual/html/isresource.html +1 -1
  169. data/manual/html/isresponsibilityof.html +1 -1
  170. data/manual/html/istask.html +1 -1
  171. data/manual/html/journalattributes.html +1 -1
  172. data/manual/html/journalentry.html +1 -1
  173. data/manual/html/journalmode.html +1 -1
  174. data/manual/html/leaveallowance.html +1 -1
  175. data/manual/html/leaves.html +1 -1
  176. data/manual/html/left.html +1 -1
  177. data/manual/html/length.html +1 -1
  178. data/manual/html/limits.allocate.html +1 -1
  179. data/manual/html/limits.html +1 -1
  180. data/manual/html/limits.resource.html +1 -1
  181. data/manual/html/limits.task.html +1 -1
  182. data/manual/html/listitem.column.html +1 -1
  183. data/manual/html/listtype.column.html +1 -1
  184. data/manual/html/loadunit.html +1 -1
  185. data/manual/html/logicalexpression.html +1 -1
  186. data/manual/html/logicalflagexpression.html +1 -1
  187. data/manual/html/macro.html +1 -1
  188. data/manual/html/managers.html +1 -1
  189. data/manual/html/mandatory.html +1 -1
  190. data/manual/html/maxend.html +1 -1
  191. data/manual/html/maximum.html +1 -1
  192. data/manual/html/maxstart.html +1 -1
  193. data/manual/html/milestone.html +1 -1
  194. data/manual/html/minend.html +1 -1
  195. data/manual/html/minimum.html +1 -1
  196. data/manual/html/minstart.html +1 -1
  197. data/manual/html/monthlymax.html +1 -1
  198. data/manual/html/monthlymin.html +1 -1
  199. data/manual/html/navbar.html +9 -1
  200. data/manual/html/navigator.html +1 -1
  201. data/manual/html/newtask.html +1 -1
  202. data/manual/html/nikureport.html +1 -1
  203. data/manual/html/note.task.html +1 -1
  204. data/manual/html/now.html +1 -1
  205. data/manual/html/numberformat.html +1 -1
  206. data/manual/html/onend.html +1 -1
  207. data/manual/html/onstart.html +1 -1
  208. data/manual/html/opennodes.html +1 -1
  209. data/manual/html/overtime.booking.html +1 -1
  210. data/manual/html/period.column.html +1 -1
  211. data/manual/html/period.limit.html +1 -1
  212. data/manual/html/period.report.html +1 -1
  213. data/manual/html/period.task.html +1 -1
  214. data/manual/html/persistent.html +1 -1
  215. data/manual/html/precedes.html +1 -1
  216. data/manual/html/priority.html +1 -1
  217. data/manual/html/priority.timesheet.html +1 -1
  218. data/manual/html/project.html +1 -1
  219. data/manual/html/projectid.html +1 -1
  220. data/manual/html/projectid.task.html +1 -1
  221. data/manual/html/projectids.html +1 -1
  222. data/manual/html/projection.html +1 -1
  223. data/manual/html/prolog.html +1 -1
  224. data/manual/html/properties.html +1 -1
  225. data/manual/html/purge.html +1 -1
  226. data/manual/html/rate.html +1 -1
  227. data/manual/html/rate.resource.html +3 -3
  228. data/manual/html/rawhtmlhead.html +68 -0
  229. data/manual/html/reference.extend.html +3 -3
  230. data/manual/html/remaining.html +1 -1
  231. data/manual/html/replace.html +1 -1
  232. data/manual/html/reportprefix.html +1 -1
  233. data/manual/html/resource.html +1 -1
  234. data/manual/html/resourceattributes.html +1 -1
  235. data/manual/html/resourceprefix.html +1 -1
  236. data/manual/html/resourcereport.html +14 -2
  237. data/manual/html/resourceroot.html +1 -1
  238. data/manual/html/resources.limit.html +1 -1
  239. data/manual/html/responsible.html +1 -1
  240. data/manual/html/richtext.extend.html +1 -1
  241. data/manual/html/right.html +1 -1
  242. data/manual/html/rollupaccount.html +1 -1
  243. data/manual/html/rollupresource.html +1 -1
  244. data/manual/html/rolluptask.html +1 -1
  245. data/manual/html/scale.column.html +1 -1
  246. data/manual/html/scenario.html +1 -1
  247. data/manual/html/scenario.ical.html +1 -1
  248. data/manual/html/scenarios.export.html +1 -1
  249. data/manual/html/scenarios.html +1 -1
  250. data/manual/html/scenariospecific.extend.html +1 -1
  251. data/manual/html/scheduled.html +1 -1
  252. data/manual/html/scheduling.html +2 -1
  253. data/manual/html/select.html +1 -1
  254. data/manual/html/selfcontained.html +1 -1
  255. data/manual/html/shift.allocate.html +1 -1
  256. data/manual/html/shift.html +1 -1
  257. data/manual/html/shift.resource.html +1 -1
  258. data/manual/html/shift.task.html +1 -1
  259. data/manual/html/shift.timesheet.html +1 -1
  260. data/manual/html/shifts.allocate.html +1 -1
  261. data/manual/html/shifts.resource.html +1 -1
  262. data/manual/html/shifts.task.html +1 -1
  263. data/manual/html/shorttimeformat.html +1 -1
  264. data/manual/html/sloppy.booking.html +1 -1
  265. data/manual/html/sloppy.projection.html +1 -1
  266. data/manual/html/sortaccounts.html +1 -1
  267. data/manual/html/sortjournalentries.html +1 -1
  268. data/manual/html/sortresources.html +1 -1
  269. data/manual/html/sorttasks.html +1 -1
  270. data/manual/html/start.column.html +1 -1
  271. data/manual/html/start.html +1 -1
  272. data/manual/html/start.limit.html +1 -1
  273. data/manual/html/start.report.html +1 -1
  274. data/manual/html/startcredit.html +1 -1
  275. data/manual/html/status.statussheet.html +1 -1
  276. data/manual/html/status.timesheet.html +1 -1
  277. data/manual/html/statussheet.html +1 -1
  278. data/manual/html/statussheetreport.html +1 -1
  279. data/manual/html/strict.projection.html +1 -1
  280. data/manual/html/summary.html +1 -1
  281. data/manual/html/supplement.html +1 -1
  282. data/manual/html/supplement.resource.html +1 -1
  283. data/manual/html/supplement.task.html +1 -1
  284. data/manual/html/tagfile.html +2 -2
  285. data/manual/html/task.html +1 -1
  286. data/manual/html/task.statussheet.html +1 -1
  287. data/manual/html/task.timesheet.html +1 -1
  288. data/manual/html/taskattributes.html +1 -1
  289. data/manual/html/taskprefix.html +1 -1
  290. data/manual/html/taskreport.html +14 -2
  291. data/manual/html/taskroot.export.html +1 -1
  292. data/manual/html/taskroot.html +1 -1
  293. data/manual/html/text.extend.html +1 -1
  294. data/manual/html/textreport.html +14 -2
  295. data/manual/html/timeformat.html +3 -3
  296. data/manual/html/timeformat1.html +67 -0
  297. data/manual/html/timeformat2.html +67 -0
  298. data/manual/html/timeoff.nikureport.html +3 -3
  299. data/manual/html/timesheet.html +1 -1
  300. data/manual/html/timesheetreport.html +1 -1
  301. data/manual/html/timezone.export.html +1 -1
  302. data/manual/html/timezone.html +1 -1
  303. data/manual/html/timezone.report.html +1 -1
  304. data/manual/html/timezone.shift.html +1 -1
  305. data/manual/html/timingresolution.html +1 -1
  306. data/manual/html/title.column.html +1 -1
  307. data/manual/html/title.html +1 -1
  308. data/manual/html/toc.html +270 -242
  309. data/manual/html/tooltip.column.html +1 -1
  310. data/manual/html/tracereport.html +14 -2
  311. data/manual/html/trackingscenario.html +1 -1
  312. data/manual/html/treelevel.html +1 -1
  313. data/manual/html/vacation.html +1 -1
  314. data/manual/html/vacation.resource.html +1 -1
  315. data/manual/html/vacation.shift.html +1 -1
  316. data/manual/html/warn.html +1 -1
  317. data/manual/html/weeklymax.html +1 -1
  318. data/manual/html/weeklymin.html +1 -1
  319. data/manual/html/weekstartsmonday.html +1 -1
  320. data/manual/html/weekstartssunday.html +1 -1
  321. data/manual/html/width.column.html +1 -1
  322. data/manual/html/width.html +1 -1
  323. data/manual/html/work.html +1 -1
  324. data/manual/html/workinghours.project.html +1 -1
  325. data/manual/html/workinghours.resource.html +1 -1
  326. data/manual/html/workinghours.shift.html +1 -1
  327. data/manual/html/yearlyworkingdays.html +1 -1
  328. data/tasks/kate.rake +8 -0
  329. data/test/TestSuite/HTML-Reports/Calendars.tjp +10 -0
  330. data/test/TestSuite/Scheduler/Correct/PersistentResources-2.tjp +33 -0
  331. data/test/TestSuite/Scheduler/Correct/PersistentResources.tjp +30 -0
  332. data/test/TestSuite/Scheduler/Correct/PriorityInversion.tjp +2 -0
  333. data/test/TestSuite/Syntax/Correct/Macro-4.tjp +4 -0
  334. data/test/TestSuite/Syntax/Errors/empty.tjp +1 -1
  335. data/test/test_BatchProcessor.rb +1 -1
  336. data/test/test_CSVFile.rb +10 -0
  337. data/test/test_RichText.rb +20 -0
  338. metadata +38 -9
@@ -341,8 +341,7 @@ class TaskJuggler
341
341
  "Unexpected token '#{token[1]}' found. " +
342
342
  "Expecting #{@stack.last.state.expectedTokens.length > 1 ?
343
343
  'one of ' : ''}" +
344
- "#{@stack.last.state.expectedTokens.join(', ')}",
345
- @scanner.sourceFileInfo)
344
+ "#{@stack.last.state.expectedTokens.join(', ')}", token[2])
346
345
  end
347
346
  if finishPattern(token)
348
347
  # Accept: We're done with parsing.
@@ -378,8 +377,7 @@ class TaskJuggler
378
377
  # rules.
379
378
  error('unexpctd_token', "Unexpected token '#{token[1]}' found. " +
380
379
  "Expecting one of " +
381
- "#{stackEntry.state.expectedTokens.join(', ')}",
382
- @scanner.sourceFileInfo)
380
+ "#{stackEntry.state.expectedTokens.join(', ')}", token[2])
383
381
  end
384
382
  # Memorize if the rule for this pattern was repeatable. Then we will
385
383
  # store the result of the pattern in an Array.
@@ -57,6 +57,13 @@ class TaskJuggler::TextParser
57
57
  # unchanged. No error is generated.
58
58
  def resolve(args, sourceFileInfo)
59
59
  name = args[0]
60
+ # If the first character of the macro name is a '?', the macro may be
61
+ # undefined and is silently ignored.
62
+ if name[0] == ??
63
+ # Remove the '?' from the name.
64
+ name = name[1..-1]
65
+ return [ nil, '' ] unless @macros[name]
66
+ end
60
67
  return nil unless @macros[name]
61
68
 
62
69
  resolved = @macros[name].value.dup
@@ -174,7 +174,7 @@ class TaskJuggler::TextParser
174
174
  begin
175
175
  @stream = StringIO.new(data.forceUTF8Encoding)
176
176
  rescue
177
- error('fileEncoding', $!)
177
+ error('fileEncoding', $!.message)
178
178
  end
179
179
  @log.msg { "Parsing file #{@fileName} ..." }
180
180
  @log.startProgressMeter("Reading file #{fileName}")
@@ -195,7 +195,7 @@ class TaskJuggler::TextParser
195
195
  begin
196
196
  @stream = StringIO.new(buffer.forceUTF8Encoding)
197
197
  rescue
198
- error('bufferEncoding', $!)
198
+ error('bufferEncoding', $!.message)
199
199
  end
200
200
  #@log.msg { "Parsing buffer #{buffer[0, 20]} ..." }
201
201
  end
@@ -242,9 +242,9 @@ class TaskJuggler::TextParser
242
242
  tokenPatterns.each do |pat|
243
243
  type = pat[0]
244
244
  regExp = pat[1]
245
- mode = pat[3] || :tjp
246
- postProc = pat[4]
247
- addPattern(type, Regexp.new(regExp), mode, postProc)
245
+ mode = pat[2] || :tjp
246
+ postProc = pat[3]
247
+ addPattern(type, regExp, mode, postProc)
248
248
  end
249
249
  self.mode = defaultMode
250
250
  end
@@ -449,13 +449,14 @@ class TaskJuggler::TextParser
449
449
  def expandMacro(prefix, args, callLength)
450
450
  # Get the expanded macro from the @macroTable.
451
451
  macro, text = @macroTable.resolve(args, sourceFileInfo)
452
- unless macro && text
453
- error('undefined_macro', "Undefined macro '#{args[0]}' called")
454
- end
455
452
 
456
453
  # If the expanded macro is empty, we can ignore it.
457
454
  return if text == ''
458
455
 
456
+ unless macro && text
457
+ error('undefined_macro', "Undefined macro '#{args[0]}' called")
458
+ end
459
+
459
460
  unless @cf.injectMacro(macro, args, prefix + text, callLength)
460
461
  error('macro_stack_overflow', "Too many nested macro calls.")
461
462
  end
@@ -526,7 +527,7 @@ class TaskJuggler::TextParser
526
527
  rescue ArgumentError
527
528
  # This is triggered by StringScanner.scan, but we don't want to put
528
529
  # the block in the inner loops for performance reasons.
529
- error('scan_encoding_error', $!.to_s)
530
+ error('scan_encoding_error', $!.message)
530
531
  end
531
532
  end
532
533
 
@@ -14,7 +14,7 @@
14
14
  require 'taskjuggler/UTF8String'
15
15
  require 'taskjuggler/AppConfig'
16
16
 
17
- AppConfig.version = '3.3.0'
17
+ AppConfig.version = '3.4.0'
18
18
  AppConfig.packageName = 'taskjuggler'
19
19
  AppConfig.softwareName = 'TaskJuggler'
20
20
  AppConfig.packageInfo = 'A Project Management Software'
@@ -370,10 +370,13 @@ class TaskJuggler
370
370
  def to_s(format = nil)
371
371
  return 'unknown' if @time.nil?
372
372
  if format.nil?
373
- format = '%Y-%m-%d-%H:%M' + (@time.sec == 0 ? '' : ':%S') + '-%z'
373
+ fmt = '%Y-%m-%d-%H:%M' + (@time.sec == 0 ? '' : ':%S') + '-%z'
374
+ else
375
+ # Handle TJ specific extensions to the strftime format.
376
+ fmt = format.sub(/%Q/, "#{((localtime.mon - 1) / 3) + 1}")
374
377
  end
375
378
  # Always report values in local timezone
376
- localtime.strftime(format)
379
+ localtime.strftime(fmt)
377
380
  end
378
381
 
379
382
  # Return the seconds since Epoch.
@@ -416,32 +419,6 @@ class TaskJuggler
416
419
  localtime.year
417
420
  end
418
421
 
419
- # Return the abbreviated month name.
420
- def shortMonthName
421
- localtime.strftime('%b')
422
- end
423
-
424
- # Return the number of the quarter prefixed by a 'Q'.
425
- def quarterName
426
- "Q#{(localtime.mon / 3) + 1}"
427
- end
428
-
429
- # Return the week number. _weekStartsMonday_ specifies wheter the counting
430
- # should be for weeks starting Mondays or Sundays.
431
- def week(weekStartsMonday)
432
- localtime.strftime(weekStartsMonday ? '%W' : '%U')
433
- end
434
-
435
- # Return the abbreviated month name and the full year. E. g. 'Feb 1972'.
436
- def monthAndYear
437
- localtime.strftime('%b %Y')
438
- end
439
-
440
- # Return the abbreviated weekday and the full date. E. g. 'Sat 2007-11-03'.
441
- def weekdayAndDate
442
- localtime.strftime('%A %Y-%m-%d')
443
- end
444
-
445
422
  private
446
423
 
447
424
  def parse(t)
@@ -839,6 +839,26 @@ invariant values.
839
839
  EOT
840
840
  )
841
841
 
842
+ pattern(%w( _timeformat1 $STRING ), lambda {
843
+ @column.timeformat1 = @val[1]
844
+ })
845
+ doc('timeformat1', <<'EOT'
846
+ Specify an alternative format for the upper header line of calendar or Gantt
847
+ chart columns.
848
+ EOT
849
+ )
850
+ arg(1, 'format', 'See [[timeformat]] for details.')
851
+
852
+ pattern(%w( _timeformat2 $STRING ), lambda {
853
+ @column.timeformat2 = @val[1]
854
+ })
855
+ doc('timeformat2', <<'EOT'
856
+ Specify an alternative format for the lower header line of calendar or Gantt
857
+ chart columns.
858
+ EOT
859
+ )
860
+ arg(1, 'format', 'See [[timeformat]] for details.')
861
+
842
862
  pattern(%w( _title $STRING ), lambda {
843
863
  @column.title = @val[1]
844
864
  })
@@ -3670,14 +3690,14 @@ EOT
3670
3690
  singlePattern('_annualleave')
3671
3691
  descr(<<'EOT'
3672
3692
  The number of annual leave units within the reported time period. The unit
3673
- can be adjusted with [[loadunit.report]].
3693
+ can be adjusted with [[loadunit]].
3674
3694
  EOT
3675
3695
  )
3676
3696
 
3677
3697
  singlePattern('_annualleavebalance')
3678
3698
  descr(<<'EOT'
3679
3699
  The balance of the annual leave at the end of the reporting interval. The unit
3680
- can be adjusted with [[loadunit.report]].
3700
+ can be adjusted with [[loadunit]].
3681
3701
  EOT
3682
3702
  )
3683
3703
 
@@ -3704,8 +3724,8 @@ EOT
3704
3724
  singlePattern('_alerttrend')
3705
3725
  descr(<<'EOT'
3706
3726
  Shows how the alert level at the end of the report period compares to the
3707
- alert level at the begining of the report period. Possible values are up, down
3708
- or flat.
3727
+ alert level at the begining of the report period. Possible values are
3728
+ ''''Up'''', ''''Down'''' or ''''Flat''''.
3709
3729
  EOT
3710
3730
  )
3711
3731
 
@@ -3730,6 +3750,19 @@ EOT
3730
3750
  The number of sub-tasks (including the current task) that have been closed
3731
3751
  during the reported time period. Closed means that they have and end date
3732
3752
  before the current time or [[now]] date.
3753
+ EOT
3754
+ )
3755
+
3756
+ singlePattern('_competitorcount')
3757
+ descr(<<'EOT'
3758
+ The number of tasks that have successfully competed for the same resources and
3759
+ have potentially delayed the completion of this task.
3760
+ EOT
3761
+ )
3762
+ singlePattern('_competitors')
3763
+ descr(<<'EOT'
3764
+ A list of tasks that have successfully competed for the same resources and
3765
+ have potentially delayed the completion of this task.
3733
3766
  EOT
3734
3767
  )
3735
3768
 
@@ -4020,20 +4053,26 @@ EOT
4020
4053
  singlePattern('_scenario')
4021
4054
  descr('The name of the scenario')
4022
4055
 
4056
+ singlePattern('_scheduling')
4057
+ descr(<<'EOT'
4058
+ The scheduling mode of the leaf tasks. ASAP tasks are scheduled start to end while ALAP tasks are scheduled end to start.
4059
+ EOT
4060
+ )
4061
+
4023
4062
  singlePattern('_seqno')
4024
4063
  descr('The index of the item based on the declaration order')
4025
4064
 
4026
4065
  singlePattern('_sickleave')
4027
4066
  descr(<<'EOT'
4028
4067
  The number of sick leave units within the reported time period. The unit can
4029
- be adjusted with [[loadunit.report]].
4068
+ be adjusted with [[loadunit]].
4030
4069
  EOT
4031
4070
  )
4032
4071
 
4033
4072
  singlePattern('_specialleave')
4034
4073
  descr(<<'EOT'
4035
4074
  The number of special leave units within the reported time period. The unit
4036
- can be adjusted with [[loadunit.report]].
4075
+ can be adjusted with [[loadunit]].
4037
4076
  EOT
4038
4077
  )
4039
4078
 
@@ -4067,7 +4106,7 @@ EOT
4067
4106
  singlePattern('_unpaidleave')
4068
4107
  descr(<<'EOT'
4069
4108
  The number of unpaid leave units within the reported time period. The unit
4070
- can be adjusted with [[loadunit.report]].
4109
+ can be adjusted with [[loadunit]].
4071
4110
  EOT
4072
4111
  )
4073
4112
 
@@ -4100,6 +4139,22 @@ EOT
4100
4139
  )
4101
4140
  example('AccountReport')
4102
4141
 
4142
+ pattern(%w( _auxdir $STRING ), lambda {
4143
+ auxdir = @val[1]
4144
+ # Ensure that the directory always ends with a '/'.
4145
+ auxdir += '/' unless auxdir[-1] == ?/
4146
+ @property.set('auxdir', auxdir)
4147
+ })
4148
+ level(:beta)
4149
+ doc('auxdir', <<'EOT'
4150
+ Specifies an alternative directory for the auxiliary report files such as CSS,
4151
+ JavaScript and icon files. If this attribute is not set, the directoy will be
4152
+ generated automatically. If an alternative is provided, the user has to ensure
4153
+ that the directory exists and is filled with the proper data. The specified
4154
+ path and be absolute or relative to the generated report file.
4155
+ EOT
4156
+ )
4157
+
4103
4158
  pattern(%w( !balance ), lambda {
4104
4159
  @property.set('costaccount', @val[0][0])
4105
4160
  @property.set('revenueaccount', @val[0][1])
@@ -4254,6 +4309,16 @@ EOT
4254
4309
  also(%w( epilog footer header ))
4255
4310
 
4256
4311
  pattern(%w( !purge ))
4312
+
4313
+ pattern(%w( _rawhtmlhead $STRING ), lambda {
4314
+ @property.set('rawHtmlHead', @val[1])
4315
+ })
4316
+ doc('rawhtmlhead', <<'EOT'
4317
+ Define a HTML fragment that will be inserted at the end of the HTML head
4318
+ section.
4319
+ EOT
4320
+ )
4321
+
4257
4322
  pattern(%w( !reports ))
4258
4323
 
4259
4324
  pattern(%w( _right $STRING ), lambda {
@@ -5315,8 +5380,9 @@ EOT
5315
5380
  newReport(@val[1], @val[2], :statusSheet, @sourceFileInfo[0])
5316
5381
  @property.set('formats', [ :tjp ])
5317
5382
 
5318
- unless @project.scenario(0).get('active')
5319
- @property.set('scenarios', [ 0 ])
5383
+ unless (@project['trackingScenarioIdx'])
5384
+ error('ss_no_tracking_scenario',
5385
+ 'You must have a tracking scenario defined to use status sheets.')
5320
5386
  end
5321
5387
  # Show all tasks, sorted by id-up.
5322
5388
  @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
@@ -5627,8 +5693,8 @@ EOT
5627
5693
  @property.set('sortResources', [ [ 'seqno', true, -1 ] ])
5628
5694
  })
5629
5695
  arg(2, 'file name', <<'EOT'
5630
- The name of the tagfile to generate. You can leave it empty and it will
5631
- default to the commonly used name ''''tags''''.
5696
+ The name of the tagfile to generate. Use ''''tags'''' if you want vim and
5697
+ other tools to find it automatically.
5632
5698
  EOT
5633
5699
  )
5634
5700
  end
@@ -6437,6 +6503,10 @@ higher priority. This can result in situations where high priority tasks do
6437
6503
  not get their resources even though the parallel competing tasks have a much
6438
6504
  lower priority.
6439
6505
 
6506
+ ALAP tasks may not have [[booking.task|bookings]] since the first booked slot
6507
+ determines the start date of the task and prevents it from being scheduled
6508
+ from end to start.
6509
+
6440
6510
  As a general rule, try to avoid ALAP tasks whenever possible. Have a close
6441
6511
  eye on tasks that have been switched implicitly to ALAP mode because the
6442
6512
  end attribute comes after the start attribute.
@@ -6971,9 +7041,11 @@ EOT
6971
7041
  newReport(@val[1], @val[2], :timeSheet, @sourceFileInfo[0])
6972
7042
  @property.set('formats', [ :tjp ])
6973
7043
 
6974
- unless @project.scenario(0).get('active')
6975
- @property.set('scenarios', [ 0 ])
7044
+ unless (scenarioIdx = @project['trackingScenarioIdx'])
7045
+ error('ts_no_tracking_scenario',
7046
+ 'You must have a tracking scenario defined to use time sheets.')
6976
7047
  end
7048
+ @property.set('scenarios', [ scenarioIdx ])
6977
7049
  # Show all tasks, sorted by seqno-up.
6978
7050
  @property.set('hideTask', LogicalExpression.new(LogicalOperation.new(0)))
6979
7051
  @property.set('sortTasks', [ [ 'seqno', true, -1 ] ])
@@ -86,6 +86,11 @@ class String
86
86
  len
87
87
  end
88
88
 
89
+ def ljust(len, pad = ' ')
90
+ return self + pad * (len - length_utf8) if length_utf8 < len
91
+ self
92
+ end
93
+
89
94
  alias old_reverse reverse
90
95
 
91
96
  # UTF-8 aware version of reverse that replaces the built-in one.
@@ -87,7 +87,7 @@ class TaskJuggler
87
87
  end
88
88
  @children += arg
89
89
  elsif arg.nil?
90
- # do nothing
90
+ # Do nothing. Insertions of nil are simply ignored.
91
91
  else
92
92
  raise "Elements must be of type XMLElement not #{arg.class}"
93
93
  end
@@ -215,6 +215,7 @@ class TaskJuggler
215
215
 
216
216
  def initialize(blob = '')
217
217
  super(nil, {})
218
+ raise ArgumentError, "blob may not be nil" if blob.nil?
218
219
  @blob = blob
219
220
  end
220
221
 
@@ -35,6 +35,10 @@ class TaskJuggler
35
35
  @checkSyntax = false
36
36
  # Don't generate reports when previous errors have been found.
37
37
  @forceReports = false
38
+ # List of requested report IDs.
39
+ @reportIDs = []
40
+ # List of requested report IDs (as regular expressions).
41
+ @reportRegExpIDs = []
38
42
  # Don't generate trace reports by default
39
43
  @generateTraces = false
40
44
  # Should a booking file be generated?
@@ -72,10 +76,6 @@ EOT
72
76
  format('Restrict debug output to a list of modules')) do |arg|
73
77
  TaskJuggler::Log.segments = arg
74
78
  end
75
- @opts.on('-f', '--force-reports',
76
- format('Generate reports despite scheduling errors')) do
77
- @forceReports = true
78
- end
79
79
  @opts.on('--freeze',
80
80
  format('Generate or update the booking file for ' +
81
81
  'the project. The file will have the same ' +
@@ -120,6 +120,21 @@ EOT
120
120
  'reports.')) do
121
121
  @noReports = true
122
122
  end
123
+ @opts.on('--report <report ID>', String,
124
+ format('Only generate the report with the specified ID. ' +
125
+ 'This option can be used multiple times.')) do |arg|
126
+ @reportIDs << arg
127
+ end
128
+ @opts.on('--reports <report ID RegExp>', String,
129
+ format('Only generate the reports that have IDs that match ' +
130
+ 'the specified regular expression. This option can ' +
131
+ 'be used multiple times.')) do |arg|
132
+ @reportRegExpIDs << arg
133
+ end
134
+ @opts.on('-f', '--force-reports',
135
+ format('Generate reports despite scheduling errors')) do
136
+ @forceReports = true
137
+ end
123
138
  @opts.on('--add-trace',
124
139
  format('Append a current data set to all trace reports.')) do
125
140
  @generateTraces = true
@@ -181,7 +196,16 @@ EOT
181
196
 
182
197
  return 0 if @noReports
183
198
 
184
- return 1 if !tj.generateReports(@outputDir) || tj.errors > 0
199
+ if @reportIDs.empty? && @reportRegExpIDs.empty?
200
+ return 1 if !tj.generateReports(@outputDir) || tj.errors > 0
201
+ else
202
+ @reportIDs.each do |id|
203
+ return 1 if !tj.generateReport(id, false)
204
+ end
205
+ @reportRegExpIDs.each do |id|
206
+ return 1 if !tj.generateReport(id, true)
207
+ end
208
+ end
185
209
 
186
210
  0
187
211
  end
@@ -29,7 +29,7 @@ class TaskJuggler
29
29
  MessageHandlerInstance.instance.trapSetup = false
30
30
  res
31
31
  rescue => e
32
- # Any exception here is a fata error. We try hard to terminate the DRb
32
+ # Any exception here is a fatal error. We try hard to terminate the DRb
33
33
  # thread and then exit the program.
34
34
  begin
35
35
  fatal('pi_crash_trap', "#{e}\n#{e.backtrace.join("\n")}\n\n" +
@@ -340,8 +340,11 @@ class TaskJuggler
340
340
  # If we have not received a ping from the ProjectBroker for 2
341
341
  # minutes, we assume it has died and terminate as well.
342
342
  if TjTime.new - @lastPing > 180
343
- error('daemon_heartbeat_lost',
344
- 'Heartbeat from daemon lost. Terminating.')
343
+ # Since the abort via error() is not thread safe, we issue a
344
+ # warning and abort manually.
345
+ warning('daemon_heartbeat_lost',
346
+ 'Heartbeat from daemon lost. Terminating.')
347
+ exit 1
345
348
  end
346
349
  sleep 1
347
350
  end