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