##// END OF EJS Templates
Wrap long text fields properly in PDF exports (#5629)....
Toshi MARUYAMA -
r5484:880e8e575a14
parent child
Show More
@@ -1,403 +1,458
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2009 Jean-Philippe Lang
4 # Copyright (C) 2006-2009 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require 'iconv'
20 require 'iconv'
21 require 'rfpdf/fpdf'
21 require 'rfpdf/fpdf'
22 require 'fpdf/chinese'
22 require 'fpdf/chinese'
23 require 'fpdf/japanese'
23 require 'fpdf/japanese'
24 require 'fpdf/korean'
24 require 'fpdf/korean'
25
25
26 module Redmine
26 module Redmine
27 module Export
27 module Export
28 module PDF
28 module PDF
29 include ActionView::Helpers::TextHelper
29 include ActionView::Helpers::TextHelper
30 include ActionView::Helpers::NumberHelper
30 include ActionView::Helpers::NumberHelper
31
31
32 class ITCPDF < TCPDF
32 class ITCPDF < TCPDF
33 include Redmine::I18n
33 include Redmine::I18n
34 attr_accessor :footer_date
34 attr_accessor :footer_date
35
35
36 def initialize(lang)
36 def initialize(lang)
37 super()
37 super()
38 set_language_if_valid lang
38 set_language_if_valid lang
39 @font_for_content = 'FreeSans'
39 @font_for_content = 'FreeSans'
40 @font_for_footer = 'FreeSans'
40 @font_for_footer = 'FreeSans'
41 SetCreator(Redmine::Info.app_name)
41 SetCreator(Redmine::Info.app_name)
42 SetFont(@font_for_content)
42 SetFont(@font_for_content)
43 end
43 end
44
44
45 def SetFontStyle(style, size)
45 def SetFontStyle(style, size)
46 SetFont(@font_for_content, style, size)
46 SetFont(@font_for_content, style, size)
47 end
47 end
48
48
49 def SetTitle(txt)
49 def SetTitle(txt)
50 txt = begin
50 txt = begin
51 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
51 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
52 hextxt = "<FEFF" # FEFF is BOM
52 hextxt = "<FEFF" # FEFF is BOM
53 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
53 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
54 hextxt << ">"
54 hextxt << ">"
55 rescue
55 rescue
56 txt
56 txt
57 end || ''
57 end || ''
58 super(txt)
58 super(txt)
59 end
59 end
60
60
61 def textstring(s)
61 def textstring(s)
62 # Format a text string
62 # Format a text string
63 if s =~ /^</ # This means the string is hex-dumped.
63 if s =~ /^</ # This means the string is hex-dumped.
64 return s
64 return s
65 else
65 else
66 return '('+escape(s)+')'
66 return '('+escape(s)+')'
67 end
67 end
68 end
68 end
69
69
70 alias RDMCell Cell
70 alias RDMCell Cell
71 alias RDMMultiCell MultiCell
71 alias RDMMultiCell MultiCell
72
72
73 def Footer
73 def Footer
74 SetFont(@font_for_footer, 'I', 8)
74 SetFont(@font_for_footer, 'I', 8)
75 SetY(-15)
75 SetY(-15)
76 SetX(15)
76 SetX(15)
77 RDMCell(0, 5, @footer_date, 0, 0, 'L')
77 RDMCell(0, 5, @footer_date, 0, 0, 'L')
78 SetY(-15)
78 SetY(-15)
79 SetX(-30)
79 SetX(-30)
80 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
80 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
81 end
81 end
82 end
82 end
83
83
84 class IFPDF < FPDF
84 class IFPDF < FPDF
85 include Redmine::I18n
85 include Redmine::I18n
86 attr_accessor :footer_date
86 attr_accessor :footer_date
87
87
88 def initialize(lang)
88 def initialize(lang)
89 super()
89 super()
90 set_language_if_valid lang
90 set_language_if_valid lang
91 case l(:general_pdf_encoding).upcase
91 case l(:general_pdf_encoding).upcase
92 when 'CP949'
92 when 'CP949'
93 extend(PDF_Korean)
93 extend(PDF_Korean)
94 AddUHCFont()
94 AddUHCFont()
95 @font_for_content = 'UHC'
95 @font_for_content = 'UHC'
96 @font_for_footer = 'UHC'
96 @font_for_footer = 'UHC'
97 when 'CP932'
97 when 'CP932'
98 extend(PDF_Japanese)
98 extend(PDF_Japanese)
99 AddSJISFont()
99 AddSJISFont()
100 @font_for_content = 'SJIS'
100 @font_for_content = 'SJIS'
101 @font_for_footer = 'SJIS'
101 @font_for_footer = 'SJIS'
102 when 'GB18030'
102 when 'GB18030'
103 extend(PDF_Chinese)
103 extend(PDF_Chinese)
104 AddGBFont()
104 AddGBFont()
105 @font_for_content = 'GB'
105 @font_for_content = 'GB'
106 @font_for_footer = 'GB'
106 @font_for_footer = 'GB'
107 when 'BIG5'
107 when 'BIG5'
108 extend(PDF_Chinese)
108 extend(PDF_Chinese)
109 AddBig5Font()
109 AddBig5Font()
110 @font_for_content = 'Big5'
110 @font_for_content = 'Big5'
111 @font_for_footer = 'Big5'
111 @font_for_footer = 'Big5'
112 else
112 else
113 @font_for_content = 'Arial'
113 @font_for_content = 'Arial'
114 @font_for_footer = 'Helvetica'
114 @font_for_footer = 'Helvetica'
115 end
115 end
116 SetCreator(Redmine::Info.app_name)
116 SetCreator(Redmine::Info.app_name)
117 SetFont(@font_for_content)
117 SetFont(@font_for_content)
118 end
118 end
119
119
120 def SetFontStyle(style, size)
120 def SetFontStyle(style, size)
121 SetFont(@font_for_content, style, size)
121 SetFont(@font_for_content, style, size)
122 end
122 end
123
123
124 def SetTitle(txt)
124 def SetTitle(txt)
125 txt = begin
125 txt = begin
126 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
126 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
127 hextxt = "<FEFF" # FEFF is BOM
127 hextxt = "<FEFF" # FEFF is BOM
128 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
128 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
129 hextxt << ">"
129 hextxt << ">"
130 rescue
130 rescue
131 txt
131 txt
132 end || ''
132 end || ''
133 super(txt)
133 super(txt)
134 end
134 end
135
135
136 def textstring(s)
136 def textstring(s)
137 # Format a text string
137 # Format a text string
138 if s =~ /^</ # This means the string is hex-dumped.
138 if s =~ /^</ # This means the string is hex-dumped.
139 return s
139 return s
140 else
140 else
141 return '('+escape(s)+')'
141 return '('+escape(s)+')'
142 end
142 end
143 end
143 end
144
144
145 def fix_text_encoding(txt)
145 def fix_text_encoding(txt)
146 txt ||= ''
146 txt ||= ''
147 if txt.respond_to?(:force_encoding)
147 if txt.respond_to?(:force_encoding)
148 txt.force_encoding('UTF-8')
148 txt.force_encoding('UTF-8')
149 txt = txt.encode(l(:general_pdf_encoding), :invalid => :replace,
149 txt = txt.encode(l(:general_pdf_encoding), :invalid => :replace,
150 :undef => :replace, :replace => '?')
150 :undef => :replace, :replace => '?')
151 txt.force_encoding('ASCII-8BIT')
151 txt.force_encoding('ASCII-8BIT')
152 else
152 else
153 @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
153 @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
154 txtar = ""
154 txtar = ""
155 begin
155 begin
156 txtar += @ic.iconv(txt)
156 txtar += @ic.iconv(txt)
157 rescue Iconv::IllegalSequence
157 rescue Iconv::IllegalSequence
158 txtar += $!.success
158 txtar += $!.success
159 txt = '?' + $!.failed[1,$!.failed.length]
159 txt = '?' + $!.failed[1,$!.failed.length]
160 retry
160 retry
161 rescue
161 rescue
162 txtar += $!.success
162 txtar += $!.success
163 end
163 end
164 txt = txtar
164 txt = txtar
165 end
165 end
166 txt
166 txt
167 end
167 end
168
168
169 def RDMCell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
169 def RDMCell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
170 Cell(w,h,fix_text_encoding(txt),border,ln,align,fill,link)
170 Cell(w,h,fix_text_encoding(txt),border,ln,align,fill,link)
171 end
171 end
172
172
173 def RDMMultiCell(w,h=0,txt='',border=0,align='',fill=0)
173 def RDMMultiCell(w,h=0,txt='',border=0,align='',fill=0)
174 MultiCell(w,h,fix_text_encoding(txt),border,align,fill)
174 MultiCell(w,h,fix_text_encoding(txt),border,align,fill)
175 end
175 end
176
176
177 def Footer
177 def Footer
178 SetFont(@font_for_footer, 'I', 8)
178 SetFont(@font_for_footer, 'I', 8)
179 SetY(-15)
179 SetY(-15)
180 SetX(15)
180 SetX(15)
181 RDMCell(0, 5, @footer_date, 0, 0, 'L')
181 RDMCell(0, 5, @footer_date, 0, 0, 'L')
182 SetY(-15)
182 SetY(-15)
183 SetX(-30)
183 SetX(-30)
184 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
184 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
185 end
185 end
186 alias alias_nb_pages AliasNbPages
186 alias alias_nb_pages AliasNbPages
187 end
187 end
188
188
189 # Returns a PDF string of a list of issues
189 # Returns a PDF string of a list of issues
190 def issues_to_pdf(issues, project, query)
190 def issues_to_pdf(issues, project, query)
191 if l(:general_pdf_encoding).upcase != 'UTF-8'
191 if l(:general_pdf_encoding).upcase != 'UTF-8'
192 pdf = IFPDF.new(current_language)
192 pdf = IFPDF.new(current_language)
193 else
193 else
194 pdf = ITCPDF.new(current_language)
194 pdf = ITCPDF.new(current_language)
195 end
195 end
196 title = query.new_record? ? l(:label_issue_plural) : query.name
196 title = query.new_record? ? l(:label_issue_plural) : query.name
197 title = "#{project} - #{title}" if project
197 title = "#{project} - #{title}" if project
198 pdf.SetTitle(title)
198 pdf.SetTitle(title)
199 pdf.alias_nb_pages
199 pdf.alias_nb_pages
200 pdf.footer_date = format_date(Date.today)
200 pdf.footer_date = format_date(Date.today)
201 pdf.SetAutoPageBreak(false)
201 pdf.AddPage("L")
202 pdf.AddPage("L")
202
203
203 row_height = 6
204 # Landscape A4 = 210 x 297 mm
205 page_height = 210
206 page_width = 297
207 right_margin = 10
208 bottom_margin = 20
209 col_id_width = 10
210 row_height = 5
211
212 # column widths
213 table_width = page_width - right_margin - 10 # fixed left margin
204 col_width = []
214 col_width = []
205 unless query.columns.empty?
215 unless query.columns.empty?
206 col_width = query.columns.collect {|column| column.name == :subject ? 4.0 : 1.0 }
216 col_width = query.columns.collect do |c|
207 ratio = 262.0 / col_width.inject(0) {|s,w| s += w}
217 (c.name == :subject || (c.is_a?(QueryCustomFieldColumn) && ['string', 'text'].include?(c.custom_field.field_format)))? 4.0 : 1.0
218 end
219 ratio = (table_width - col_id_width) / col_width.inject(0) {|s,w| s += w}
208 col_width = col_width.collect {|w| w * ratio}
220 col_width = col_width.collect {|w| w * ratio}
209 end
221 end
210
222
211 # title
223 # title
212 pdf.SetFontStyle('B',11)
224 pdf.SetFontStyle('B',11)
213 pdf.RDMCell(190,10, title)
225 pdf.RDMCell(190,10, title)
214 pdf.Ln
226 pdf.Ln
215
227
216 # headers
228 # headers
217 pdf.SetFontStyle('B',8)
229 pdf.SetFontStyle('B',8)
218 pdf.SetFillColor(230, 230, 230)
230 pdf.SetFillColor(230, 230, 230)
219 pdf.RDMCell(15, row_height, "#", 1, 0, 'L', 1)
231 pdf.RDMCell(col_id_width, row_height, "#", 1, 0, 'C', 1)
220 query.columns.each_with_index do |column, i|
232 query.columns.each_with_index do |column, i|
221 pdf.RDMCell(col_width[i], row_height, column.caption, 1, 0, 'L', 1)
233 pdf.RDMCell(col_width[i], row_height, column.caption, 1, 0, 'L', 1)
222 end
234 end
223 pdf.Ln
235 pdf.Ln
224
236
225 # rows
237 # rows
226 pdf.SetFontStyle('',8)
238 pdf.SetFontStyle('',8)
227 pdf.SetFillColor(255, 255, 255)
239 pdf.SetFillColor(255, 255, 255)
228 previous_group = false
240 previous_group = false
229 issues.each do |issue|
241 issues.each do |issue|
230 if query.grouped? &&
242 if query.grouped? &&
231 (group = query.group_by_column.value(issue)) != previous_group
243 (group = query.group_by_column.value(issue)) != previous_group
232 pdf.SetFontStyle('B',9)
244 pdf.SetFontStyle('B',9)
233 pdf.RDMCell(277, row_height,
245 pdf.RDMCell(277, row_height,
234 (group.blank? ? 'None' : group.to_s) + " (#{query.issue_count_by_group[group]})",
246 (group.blank? ? 'None' : group.to_s) + " (#{query.issue_count_by_group[group]})",
235 1, 1, 'L')
247 1, 1, 'L')
236 pdf.SetFontStyle('',8)
248 pdf.SetFontStyle('',8)
237 previous_group = group
249 previous_group = group
238 end
250 end
239 pdf.RDMCell(15, row_height, issue.id.to_s, 1, 0, 'L', 1)
251 # fetch all the row values
240 query.columns.each_with_index do |column, i|
252 col_values = query.columns.collect do |column|
241 s = if column.is_a?(QueryCustomFieldColumn)
253 s = if column.is_a?(QueryCustomFieldColumn)
242 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
254 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
243 show_value(cv)
255 show_value(cv)
244 else
256 else
245 value = issue.send(column.name)
257 value = issue.send(column.name)
246 if value.is_a?(Date)
258 if value.is_a?(Date)
247 format_date(value)
259 format_date(value)
248 elsif value.is_a?(Time)
260 elsif value.is_a?(Time)
249 format_time(value)
261 format_time(value)
250 else
262 else
251 value
263 value
252 end
264 end
253 end
265 end
254 pdf.RDMCell(col_width[i], row_height, s.to_s, 1, 0, 'L', 1)
266 s.to_s
255 end
267 end
256 pdf.Ln
268
269 # render it off-page to find the max height used
270 base_x = pdf.GetX
271 base_y = pdf.GetY
272 pdf.SetY(2 * page_height)
273 max_height = issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
274 pdf.SetXY(base_x, base_y)
275
276 # make new page if it doesn't fit on the current one
277 space_left = page_height - base_y - bottom_margin
278 if max_height > space_left
279 pdf.AddPage("L")
280 base_x = pdf.GetX
281 base_y = pdf.GetY
282 end
283
284 # write the cells on page
285 pdf.RDMCell(col_id_width, row_height, issue.id.to_s, "T", 0, 'C', 1)
286 issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
287 issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
288 pdf.SetY(base_y + max_height);
257 end
289 end
290
258 if issues.size == Setting.issues_export_limit.to_i
291 if issues.size == Setting.issues_export_limit.to_i
259 pdf.SetFontStyle('B',10)
292 pdf.SetFontStyle('B',10)
260 pdf.RDMCell(0, row_height, '...')
293 pdf.RDMCell(0, row_height, '...')
261 end
294 end
262 pdf.Output
295 pdf.Output
263 end
296 end
264
297
298 # Renders MultiCells and returns the maximum height used
299 def issues_to_pdf_write_cells(pdf, col_values, col_widths, row_height)
300 base_y = pdf.GetY
301 max_height = row_height
302 col_values.each_with_index do |column, i|
303 col_x = pdf.GetX
304 pdf.RDMMultiCell(col_widths[i], row_height, col_values[i], "T", 'L', 1)
305 max_height = (pdf.GetY - base_y) if (pdf.GetY - base_y) > max_height
306 pdf.SetXY(col_x + col_widths[i], base_y);
307 end
308 return max_height
309 end
310
311 # Draw lines to close the row (MultiCell border drawing in not uniform)
312 def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y, id_width, col_widths)
313 col_x = top_x + id_width
314 pdf.Line(col_x, top_y, col_x, lower_y) # id right border
315 col_widths.each do |width|
316 col_x += width
317 pdf.Line(col_x, top_y, col_x, lower_y) # columns right border
318 end
319 pdf.Line(top_x, top_y, top_x, lower_y) # left border
320 pdf.Line(top_x, lower_y, col_x, lower_y) # bottom border
321 end
322
265 # Returns a PDF string of a single issue
323 # Returns a PDF string of a single issue
266 def issue_to_pdf(issue)
324 def issue_to_pdf(issue)
267 if l(:general_pdf_encoding).upcase != 'UTF-8'
325 if l(:general_pdf_encoding).upcase != 'UTF-8'
268 pdf = IFPDF.new(current_language)
326 pdf = IFPDF.new(current_language)
269 else
327 else
270 pdf = ITCPDF.new(current_language)
328 pdf = ITCPDF.new(current_language)
271 end
329 end
272 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
330 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
273 pdf.alias_nb_pages
331 pdf.alias_nb_pages
274 pdf.footer_date = format_date(Date.today)
332 pdf.footer_date = format_date(Date.today)
275 pdf.AddPage
333 pdf.AddPage
276
334 pdf.SetFontStyle('B',11)
277 pdf.SetFontStyle('B',11)
335 pdf.RDMMultiCell(190,5, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
278 pdf.RDMCell(190,10,
279 "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
280 pdf.Ln
336 pdf.Ln
281
337
282 y0 = pdf.GetY
338 y0 = pdf.GetY
283
339
284 pdf.SetFontStyle('B',9)
340 pdf.SetFontStyle('B',9)
285 pdf.RDMCell(35,5, l(:field_status) + ":","LT")
341 pdf.RDMCell(35,5, l(:field_status) + ":","LT")
286 pdf.SetFontStyle('',9)
342 pdf.SetFontStyle('',9)
287 pdf.RDMCell(60,5, issue.status.to_s,"RT")
343 pdf.RDMCell(60,5, issue.status.to_s,"RT")
288 pdf.SetFontStyle('B',9)
344 pdf.SetFontStyle('B',9)
289 pdf.RDMCell(35,5, l(:field_priority) + ":","LT")
345 pdf.RDMCell(35,5, l(:field_priority) + ":","LT")
290 pdf.SetFontStyle('',9)
346 pdf.SetFontStyle('',9)
291 pdf.RDMCell(60,5, issue.priority.to_s,"RT")
347 pdf.RDMCell(60,5, issue.priority.to_s,"RT")
292 pdf.Ln
348 pdf.Ln
293
349
294 pdf.SetFontStyle('B',9)
350 pdf.SetFontStyle('B',9)
295 pdf.RDMCell(35,5, l(:field_author) + ":","L")
351 pdf.RDMCell(35,5, l(:field_author) + ":","L")
296 pdf.SetFontStyle('',9)
352 pdf.SetFontStyle('',9)
297 pdf.RDMCell(60,5, issue.author.to_s,"R")
353 pdf.RDMCell(60,5, issue.author.to_s,"R")
298 pdf.SetFontStyle('B',9)
354 pdf.SetFontStyle('B',9)
299 pdf.RDMCell(35,5, l(:field_category) + ":","L")
355 pdf.RDMCell(35,5, l(:field_category) + ":","L")
300 pdf.SetFontStyle('',9)
356 pdf.SetFontStyle('',9)
301 pdf.RDMCell(60,5, issue.category.to_s,"R")
357 pdf.RDMCell(60,5, issue.category.to_s,"R")
302 pdf.Ln
358 pdf.Ln
303
359
304 pdf.SetFontStyle('B',9)
360 pdf.SetFontStyle('B',9)
305 pdf.RDMCell(35,5, l(:field_created_on) + ":","L")
361 pdf.RDMCell(35,5, l(:field_created_on) + ":","L")
306 pdf.SetFontStyle('',9)
362 pdf.SetFontStyle('',9)
307 pdf.RDMCell(60,5, format_date(issue.created_on),"R")
363 pdf.RDMCell(60,5, format_date(issue.created_on),"R")
308 pdf.SetFontStyle('B',9)
364 pdf.SetFontStyle('B',9)
309 pdf.RDMCell(35,5, l(:field_assigned_to) + ":","L")
365 pdf.RDMCell(35,5, l(:field_assigned_to) + ":","L")
310 pdf.SetFontStyle('',9)
366 pdf.SetFontStyle('',9)
311 pdf.RDMCell(60,5, issue.assigned_to.to_s,"R")
367 pdf.RDMCell(60,5, issue.assigned_to.to_s,"R")
312 pdf.Ln
368 pdf.Ln
313
369
314 pdf.SetFontStyle('B',9)
370 pdf.SetFontStyle('B',9)
315 pdf.RDMCell(35,5, l(:field_updated_on) + ":","LB")
371 pdf.RDMCell(35,5, l(:field_updated_on) + ":","LB")
316 pdf.SetFontStyle('',9)
372 pdf.SetFontStyle('',9)
317 pdf.RDMCell(60,5, format_date(issue.updated_on),"RB")
373 pdf.RDMCell(60,5, format_date(issue.updated_on),"RB")
318 pdf.SetFontStyle('B',9)
374 pdf.SetFontStyle('B',9)
319 pdf.RDMCell(35,5, l(:field_due_date) + ":","LB")
375 pdf.RDMCell(35,5, l(:field_due_date) + ":","LB")
320 pdf.SetFontStyle('',9)
376 pdf.SetFontStyle('',9)
321 pdf.RDMCell(60,5, format_date(issue.due_date),"RB")
377 pdf.RDMCell(60,5, format_date(issue.due_date),"RB")
322 pdf.Ln
378 pdf.Ln
323
379
324 for custom_value in issue.custom_field_values
380 for custom_value in issue.custom_field_values
325 pdf.SetFontStyle('B',9)
381 pdf.SetFontStyle('B',9)
326 pdf.RDMCell(35,5, custom_value.custom_field.name + ":","L")
382 pdf.RDMCell(35,5, custom_value.custom_field.name + ":","L")
327 pdf.SetFontStyle('',9)
383 pdf.SetFontStyle('',9)
328 pdf.RDMMultiCell(155,5, (show_value custom_value),"R")
384 pdf.RDMMultiCell(155,5, (show_value custom_value),"R")
329 end
385 end
330
386
331 pdf.SetFontStyle('B',9)
387 pdf.SetFontStyle('B',9)
332 pdf.RDMCell(35,5, l(:field_subject) + ":","LTB")
388 pdf.RDMCell(35,5, l(:field_subject) + ":","LT")
333 pdf.SetFontStyle('',9)
389 pdf.SetFontStyle('',9)
334 pdf.RDMCell(155,5, issue.subject,"RTB")
390 pdf.RDMMultiCell(155,5, issue.subject,"RT")
335 pdf.Ln
391
336
337 pdf.SetFontStyle('B',9)
392 pdf.SetFontStyle('B',9)
338 pdf.RDMCell(35,5, l(:field_description) + ":")
393 pdf.RDMCell(35,5, l(:field_description) + ":","LT")
339 pdf.SetFontStyle('',9)
394 pdf.SetFontStyle('',9)
340 pdf.RDMMultiCell(155,5, issue.description.to_s,"BR")
395 pdf.RDMMultiCell(155,5, issue.description.to_s,"RT")
341
396
342 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
397 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
343 pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
398 pdf.Line(pdf.GetX, pdf.GetY, pdf.GetX + 190, pdf.GetY)
344 pdf.Ln
399 pdf.Ln
345
400
346 if issue.changesets.any? &&
401 if issue.changesets.any? &&
347 User.current.allowed_to?(:view_changesets, issue.project)
402 User.current.allowed_to?(:view_changesets, issue.project)
348 pdf.SetFontStyle('B',9)
403 pdf.SetFontStyle('B',9)
349 pdf.RDMCell(190,5, l(:label_associated_revisions), "B")
404 pdf.RDMCell(190,5, l(:label_associated_revisions), "B")
350 pdf.Ln
405 pdf.Ln
351 for changeset in issue.changesets
406 for changeset in issue.changesets
352 pdf.SetFontStyle('B',8)
407 pdf.SetFontStyle('B',8)
353 pdf.RDMCell(190,5,
408 pdf.RDMCell(190,5,
354 format_time(changeset.committed_on) + " - " + changeset.author.to_s)
409 format_time(changeset.committed_on) + " - " + changeset.author.to_s)
355 pdf.Ln
410 pdf.Ln
356 unless changeset.comments.blank?
411 unless changeset.comments.blank?
357 pdf.SetFontStyle('',8)
412 pdf.SetFontStyle('',8)
358 pdf.RDMMultiCell(190,5, changeset.comments.to_s)
413 pdf.RDMMultiCell(190,5, changeset.comments.to_s)
359 end
414 end
360 pdf.Ln
415 pdf.Ln
361 end
416 end
362 end
417 end
363
418
364 pdf.SetFontStyle('B',9)
419 pdf.SetFontStyle('B',9)
365 pdf.RDMCell(190,5, l(:label_history), "B")
420 pdf.RDMCell(190,5, l(:label_history), "B")
366 pdf.Ln
421 pdf.Ln
367 for journal in issue.journals.find(
422 for journal in issue.journals.find(
368 :all, :include => [:user, :details],
423 :all, :include => [:user, :details],
369 :order => "#{Journal.table_name}.created_on ASC")
424 :order => "#{Journal.table_name}.created_on ASC")
370 pdf.SetFontStyle('B',8)
425 pdf.SetFontStyle('B',8)
371 pdf.RDMCell(190,5,
426 pdf.RDMCell(190,5,
372 format_time(journal.created_on) + " - " + journal.user.name)
427 format_time(journal.created_on) + " - " + journal.user.name)
373 pdf.Ln
428 pdf.Ln
374 pdf.SetFontStyle('I',8)
429 pdf.SetFontStyle('I',8)
375 for detail in journal.details
430 for detail in journal.details
376 pdf.RDMCell(190,5, "- " + show_detail(detail, true))
431 pdf.RDMMultiCell(190,5, "- " + show_detail(detail, true))
377 pdf.Ln
378 end
432 end
379 if journal.notes?
433 if journal.notes?
434 pdf.Ln unless journal.details.empty?
380 pdf.SetFontStyle('',8)
435 pdf.SetFontStyle('',8)
381 pdf.RDMMultiCell(190,5, journal.notes.to_s)
436 pdf.RDMMultiCell(190,5, journal.notes.to_s)
382 end
437 end
383 pdf.Ln
438 pdf.Ln
384 end
439 end
385
440
386 if issue.attachments.any?
441 if issue.attachments.any?
387 pdf.SetFontStyle('B',9)
442 pdf.SetFontStyle('B',9)
388 pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
443 pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
389 pdf.Ln
444 pdf.Ln
390 for attachment in issue.attachments
445 for attachment in issue.attachments
391 pdf.SetFontStyle('',8)
446 pdf.SetFontStyle('',8)
392 pdf.RDMCell(80,5, attachment.filename)
447 pdf.RDMCell(80,5, attachment.filename)
393 pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
448 pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
394 pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
449 pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
395 pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
450 pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
396 pdf.Ln
451 pdf.Ln
397 end
452 end
398 end
453 end
399 pdf.Output
454 pdf.Output
400 end
455 end
401 end
456 end
402 end
457 end
403 end
458 end
General Comments 0
You need to be logged in to leave comments. Login now