##// END OF EJS Templates
Use selected columns in the issues PDF export (#1190)....
Jean-Philippe Lang -
r2736:a49506ce5fa9
parent child
Show More
@@ -1,474 +1,485
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'iconv'
18 require 'iconv'
19 require 'rfpdf/fpdf'
19 require 'rfpdf/fpdf'
20 require 'rfpdf/chinese'
20 require 'rfpdf/chinese'
21
21
22 module Redmine
22 module Redmine
23 module Export
23 module Export
24 module PDF
24 module PDF
25 include ActionView::Helpers::TextHelper
25 include ActionView::Helpers::TextHelper
26 include ActionView::Helpers::NumberHelper
26 include ActionView::Helpers::NumberHelper
27
27
28 class IFPDF < FPDF
28 class IFPDF < FPDF
29 include Redmine::I18n
29 include Redmine::I18n
30 attr_accessor :footer_date
30 attr_accessor :footer_date
31
31
32 def initialize(lang)
32 def initialize(lang)
33 super()
33 super()
34 set_language_if_valid lang
34 set_language_if_valid lang
35 case current_language.to_s.downcase
35 case current_language.to_s.downcase
36 when 'ja'
36 when 'ja'
37 extend(PDF_Japanese)
37 extend(PDF_Japanese)
38 AddSJISFont()
38 AddSJISFont()
39 @font_for_content = 'SJIS'
39 @font_for_content = 'SJIS'
40 @font_for_footer = 'SJIS'
40 @font_for_footer = 'SJIS'
41 when 'zh'
41 when 'zh'
42 extend(PDF_Chinese)
42 extend(PDF_Chinese)
43 AddGBFont()
43 AddGBFont()
44 @font_for_content = 'GB'
44 @font_for_content = 'GB'
45 @font_for_footer = 'GB'
45 @font_for_footer = 'GB'
46 when 'zh-tw'
46 when 'zh-tw'
47 extend(PDF_Chinese)
47 extend(PDF_Chinese)
48 AddBig5Font()
48 AddBig5Font()
49 @font_for_content = 'Big5'
49 @font_for_content = 'Big5'
50 @font_for_footer = 'Big5'
50 @font_for_footer = 'Big5'
51 else
51 else
52 @font_for_content = 'Arial'
52 @font_for_content = 'Arial'
53 @font_for_footer = 'Helvetica'
53 @font_for_footer = 'Helvetica'
54 end
54 end
55 SetCreator(Redmine::Info.app_name)
55 SetCreator(Redmine::Info.app_name)
56 SetFont(@font_for_content)
56 SetFont(@font_for_content)
57 end
57 end
58
58
59 def SetFontStyle(style, size)
59 def SetFontStyle(style, size)
60 SetFont(@font_for_content, style, size)
60 SetFont(@font_for_content, style, size)
61 end
61 end
62
62
63 def SetTitle(txt)
63 def SetTitle(txt)
64 txt = begin
64 txt = begin
65 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
65 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
66 hextxt = "<FEFF" # FEFF is BOM
66 hextxt = "<FEFF" # FEFF is BOM
67 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
67 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
68 hextxt << ">"
68 hextxt << ">"
69 rescue
69 rescue
70 txt
70 txt
71 end || ''
71 end || ''
72 super(txt)
72 super(txt)
73 end
73 end
74
74
75 def textstring(s)
75 def textstring(s)
76 # Format a text string
76 # Format a text string
77 if s =~ /^</ # This means the string is hex-dumped.
77 if s =~ /^</ # This means the string is hex-dumped.
78 return s
78 return s
79 else
79 else
80 return '('+escape(s)+')'
80 return '('+escape(s)+')'
81 end
81 end
82 end
82 end
83
83
84 def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
84 def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
85 @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
85 @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
86 # these quotation marks are not correctly rendered in the pdf
86 # these quotation marks are not correctly rendered in the pdf
87 txt = txt.gsub(/[Ò€œÒ€�]/, '"') if txt
87 txt = txt.gsub(/[Ò€œÒ€�]/, '"') if txt
88 txt = begin
88 txt = begin
89 # 0x5c char handling
89 # 0x5c char handling
90 txtar = txt.split('\\')
90 txtar = txt.split('\\')
91 txtar << '' if txt[-1] == ?\\
91 txtar << '' if txt[-1] == ?\\
92 txtar.collect {|x| @ic.iconv(x)}.join('\\').gsub(/\\/, "\\\\\\\\")
92 txtar.collect {|x| @ic.iconv(x)}.join('\\').gsub(/\\/, "\\\\\\\\")
93 rescue
93 rescue
94 txt
94 txt
95 end || ''
95 end || ''
96 super w,h,txt,border,ln,align,fill,link
96 super w,h,txt,border,ln,align,fill,link
97 end
97 end
98
98
99 def Footer
99 def Footer
100 SetFont(@font_for_footer, 'I', 8)
100 SetFont(@font_for_footer, 'I', 8)
101 SetY(-15)
101 SetY(-15)
102 SetX(15)
102 SetX(15)
103 Cell(0, 5, @footer_date, 0, 0, 'L')
103 Cell(0, 5, @footer_date, 0, 0, 'L')
104 SetY(-15)
104 SetY(-15)
105 SetX(-30)
105 SetX(-30)
106 Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
106 Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
107 end
107 end
108 end
108 end
109
109
110 # Returns a PDF string of a list of issues
110 # Returns a PDF string of a list of issues
111 def issues_to_pdf(issues, project, query)
111 def issues_to_pdf(issues, project, query)
112 pdf = IFPDF.new(current_language)
112 pdf = IFPDF.new(current_language)
113 title = project ? "#{project} - #{l(:label_issue_plural)}" : "#{l(:label_issue_plural)}"
113 title = query.new_record? ? l(:label_issue_plural) : query.name
114 title = "#{project} - #{title}" if project
114 pdf.SetTitle(title)
115 pdf.SetTitle(title)
115 pdf.AliasNbPages
116 pdf.AliasNbPages
116 pdf.footer_date = format_date(Date.today)
117 pdf.footer_date = format_date(Date.today)
117 pdf.AddPage("L")
118 pdf.AddPage("L")
118 row_height = 7
119
120 row_height = 6
121 col_width = []
122 unless query.columns.empty?
123 col_width = query.columns.collect {|column| column.name == :subject ? 4.0 : 1.0 }
124 ratio = 262.0 / col_width.inject(0) {|s,w| s += w}
125 col_width = col_width.collect {|w| w * ratio}
126 end
119
127
120 # title
128 # title
121 pdf.SetFontStyle('B',11)
129 pdf.SetFontStyle('B',11)
122 pdf.Cell(190,10, title)
130 pdf.Cell(190,10, title)
123 pdf.Ln
131 pdf.Ln
124
132
125 # headers
133 # headers
126 pdf.SetFontStyle('B',10)
134 pdf.SetFontStyle('B',8)
127 pdf.SetFillColor(230, 230, 230)
135 pdf.SetFillColor(230, 230, 230)
128 pdf.Cell(15, row_height, "#", 0, 0, 'L', 1)
136 pdf.Cell(15, row_height, "#", 1, 0, 'L', 1)
129 pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
137 query.columns.each_with_index do |column, i|
130 pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
138 pdf.Cell(col_width[i], row_height, column.caption, 1, 0, 'L', 1)
131 pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
139 end
132 pdf.Cell(40, row_height, l(:field_assigned_to), 0, 0, 'L', 1)
133 pdf.Cell(25, row_height, l(:field_updated_on), 0, 0, 'L', 1)
134 pdf.Cell(0, row_height, l(:field_subject), 0, 0, 'L', 1)
135 pdf.Line(10, pdf.GetY, 287, pdf.GetY)
136 pdf.Ln
140 pdf.Ln
137 pdf.Line(10, pdf.GetY, 287, pdf.GetY)
138 pdf.SetY(pdf.GetY() + 1)
139
141
140 # rows
142 # rows
141 pdf.SetFontStyle('',9)
143 pdf.SetFontStyle('',8)
142 pdf.SetFillColor(255, 255, 255)
144 pdf.SetFillColor(255, 255, 255)
143 group = false
145 group = false
144 issues.each do |issue|
146 issues.each do |issue|
145 if query.grouped? && issue.send(query.group_by) != group
147 if query.grouped? && issue.send(query.group_by) != group
146 group = issue.send(query.group_by)
148 group = issue.send(query.group_by)
147 pdf.SetFontStyle('B',10)
149 pdf.SetFontStyle('B',9)
148 pdf.Cell(0, row_height, "#{group.blank? ? 'None' : group.to_s}", 0, 1, 'L')
150 pdf.Cell(277, row_height, "#{group.blank? ? 'None' : group.to_s}", 1, 1, 'L')
149 pdf.Line(10, pdf.GetY, 287, pdf.GetY)
151 pdf.SetFontStyle('',8)
150 pdf.SetY(pdf.GetY() + 0.5)
151 pdf.Line(10, pdf.GetY, 287, pdf.GetY)
152 pdf.SetY(pdf.GetY() + 1)
153 pdf.SetFontStyle('',9)
154 end
152 end
155 pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'L', 1)
153 pdf.Cell(15, row_height, issue.id.to_s, 1, 0, 'L', 1)
156 pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
154 query.columns.each_with_index do |column, i|
157 pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
155 s = if column.is_a?(QueryCustomFieldColumn)
158 pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
156 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
159 pdf.Cell(40, row_height, issue.assigned_to ? issue.assigned_to.to_s : '', 0, 0, 'L', 1)
157 show_value(cv)
160 pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
158 else
161 pdf.MultiCell(0, row_height, (project == issue.project ? issue.subject : "#{issue.project} - #{issue.subject}"))
159 value = issue.send(column.name)
162 pdf.Line(10, pdf.GetY, 287, pdf.GetY)
160 if value.is_a?(Date)
163 pdf.SetY(pdf.GetY() + 1)
161 format_date(value)
162 elsif value.is_a?(Time)
163 format_time(value)
164 else
165 value
166 end
167 end
168 pdf.Cell(col_width[i], row_height, s.to_s, 1, 0, 'L', 1)
169 end
170 pdf.Ln
171 end
172 if issues.size == Setting.issues_export_limit.to_i
173 pdf.SetFontStyle('B',10)
174 pdf.Cell(0, row_height, '...')
164 end
175 end
165 pdf.Output
176 pdf.Output
166 end
177 end
167
178
168 # Returns a PDF string of a single issue
179 # Returns a PDF string of a single issue
169 def issue_to_pdf(issue)
180 def issue_to_pdf(issue)
170 pdf = IFPDF.new(current_language)
181 pdf = IFPDF.new(current_language)
171 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
182 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
172 pdf.AliasNbPages
183 pdf.AliasNbPages
173 pdf.footer_date = format_date(Date.today)
184 pdf.footer_date = format_date(Date.today)
174 pdf.AddPage
185 pdf.AddPage
175
186
176 pdf.SetFontStyle('B',11)
187 pdf.SetFontStyle('B',11)
177 pdf.Cell(190,10, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
188 pdf.Cell(190,10, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
178 pdf.Ln
189 pdf.Ln
179
190
180 y0 = pdf.GetY
191 y0 = pdf.GetY
181
192
182 pdf.SetFontStyle('B',9)
193 pdf.SetFontStyle('B',9)
183 pdf.Cell(35,5, l(:field_status) + ":","LT")
194 pdf.Cell(35,5, l(:field_status) + ":","LT")
184 pdf.SetFontStyle('',9)
195 pdf.SetFontStyle('',9)
185 pdf.Cell(60,5, issue.status.to_s,"RT")
196 pdf.Cell(60,5, issue.status.to_s,"RT")
186 pdf.SetFontStyle('B',9)
197 pdf.SetFontStyle('B',9)
187 pdf.Cell(35,5, l(:field_priority) + ":","LT")
198 pdf.Cell(35,5, l(:field_priority) + ":","LT")
188 pdf.SetFontStyle('',9)
199 pdf.SetFontStyle('',9)
189 pdf.Cell(60,5, issue.priority.to_s,"RT")
200 pdf.Cell(60,5, issue.priority.to_s,"RT")
190 pdf.Ln
201 pdf.Ln
191
202
192 pdf.SetFontStyle('B',9)
203 pdf.SetFontStyle('B',9)
193 pdf.Cell(35,5, l(:field_author) + ":","L")
204 pdf.Cell(35,5, l(:field_author) + ":","L")
194 pdf.SetFontStyle('',9)
205 pdf.SetFontStyle('',9)
195 pdf.Cell(60,5, issue.author.to_s,"R")
206 pdf.Cell(60,5, issue.author.to_s,"R")
196 pdf.SetFontStyle('B',9)
207 pdf.SetFontStyle('B',9)
197 pdf.Cell(35,5, l(:field_category) + ":","L")
208 pdf.Cell(35,5, l(:field_category) + ":","L")
198 pdf.SetFontStyle('',9)
209 pdf.SetFontStyle('',9)
199 pdf.Cell(60,5, issue.category.to_s,"R")
210 pdf.Cell(60,5, issue.category.to_s,"R")
200 pdf.Ln
211 pdf.Ln
201
212
202 pdf.SetFontStyle('B',9)
213 pdf.SetFontStyle('B',9)
203 pdf.Cell(35,5, l(:field_created_on) + ":","L")
214 pdf.Cell(35,5, l(:field_created_on) + ":","L")
204 pdf.SetFontStyle('',9)
215 pdf.SetFontStyle('',9)
205 pdf.Cell(60,5, format_date(issue.created_on),"R")
216 pdf.Cell(60,5, format_date(issue.created_on),"R")
206 pdf.SetFontStyle('B',9)
217 pdf.SetFontStyle('B',9)
207 pdf.Cell(35,5, l(:field_assigned_to) + ":","L")
218 pdf.Cell(35,5, l(:field_assigned_to) + ":","L")
208 pdf.SetFontStyle('',9)
219 pdf.SetFontStyle('',9)
209 pdf.Cell(60,5, issue.assigned_to.to_s,"R")
220 pdf.Cell(60,5, issue.assigned_to.to_s,"R")
210 pdf.Ln
221 pdf.Ln
211
222
212 pdf.SetFontStyle('B',9)
223 pdf.SetFontStyle('B',9)
213 pdf.Cell(35,5, l(:field_updated_on) + ":","LB")
224 pdf.Cell(35,5, l(:field_updated_on) + ":","LB")
214 pdf.SetFontStyle('',9)
225 pdf.SetFontStyle('',9)
215 pdf.Cell(60,5, format_date(issue.updated_on),"RB")
226 pdf.Cell(60,5, format_date(issue.updated_on),"RB")
216 pdf.SetFontStyle('B',9)
227 pdf.SetFontStyle('B',9)
217 pdf.Cell(35,5, l(:field_due_date) + ":","LB")
228 pdf.Cell(35,5, l(:field_due_date) + ":","LB")
218 pdf.SetFontStyle('',9)
229 pdf.SetFontStyle('',9)
219 pdf.Cell(60,5, format_date(issue.due_date),"RB")
230 pdf.Cell(60,5, format_date(issue.due_date),"RB")
220 pdf.Ln
231 pdf.Ln
221
232
222 for custom_value in issue.custom_field_values
233 for custom_value in issue.custom_field_values
223 pdf.SetFontStyle('B',9)
234 pdf.SetFontStyle('B',9)
224 pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
235 pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
225 pdf.SetFontStyle('',9)
236 pdf.SetFontStyle('',9)
226 pdf.MultiCell(155,5, (show_value custom_value),"R")
237 pdf.MultiCell(155,5, (show_value custom_value),"R")
227 end
238 end
228
239
229 pdf.SetFontStyle('B',9)
240 pdf.SetFontStyle('B',9)
230 pdf.Cell(35,5, l(:field_subject) + ":","LTB")
241 pdf.Cell(35,5, l(:field_subject) + ":","LTB")
231 pdf.SetFontStyle('',9)
242 pdf.SetFontStyle('',9)
232 pdf.Cell(155,5, issue.subject,"RTB")
243 pdf.Cell(155,5, issue.subject,"RTB")
233 pdf.Ln
244 pdf.Ln
234
245
235 pdf.SetFontStyle('B',9)
246 pdf.SetFontStyle('B',9)
236 pdf.Cell(35,5, l(:field_description) + ":")
247 pdf.Cell(35,5, l(:field_description) + ":")
237 pdf.SetFontStyle('',9)
248 pdf.SetFontStyle('',9)
238 pdf.MultiCell(155,5, @issue.description,"BR")
249 pdf.MultiCell(155,5, @issue.description,"BR")
239
250
240 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
251 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
241 pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
252 pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
242 pdf.Ln
253 pdf.Ln
243
254
244 if issue.changesets.any? && User.current.allowed_to?(:view_changesets, issue.project)
255 if issue.changesets.any? && User.current.allowed_to?(:view_changesets, issue.project)
245 pdf.SetFontStyle('B',9)
256 pdf.SetFontStyle('B',9)
246 pdf.Cell(190,5, l(:label_associated_revisions), "B")
257 pdf.Cell(190,5, l(:label_associated_revisions), "B")
247 pdf.Ln
258 pdf.Ln
248 for changeset in issue.changesets
259 for changeset in issue.changesets
249 pdf.SetFontStyle('B',8)
260 pdf.SetFontStyle('B',8)
250 pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.author.to_s)
261 pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.author.to_s)
251 pdf.Ln
262 pdf.Ln
252 unless changeset.comments.blank?
263 unless changeset.comments.blank?
253 pdf.SetFontStyle('',8)
264 pdf.SetFontStyle('',8)
254 pdf.MultiCell(190,5, changeset.comments)
265 pdf.MultiCell(190,5, changeset.comments)
255 end
266 end
256 pdf.Ln
267 pdf.Ln
257 end
268 end
258 end
269 end
259
270
260 pdf.SetFontStyle('B',9)
271 pdf.SetFontStyle('B',9)
261 pdf.Cell(190,5, l(:label_history), "B")
272 pdf.Cell(190,5, l(:label_history), "B")
262 pdf.Ln
273 pdf.Ln
263 for journal in issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
274 for journal in issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
264 pdf.SetFontStyle('B',8)
275 pdf.SetFontStyle('B',8)
265 pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
276 pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
266 pdf.Ln
277 pdf.Ln
267 pdf.SetFontStyle('I',8)
278 pdf.SetFontStyle('I',8)
268 for detail in journal.details
279 for detail in journal.details
269 pdf.Cell(190,5, "- " + show_detail(detail, true))
280 pdf.Cell(190,5, "- " + show_detail(detail, true))
270 pdf.Ln
281 pdf.Ln
271 end
282 end
272 if journal.notes?
283 if journal.notes?
273 pdf.SetFontStyle('',8)
284 pdf.SetFontStyle('',8)
274 pdf.MultiCell(190,5, journal.notes)
285 pdf.MultiCell(190,5, journal.notes)
275 end
286 end
276 pdf.Ln
287 pdf.Ln
277 end
288 end
278
289
279 if issue.attachments.any?
290 if issue.attachments.any?
280 pdf.SetFontStyle('B',9)
291 pdf.SetFontStyle('B',9)
281 pdf.Cell(190,5, l(:label_attachment_plural), "B")
292 pdf.Cell(190,5, l(:label_attachment_plural), "B")
282 pdf.Ln
293 pdf.Ln
283 for attachment in issue.attachments
294 for attachment in issue.attachments
284 pdf.SetFontStyle('',8)
295 pdf.SetFontStyle('',8)
285 pdf.Cell(80,5, attachment.filename)
296 pdf.Cell(80,5, attachment.filename)
286 pdf.Cell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
297 pdf.Cell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
287 pdf.Cell(25,5, format_date(attachment.created_on),0,0,"R")
298 pdf.Cell(25,5, format_date(attachment.created_on),0,0,"R")
288 pdf.Cell(65,5, attachment.author.name,0,0,"R")
299 pdf.Cell(65,5, attachment.author.name,0,0,"R")
289 pdf.Ln
300 pdf.Ln
290 end
301 end
291 end
302 end
292 pdf.Output
303 pdf.Output
293 end
304 end
294
305
295 # Returns a PDF string of a gantt chart
306 # Returns a PDF string of a gantt chart
296 def gantt_to_pdf(gantt, project)
307 def gantt_to_pdf(gantt, project)
297 pdf = IFPDF.new(current_language)
308 pdf = IFPDF.new(current_language)
298 pdf.SetTitle("#{l(:label_gantt)} #{project}")
309 pdf.SetTitle("#{l(:label_gantt)} #{project}")
299 pdf.AliasNbPages
310 pdf.AliasNbPages
300 pdf.footer_date = format_date(Date.today)
311 pdf.footer_date = format_date(Date.today)
301 pdf.AddPage("L")
312 pdf.AddPage("L")
302 pdf.SetFontStyle('B',12)
313 pdf.SetFontStyle('B',12)
303 pdf.SetX(15)
314 pdf.SetX(15)
304 pdf.Cell(70, 20, project.to_s)
315 pdf.Cell(70, 20, project.to_s)
305 pdf.Ln
316 pdf.Ln
306 pdf.SetFontStyle('B',9)
317 pdf.SetFontStyle('B',9)
307
318
308 subject_width = 70
319 subject_width = 70
309 header_heigth = 5
320 header_heigth = 5
310
321
311 headers_heigth = header_heigth
322 headers_heigth = header_heigth
312 show_weeks = false
323 show_weeks = false
313 show_days = false
324 show_days = false
314
325
315 if gantt.months < 7
326 if gantt.months < 7
316 show_weeks = true
327 show_weeks = true
317 headers_heigth = 2*header_heigth
328 headers_heigth = 2*header_heigth
318 if gantt.months < 3
329 if gantt.months < 3
319 show_days = true
330 show_days = true
320 headers_heigth = 3*header_heigth
331 headers_heigth = 3*header_heigth
321 end
332 end
322 end
333 end
323
334
324 g_width = 210
335 g_width = 210
325 zoom = (g_width) / (gantt.date_to - gantt.date_from + 1)
336 zoom = (g_width) / (gantt.date_to - gantt.date_from + 1)
326 g_height = 120
337 g_height = 120
327 t_height = g_height + headers_heigth
338 t_height = g_height + headers_heigth
328
339
329 y_start = pdf.GetY
340 y_start = pdf.GetY
330
341
331 # Months headers
342 # Months headers
332 month_f = gantt.date_from
343 month_f = gantt.date_from
333 left = subject_width
344 left = subject_width
334 height = header_heigth
345 height = header_heigth
335 gantt.months.times do
346 gantt.months.times do
336 width = ((month_f >> 1) - month_f) * zoom
347 width = ((month_f >> 1) - month_f) * zoom
337 pdf.SetY(y_start)
348 pdf.SetY(y_start)
338 pdf.SetX(left)
349 pdf.SetX(left)
339 pdf.Cell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
350 pdf.Cell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
340 left = left + width
351 left = left + width
341 month_f = month_f >> 1
352 month_f = month_f >> 1
342 end
353 end
343
354
344 # Weeks headers
355 # Weeks headers
345 if show_weeks
356 if show_weeks
346 left = subject_width
357 left = subject_width
347 height = header_heigth
358 height = header_heigth
348 if gantt.date_from.cwday == 1
359 if gantt.date_from.cwday == 1
349 # gantt.date_from is monday
360 # gantt.date_from is monday
350 week_f = gantt.date_from
361 week_f = gantt.date_from
351 else
362 else
352 # find next monday after gantt.date_from
363 # find next monday after gantt.date_from
353 week_f = gantt.date_from + (7 - gantt.date_from.cwday + 1)
364 week_f = gantt.date_from + (7 - gantt.date_from.cwday + 1)
354 width = (7 - gantt.date_from.cwday + 1) * zoom-1
365 width = (7 - gantt.date_from.cwday + 1) * zoom-1
355 pdf.SetY(y_start + header_heigth)
366 pdf.SetY(y_start + header_heigth)
356 pdf.SetX(left)
367 pdf.SetX(left)
357 pdf.Cell(width + 1, height, "", "LTR")
368 pdf.Cell(width + 1, height, "", "LTR")
358 left = left + width+1
369 left = left + width+1
359 end
370 end
360 while week_f <= gantt.date_to
371 while week_f <= gantt.date_to
361 width = (week_f + 6 <= gantt.date_to) ? 7 * zoom : (gantt.date_to - week_f + 1) * zoom
372 width = (week_f + 6 <= gantt.date_to) ? 7 * zoom : (gantt.date_to - week_f + 1) * zoom
362 pdf.SetY(y_start + header_heigth)
373 pdf.SetY(y_start + header_heigth)
363 pdf.SetX(left)
374 pdf.SetX(left)
364 pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
375 pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
365 left = left + width
376 left = left + width
366 week_f = week_f+7
377 week_f = week_f+7
367 end
378 end
368 end
379 end
369
380
370 # Days headers
381 # Days headers
371 if show_days
382 if show_days
372 left = subject_width
383 left = subject_width
373 height = header_heigth
384 height = header_heigth
374 wday = gantt.date_from.cwday
385 wday = gantt.date_from.cwday
375 pdf.SetFontStyle('B',7)
386 pdf.SetFontStyle('B',7)
376 (gantt.date_to - gantt.date_from + 1).to_i.times do
387 (gantt.date_to - gantt.date_from + 1).to_i.times do
377 width = zoom
388 width = zoom
378 pdf.SetY(y_start + 2 * header_heigth)
389 pdf.SetY(y_start + 2 * header_heigth)
379 pdf.SetX(left)
390 pdf.SetX(left)
380 pdf.Cell(width, height, day_name(wday).first, "LTR", 0, "C")
391 pdf.Cell(width, height, day_name(wday).first, "LTR", 0, "C")
381 left = left + width
392 left = left + width
382 wday = wday + 1
393 wday = wday + 1
383 wday = 1 if wday > 7
394 wday = 1 if wday > 7
384 end
395 end
385 end
396 end
386
397
387 pdf.SetY(y_start)
398 pdf.SetY(y_start)
388 pdf.SetX(15)
399 pdf.SetX(15)
389 pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
400 pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
390
401
391 # Tasks
402 # Tasks
392 top = headers_heigth + y_start
403 top = headers_heigth + y_start
393 pdf.SetFontStyle('B',7)
404 pdf.SetFontStyle('B',7)
394 gantt.events.each do |i|
405 gantt.events.each do |i|
395 pdf.SetY(top)
406 pdf.SetY(top)
396 pdf.SetX(15)
407 pdf.SetX(15)
397
408
398 if i.is_a? Issue
409 if i.is_a? Issue
399 pdf.Cell(subject_width-15, 5, "#{i.tracker} #{i.id}: #{i.subject}".sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), "LR")
410 pdf.Cell(subject_width-15, 5, "#{i.tracker} #{i.id}: #{i.subject}".sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), "LR")
400 else
411 else
401 pdf.Cell(subject_width-15, 5, "#{l(:label_version)}: #{i.name}", "LR")
412 pdf.Cell(subject_width-15, 5, "#{l(:label_version)}: #{i.name}", "LR")
402 end
413 end
403
414
404 pdf.SetY(top)
415 pdf.SetY(top)
405 pdf.SetX(subject_width)
416 pdf.SetX(subject_width)
406 pdf.Cell(g_width, 5, "", "LR")
417 pdf.Cell(g_width, 5, "", "LR")
407
418
408 pdf.SetY(top+1.5)
419 pdf.SetY(top+1.5)
409
420
410 if i.is_a? Issue
421 if i.is_a? Issue
411 i_start_date = (i.start_date >= gantt.date_from ? i.start_date : gantt.date_from )
422 i_start_date = (i.start_date >= gantt.date_from ? i.start_date : gantt.date_from )
412 i_end_date = (i.due_before <= gantt.date_to ? i.due_before : gantt.date_to )
423 i_end_date = (i.due_before <= gantt.date_to ? i.due_before : gantt.date_to )
413
424
414 i_done_date = i.start_date + ((i.due_before - i.start_date+1)*i.done_ratio/100).floor
425 i_done_date = i.start_date + ((i.due_before - i.start_date+1)*i.done_ratio/100).floor
415 i_done_date = (i_done_date <= gantt.date_from ? gantt.date_from : i_done_date )
426 i_done_date = (i_done_date <= gantt.date_from ? gantt.date_from : i_done_date )
416 i_done_date = (i_done_date >= gantt.date_to ? gantt.date_to : i_done_date )
427 i_done_date = (i_done_date >= gantt.date_to ? gantt.date_to : i_done_date )
417
428
418 i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
429 i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
419
430
420 i_left = ((i_start_date - gantt.date_from)*zoom)
431 i_left = ((i_start_date - gantt.date_from)*zoom)
421 i_width = ((i_end_date - i_start_date + 1)*zoom)
432 i_width = ((i_end_date - i_start_date + 1)*zoom)
422 d_width = ((i_done_date - i_start_date)*zoom)
433 d_width = ((i_done_date - i_start_date)*zoom)
423 l_width = ((i_late_date - i_start_date+1)*zoom) if i_late_date
434 l_width = ((i_late_date - i_start_date+1)*zoom) if i_late_date
424 l_width ||= 0
435 l_width ||= 0
425
436
426 pdf.SetX(subject_width + i_left)
437 pdf.SetX(subject_width + i_left)
427 pdf.SetFillColor(200,200,200)
438 pdf.SetFillColor(200,200,200)
428 pdf.Cell(i_width, 2, "", 0, 0, "", 1)
439 pdf.Cell(i_width, 2, "", 0, 0, "", 1)
429
440
430 if l_width > 0
441 if l_width > 0
431 pdf.SetY(top+1.5)
442 pdf.SetY(top+1.5)
432 pdf.SetX(subject_width + i_left)
443 pdf.SetX(subject_width + i_left)
433 pdf.SetFillColor(255,100,100)
444 pdf.SetFillColor(255,100,100)
434 pdf.Cell(l_width, 2, "", 0, 0, "", 1)
445 pdf.Cell(l_width, 2, "", 0, 0, "", 1)
435 end
446 end
436 if d_width > 0
447 if d_width > 0
437 pdf.SetY(top+1.5)
448 pdf.SetY(top+1.5)
438 pdf.SetX(subject_width + i_left)
449 pdf.SetX(subject_width + i_left)
439 pdf.SetFillColor(100,100,255)
450 pdf.SetFillColor(100,100,255)
440 pdf.Cell(d_width, 2, "", 0, 0, "", 1)
451 pdf.Cell(d_width, 2, "", 0, 0, "", 1)
441 end
452 end
442
453
443 pdf.SetY(top+1.5)
454 pdf.SetY(top+1.5)
444 pdf.SetX(subject_width + i_left + i_width)
455 pdf.SetX(subject_width + i_left + i_width)
445 pdf.Cell(30, 2, "#{i.status} #{i.done_ratio}%")
456 pdf.Cell(30, 2, "#{i.status} #{i.done_ratio}%")
446 else
457 else
447 i_left = ((i.start_date - gantt.date_from)*zoom)
458 i_left = ((i.start_date - gantt.date_from)*zoom)
448
459
449 pdf.SetX(subject_width + i_left)
460 pdf.SetX(subject_width + i_left)
450 pdf.SetFillColor(50,200,50)
461 pdf.SetFillColor(50,200,50)
451 pdf.Cell(2, 2, "", 0, 0, "", 1)
462 pdf.Cell(2, 2, "", 0, 0, "", 1)
452
463
453 pdf.SetY(top+1.5)
464 pdf.SetY(top+1.5)
454 pdf.SetX(subject_width + i_left + 3)
465 pdf.SetX(subject_width + i_left + 3)
455 pdf.Cell(30, 2, "#{i.name}")
466 pdf.Cell(30, 2, "#{i.name}")
456 end
467 end
457
468
458 top = top + 5
469 top = top + 5
459 pdf.SetDrawColor(200, 200, 200)
470 pdf.SetDrawColor(200, 200, 200)
460 pdf.Line(15, top, subject_width+g_width, top)
471 pdf.Line(15, top, subject_width+g_width, top)
461 if pdf.GetY() > 180
472 if pdf.GetY() > 180
462 pdf.AddPage("L")
473 pdf.AddPage("L")
463 top = 20
474 top = 20
464 pdf.Line(15, top, subject_width+g_width, top)
475 pdf.Line(15, top, subject_width+g_width, top)
465 end
476 end
466 pdf.SetDrawColor(0, 0, 0)
477 pdf.SetDrawColor(0, 0, 0)
467 end
478 end
468
479
469 pdf.Line(15, top, subject_width+g_width, top)
480 pdf.Line(15, top, subject_width+g_width, top)
470 pdf.Output
481 pdf.Output
471 end
482 end
472 end
483 end
473 end
484 end
474 end
485 end
General Comments 0
You need to be logged in to leave comments. Login now