lib/reports/Report.rb in taskjuggler-0.0.2 vs lib/reports/Report.rb in taskjuggler-0.0.3

- old
+ new

@@ -8,99 +8,71 @@ # This program is free software; you can redistribute it and/or modify # it under the terms of version 2 of the GNU General Public License as # published by the Free Software Foundation. # -require 'reports/ReportElement' +require 'PropertyTreeNode' +require 'reports/TextReport' require 'reports/TaskListRE' require 'reports/ResourceListRE' require 'reports/TjpExportRE' require 'reports/CSVFile' +require 'reports/Navigator' +require 'reports/ReportContext' require 'HTMLDocument' class TaskJuggler - # The Report class holds the fundamental description and functionality to turn - # the scheduled project into a user readable form. A report consists of one or - # more ReportElement objects and some attributes that are global to all - # elements. - class Report + # The Report class holds the fundamental description and functionality to + # turn the scheduled project into a user readable form. A report may contain + # other reports. + class Report < PropertyTreeNode - attr_reader :name, :project, :start, :end, :userDefinedPeriod, - :sourceFileInfo - attr_accessor :costAccount, :currencyformat, :loadUnit, :now, - :numberformat, :resourceRoot, :revenueAccount, - :shorttimeformat, :taskRoot, :timeformat, :timezone, - :weekstartsmonday + attr_accessor :typeSpec, :content # Create a new report object. - def initialize(project, name, format, sourceFileInfo) - @project = project - @name = name - @project.addReport(self) - @outputFormats = [ format ] - @sourceFileInfo = sourceFileInfo + def initialize(project, id, name, parent) + super(project.reports, id, name, parent) + project.addReport(self) - # The following attributes determine the content and look of the report. - @costAccount = @project['costAccount'] - @currencyformat = @project['currencyformat'] - @loadUnit = @project['loadunit'] - @end = @project['end'] - @now = @project['now'] - @numberformat = @project['numberformat'] - @resourceRoot = nil - @revenueAccount = @project['revenueAccount'] - @shorttimeformat = @project['shorttimeformat'] - @start = @project['start'] - @taskRoot = nil - @timeformat = @project['timeformat'] - @timezone = @project['timezone'] - @userDefinedPeriod = false - @weekstartsmonday = @project['weekstartsmonday'] - - @elements = [] + # The type specifier must be set for every report. It tells whether this + # is a task, resource, text or other report. + @typeSpec = nil end - # Set the start _date_ of the report period and mark it as user defined. - def start=(date) - @start = date - @userDefinedPeriod = true - end - - # Set the end _date_ of the report period and mark it as user defined. - def end=(date) - @end = date - @userDefinedPeriod = true - end - - # Add new ouput format request. - def addFormat(format) - @outputFormats << format - end - # The generate function is where the action happens in this class. The # report defined by all the class attributes and report elements is # generated according the the requested output format(s). def generate begin + @content = nil + case @typeSpec + when :export + # Does not have an intermediate representation. Nothing to do here. + when :resourcereport + @content = ResourceListRE.new(self) + when :textreport + @content = TextReport.new(self) + when :taskreport + @content = TaskListRE.new(self) + else + raise "Unknown report type" + end + # Most output format can be generated from a common intermediate # representation of the elements. We generate that IR first. - @elements.each do |element| - element.generateIntermediateFormat - end + @content.generateIntermediateFormat if @content # Then generate the actual output format. - @outputFormats.each do |format| + get('formats').each do |format| case format when :html generateHTML when :csv generateCSV when :export generateExport - when :gui - # TODO: Find a way to hook up the GUI here. else raise 'Unknown report output format.' end end rescue TjException @@ -108,17 +80,21 @@ $!.message, nil, nil, @sourceFileInfo)) end end - # This function should only be called within the library. It's not a user - # callable function. - def addElement(element) # :nodoc: - @elements << element + # Render the content of the report as HTML (without the framing). + def to_html + @content ? @content.to_html : nil end + private + # Convenience function to access a report attribute + def a(attribute) + get(attribute) + end # Generate an HTML version of the report. def generateHTML html = HTMLDocument.new(:transitional) html << (head = XMLElement.new('head')) @@ -178,10 +154,11 @@ overflow:auto; } .tabline { color:#000000 } .tabcell { white-space:nowrap; + overflow:hidden; padding:0px; } .taskcell1 { background-color:#ebf2ff; white-space:nowrap; @@ -244,11 +221,11 @@ .loadstackframe { background-color:#452a2a; position:absolute; } .free { - background-color:#a5ffb4; + background-color:#a5ffb5; position:absolute; } .busy { background-color:#ff9b9b; position:absolute; @@ -284,21 +261,26 @@ } EOT ) html << (body = XMLElement.new('body')) - @elements.each do |element| - body << element.to_html - end + # Make sure we have some margins around the report. + body << (frame = XMLElement.new('div', + 'style' => 'margin: 35px 5% 25px 5%; ')) - html.write(@name + '.html') + frame << @content.to_html if @content + + html.write((@name[0] == '/' ? '' : @project.outputDir) + + @name + (@name == '.' ? '' : '.html')) end # Generate a CSV version of the report. def generateCSV + return nil unless @content + # CSV format can only handle the first element. - csv = @elements[0].to_csv + csv = @content.to_csv # Expand nested tables into the outer table. columnIdx = 0 while columnIdx < csv[0].length do if csv[0][columnIdx].is_a?(Array) # We've found a nested table. @@ -326,17 +308,20 @@ end end # Use the CSVFile class to write the Array of Arrays to a colon # separated file. Write to $stdout if the filename was set to '.'. - CSVFile.new(csv, ';').write(@name) + CSVFile.new(csv, ';').write((@name[0] == '/' ? '' : @project.outputDir) + + @name + (@name == '.' ? '' : '.csv')) end # Generate an export report def generateExport - extension = @elements[0].mainFile ? 'tjp' : 'tji' - f = @name == '.' ? $stdout : File.new(@name + '.' + extension, 'w') - f.puts "#{@elements[0].to_tjp}" + @content = TjpExportRE.new(self) + f = @name == '.' ? $stdout : + File.new((@name[0] == '/' ? '' : @project.outputDir) + + @name, 'w') + f.puts "#{@content.to_tjp}" end end end