##// END OF EJS Templates
remove trailing white-spaces from lib/redmine/export/pdf.rb...
Toshi MARUYAMA -
r9125:b17b6730395d
parent child
Show More
@@ -1,680 +1,680
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
4 # Copyright (C) 2006-2012 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 'fpdf/chinese'
22 22 require 'fpdf/japanese'
23 23 require 'fpdf/korean'
24 24 require 'core/rmagick'
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 include IssuesHelper
32 32
33 33 class ITCPDF < TCPDF
34 34 include Redmine::I18n
35 35 attr_accessor :footer_date
36 36
37 37 def initialize(lang)
38 38 @@k_path_cache = Rails.root.join('tmp', 'pdf')
39 39 FileUtils.mkdir_p @@k_path_cache unless File::exist?(@@k_path_cache)
40 40 set_language_if_valid lang
41 41 pdf_encoding = l(:general_pdf_encoding).upcase
42 42 super('P', 'mm', 'A4', (pdf_encoding == 'UTF-8'), pdf_encoding)
43 43 case current_language.to_s.downcase
44 44 when 'vi'
45 45 @font_for_content = 'DejaVuSans'
46 46 @font_for_footer = 'DejaVuSans'
47 47 else
48 48 case pdf_encoding
49 49 when 'UTF-8'
50 50 @font_for_content = 'FreeSans'
51 51 @font_for_footer = 'FreeSans'
52 52 when 'CP949'
53 53 extend(PDF_Korean)
54 54 AddUHCFont()
55 55 @font_for_content = 'UHC'
56 56 @font_for_footer = 'UHC'
57 57 when 'CP932', 'SJIS', 'SHIFT_JIS'
58 58 extend(PDF_Japanese)
59 59 AddSJISFont()
60 60 @font_for_content = 'SJIS'
61 61 @font_for_footer = 'SJIS'
62 62 when 'GB18030'
63 63 extend(PDF_Chinese)
64 64 AddGBFont()
65 65 @font_for_content = 'GB'
66 66 @font_for_footer = 'GB'
67 67 when 'BIG5'
68 68 extend(PDF_Chinese)
69 69 AddBig5Font()
70 70 @font_for_content = 'Big5'
71 71 @font_for_footer = 'Big5'
72 72 else
73 73 @font_for_content = 'Arial'
74 74 @font_for_footer = 'Helvetica'
75 75 end
76 76 end
77 77 SetCreator(Redmine::Info.app_name)
78 78 SetFont(@font_for_content)
79 79 @outlines = []
80 80 @outlineRoot = nil
81 81 end
82 82
83 83 def SetFontStyle(style, size)
84 84 SetFont(@font_for_content, style, size)
85 85 end
86 86
87 87 def SetTitle(txt)
88 88 txt = begin
89 89 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
90 90 hextxt = "<FEFF" # FEFF is BOM
91 91 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
92 92 hextxt << ">"
93 93 rescue
94 94 txt
95 95 end || ''
96 96 super(txt)
97 97 end
98 98
99 99 def textstring(s)
100 100 # Format a text string
101 101 if s =~ /^</ # This means the string is hex-dumped.
102 102 return s
103 103 else
104 104 return '('+escape(s)+')'
105 105 end
106 106 end
107 107
108 108 def fix_text_encoding(txt)
109 109 RDMPdfEncoding::rdm_from_utf8(txt, l(:general_pdf_encoding))
110 110 end
111 111
112 112 def RDMCell(w ,h=0, txt='', border=0, ln=0, align='', fill=0, link='')
113 113 Cell(w, h, fix_text_encoding(txt), border, ln, align, fill, link)
114 114 end
115 115
116 116 def RDMMultiCell(w, h=0, txt='', border=0, align='', fill=0, ln=1)
117 117 MultiCell(w, h, fix_text_encoding(txt), border, align, fill, ln)
118 118 end
119 119
120 120 def RDMwriteHTMLCell(w, h, x, y, txt='', attachments=[], border=0, ln=1, fill=0)
121 121 @attachments = attachments
122 122 writeHTMLCell(w, h, x, y,
123 123 fix_text_encoding(
124 124 Redmine::WikiFormatting.to_html(Setting.text_formatting, txt)),
125 125 border, ln, fill)
126 126 end
127 127
128 128 def getImageFilename(attrname)
129 129 # attrname: general_pdf_encoding string file/uri name
130 130 atta = RDMPdfEncoding.attach(@attachments, attrname, l(:general_pdf_encoding))
131 131 if atta
132 132 return atta.diskfile
133 133 else
134 134 return nil
135 135 end
136 136 end
137 137
138 138 def Footer
139 139 SetFont(@font_for_footer, 'I', 8)
140 140 SetY(-15)
141 141 SetX(15)
142 142 RDMCell(0, 5, @footer_date, 0, 0, 'L')
143 143 SetY(-15)
144 144 SetX(-30)
145 145 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
146 146 end
147 147
148 148 def Bookmark(txt, level=0, y=0)
149 149 if (y == -1)
150 150 y = GetY()
151 151 end
152 152 @outlines << {:t => txt, :l => level, :p => PageNo(), :y => (@h - y)*@k}
153 153 end
154 154
155 155 def bookmark_title(txt)
156 156 txt = begin
157 157 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
158 158 hextxt = "<FEFF" # FEFF is BOM
159 159 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
160 160 hextxt << ">"
161 161 rescue
162 162 txt
163 163 end || ''
164 164 end
165 165
166 166 def putbookmarks
167 167 nb=@outlines.size
168 168 return if (nb==0)
169 169 lru=[]
170 170 level=0
171 171 @outlines.each_with_index do |o, i|
172 172 if(o[:l]>0)
173 173 parent=lru[o[:l]-1]
174 174 #Set parent and last pointers
175 175 @outlines[i][:parent]=parent
176 176 @outlines[parent][:last]=i
177 177 if (o[:l]>level)
178 178 #Level increasing: set first pointer
179 179 @outlines[parent][:first]=i
180 180 end
181 181 else
182 182 @outlines[i][:parent]=nb
183 183 end
184 184 if (o[:l]<=level && i>0)
185 185 #Set prev and next pointers
186 186 prev=lru[o[:l]]
187 187 @outlines[prev][:next]=i
188 188 @outlines[i][:prev]=prev
189 189 end
190 190 lru[o[:l]]=i
191 191 level=o[:l]
192 192 end
193 193 #Outline items
194 194 n=self.n+1
195 195 @outlines.each_with_index do |o, i|
196 196 newobj()
197 197 out('<</Title '+bookmark_title(o[:t]))
198 198 out("/Parent #{n+o[:parent]} 0 R")
199 199 if (o[:prev])
200 200 out("/Prev #{n+o[:prev]} 0 R")
201 201 end
202 202 if (o[:next])
203 203 out("/Next #{n+o[:next]} 0 R")
204 204 end
205 205 if (o[:first])
206 206 out("/First #{n+o[:first]} 0 R")
207 207 end
208 208 if (o[:last])
209 209 out("/Last #{n+o[:last]} 0 R")
210 210 end
211 211 out("/Dest [%d 0 R /XYZ 0 %.2f null]" % [1+2*o[:p], o[:y]])
212 212 out('/Count 0>>')
213 213 out('endobj')
214 214 end
215 215 #Outline root
216 216 newobj()
217 217 @outlineRoot=self.n
218 218 out("<</Type /Outlines /First #{n} 0 R");
219 219 out("/Last #{n+lru[0]} 0 R>>");
220 220 out('endobj');
221 221 end
222 222
223 223 def putresources()
224 224 super
225 225 putbookmarks()
226 226 end
227 227
228 228 def putcatalog()
229 229 super
230 230 if(@outlines.size > 0)
231 231 out("/Outlines #{@outlineRoot} 0 R");
232 232 out('/PageMode /UseOutlines');
233 233 end
234 234 end
235 235 end
236 236
237 237 # Returns a PDF string of a list of issues
238 238 def issues_to_pdf(issues, project, query)
239 239 pdf = ITCPDF.new(current_language)
240 240 title = query.new_record? ? l(:label_issue_plural) : query.name
241 241 title = "#{project} - #{title}" if project
242 242 pdf.SetTitle(title)
243 243 pdf.alias_nb_pages
244 244 pdf.footer_date = format_date(Date.today)
245 245 pdf.SetAutoPageBreak(false)
246 246 pdf.AddPage("L")
247 247
248 248 # Landscape A4 = 210 x 297 mm
249 249 page_height = 210
250 250 page_width = 297
251 251 right_margin = 10
252 252 bottom_margin = 20
253 253 col_id_width = 10
254 254 row_height = 5
255 255
256 256 # column widths
257 257 table_width = page_width - right_margin - 10 # fixed left margin
258 258 col_width = []
259 259 unless query.columns.empty?
260 260 col_width = query.columns.collect do |c|
261 261 (c.name == :subject || (c.is_a?(QueryCustomFieldColumn) &&
262 262 ['string', 'text'].include?(c.custom_field.field_format))) ? 4.0 : 1.0
263 263 end
264 264 ratio = (table_width - col_id_width) / col_width.inject(0) {|s,w| s += w}
265 265 col_width = col_width.collect {|w| w * ratio}
266 266 end
267 267
268 268 # title
269 269 pdf.SetFontStyle('B',11)
270 270 pdf.RDMCell(190,10, title)
271 271 pdf.Ln
272 272
273 273 # headers
274 274 pdf.SetFontStyle('B',8)
275 275 pdf.SetFillColor(230, 230, 230)
276 276
277 277 # render it background to find the max height used
278 278 base_x = pdf.GetX
279 279 base_y = pdf.GetY
280 280 max_height = issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
281 281 pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
282 282 pdf.SetXY(base_x, base_y);
283 283
284 284 # write the cells on page
285 285 pdf.RDMCell(col_id_width, row_height, "#", "T", 0, 'C', 1)
286 286 issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
287 287 issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
288 288 pdf.SetY(base_y + max_height);
289 289
290 290 # rows
291 291 pdf.SetFontStyle('',8)
292 292 pdf.SetFillColor(255, 255, 255)
293 293 previous_group = false
294 294 issue_list(issues) do |issue, level|
295 295 if query.grouped? &&
296 296 (group = query.group_by_column.value(issue)) != previous_group
297 297 pdf.SetFontStyle('B',9)
298 298 group_label = group.blank? ? 'None' : group.to_s
299 299 group_label << " (#{query.issue_count_by_group[group]})"
300 300 pdf.Bookmark group_label, 0, -1
301 301 pdf.RDMCell(277, row_height, group_label, 1, 1, 'L')
302 302 pdf.SetFontStyle('',8)
303 303 previous_group = group
304 304 end
305 305 # fetch all the row values
306 306 col_values = query.columns.collect do |column|
307 307 s = if column.is_a?(QueryCustomFieldColumn)
308 308 cv = issue.custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
309 309 show_value(cv)
310 310 else
311 311 value = issue.send(column.name)
312 312 if column.name == :subject
313 313 value = " " * level + value
314 314 end
315 315 if value.is_a?(Date)
316 316 format_date(value)
317 317 elsif value.is_a?(Time)
318 318 format_time(value)
319 319 else
320 320 value
321 321 end
322 322 end
323 323 s.to_s
324 324 end
325 325
326 326 # render it off-page to find the max height used
327 327 base_x = pdf.GetX
328 328 base_y = pdf.GetY
329 329 pdf.SetY(2 * page_height)
330 330 max_height = issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
331 331 pdf.SetXY(base_x, base_y)
332 332
333 333 # make new page if it doesn't fit on the current one
334 334 space_left = page_height - base_y - bottom_margin
335 335 if max_height > space_left
336 336 pdf.AddPage("L")
337 337 base_x = pdf.GetX
338 338 base_y = pdf.GetY
339 339 end
340 340
341 341 # write the cells on page
342 342 pdf.RDMCell(col_id_width, row_height, issue.id.to_s, "T", 0, 'C', 1)
343 343 issues_to_pdf_write_cells(pdf, col_values, col_width, row_height)
344 344 issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
345 345 pdf.SetY(base_y + max_height);
346 346 end
347 347
348 348 if issues.size == Setting.issues_export_limit.to_i
349 349 pdf.SetFontStyle('B',10)
350 350 pdf.RDMCell(0, row_height, '...')
351 351 end
352 352 pdf.Output
353 353 end
354 354
355 355 # Renders MultiCells and returns the maximum height used
356 356 def issues_to_pdf_write_cells(pdf, col_values, col_widths,
357 357 row_height, head=false)
358 358 base_y = pdf.GetY
359 359 max_height = row_height
360 360 col_values.each_with_index do |column, i|
361 361 col_x = pdf.GetX
362 362 if head == true
363 363 pdf.RDMMultiCell(col_widths[i], row_height, column.caption, "T", 'L', 1)
364 364 else
365 365 pdf.RDMMultiCell(col_widths[i], row_height, column, "T", 'L', 1)
366 366 end
367 367 max_height = (pdf.GetY - base_y) if (pdf.GetY - base_y) > max_height
368 368 pdf.SetXY(col_x + col_widths[i], base_y);
369 369 end
370 370 return max_height
371 371 end
372 372
373 373 # Draw lines to close the row (MultiCell border drawing in not uniform)
374 374 def issues_to_pdf_draw_borders(pdf, top_x, top_y, lower_y,
375 375 id_width, col_widths)
376 376 col_x = top_x + id_width
377 377 pdf.Line(col_x, top_y, col_x, lower_y) # id right border
378 378 col_widths.each do |width|
379 379 col_x += width
380 380 pdf.Line(col_x, top_y, col_x, lower_y) # columns right border
381 381 end
382 382 pdf.Line(top_x, top_y, top_x, lower_y) # left border
383 383 pdf.Line(top_x, lower_y, col_x, lower_y) # bottom border
384 384 end
385 385
386 386 # Returns a PDF string of a single issue
387 387 def issue_to_pdf(issue)
388 388 pdf = ITCPDF.new(current_language)
389 389 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
390 390 pdf.alias_nb_pages
391 391 pdf.footer_date = format_date(Date.today)
392 392 pdf.AddPage
393 393 pdf.SetFontStyle('B',11)
394 394 buf = "#{issue.project} - #{issue.tracker} # #{issue.id}"
395 395 pdf.RDMMultiCell(190, 5, buf)
396 396 pdf.Ln
397 397 pdf.SetFontStyle('',8)
398 398 base_x = pdf.GetX
399 399 i = 1
400 400 issue.ancestors.each do |ancestor|
401 401 pdf.SetX(base_x + i)
402 402 buf = "#{ancestor.tracker} # #{ancestor.id} (#{ancestor.status.to_s}): #{ancestor.subject}"
403 403 pdf.RDMMultiCell(190 - i, 5, buf)
404 404 i += 1 if i < 35
405 405 end
406 406 pdf.Ln
407 407
408 408 pdf.SetFontStyle('B',9)
409 409 pdf.RDMCell(35,5, l(:field_status) + ":","LT")
410 410 pdf.SetFontStyle('',9)
411 411 pdf.RDMCell(60,5, issue.status.to_s,"RT")
412 412 pdf.SetFontStyle('B',9)
413 413 pdf.RDMCell(35,5, l(:field_priority) + ":","LT")
414 414 pdf.SetFontStyle('',9)
415 415 pdf.RDMCell(60,5, issue.priority.to_s,"RT")
416 416 pdf.Ln
417 417
418 418 pdf.SetFontStyle('B',9)
419 419 pdf.RDMCell(35,5, l(:field_author) + ":","L")
420 420 pdf.SetFontStyle('',9)
421 421 pdf.RDMCell(60,5, issue.author.to_s,"R")
422 422 pdf.SetFontStyle('B',9)
423 423 pdf.RDMCell(35,5, l(:field_category) + ":","L")
424 424 pdf.SetFontStyle('',9)
425 425 pdf.RDMCell(60,5, issue.category.to_s,"R")
426 426 pdf.Ln
427 427
428 428 pdf.SetFontStyle('B',9)
429 429 pdf.RDMCell(35,5, l(:field_created_on) + ":","L")
430 430 pdf.SetFontStyle('',9)
431 431 pdf.RDMCell(60,5, format_date(issue.created_on),"R")
432 432 pdf.SetFontStyle('B',9)
433 433 pdf.RDMCell(35,5, l(:field_assigned_to) + ":","L")
434 434 pdf.SetFontStyle('',9)
435 435 pdf.RDMCell(60,5, issue.assigned_to.to_s,"R")
436 436 pdf.Ln
437 437
438 438 pdf.SetFontStyle('B',9)
439 439 pdf.RDMCell(35,5, l(:field_updated_on) + ":","LB")
440 440 pdf.SetFontStyle('',9)
441 441 pdf.RDMCell(60,5, format_date(issue.updated_on),"RB")
442 442 pdf.SetFontStyle('B',9)
443 443 pdf.RDMCell(35,5, l(:field_due_date) + ":","LB")
444 444 pdf.SetFontStyle('',9)
445 445 pdf.RDMCell(60,5, format_date(issue.due_date),"RB")
446 446 pdf.Ln
447 447
448 448 for custom_value in issue.custom_field_values
449 449 pdf.SetFontStyle('B',9)
450 450 pdf.RDMCell(35,5, custom_value.custom_field.name + ":","L")
451 451 pdf.SetFontStyle('',9)
452 452 pdf.RDMMultiCell(155,5, (show_value custom_value),"R")
453 453 end
454 454
455 455 y0 = pdf.GetY
456 456
457 457 pdf.SetFontStyle('B',9)
458 458 pdf.RDMCell(35,5, l(:field_subject) + ":","LT")
459 459 pdf.SetFontStyle('',9)
460 460 pdf.RDMMultiCell(155,5, issue.subject,"RT")
461 461 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
462 462
463 463 pdf.SetFontStyle('B',9)
464 464 pdf.RDMCell(35+155, 5, l(:field_description), "LRT", 1)
465 465 pdf.SetFontStyle('',9)
466 466
467 467 # Set resize image scale
468 468 pdf.SetImageScale(1.6)
469 469 pdf.RDMwriteHTMLCell(35+155, 5, 0, 0,
470 470 issue.description.to_s, issue.attachments, "LRB")
471 471
472 472 unless issue.leaf?
473 473 # for CJK
474 474 truncate_length = ( l(:general_pdf_encoding).upcase == "UTF-8" ? 90 : 65 )
475 475
476 476 pdf.SetFontStyle('B',9)
477 477 pdf.RDMCell(35+155,5, l(:label_subtask_plural) + ":", "LTR")
478 478 pdf.Ln
479 479 issue_list(issue.descendants.sort_by(&:lft)) do |child, level|
480 480 buf = truncate("#{child.tracker} # #{child.id}: #{child.subject}",
481 481 :length => truncate_length)
482 482 level = 10 if level >= 10
483 483 pdf.SetFontStyle('',8)
484 484 pdf.RDMCell(35+135,5, (level >=1 ? " " * level : "") + buf, "L")
485 485 pdf.SetFontStyle('B',8)
486 486 pdf.RDMCell(20,5, child.status.to_s, "R")
487 487 pdf.Ln
488 488 end
489 489 end
490 490
491 491 relations = issue.relations.select { |r| r.other_issue(issue).visible? }
492 492 unless relations.empty?
493 493 # for CJK
494 494 truncate_length = ( l(:general_pdf_encoding).upcase == "UTF-8" ? 80 : 60 )
495 495
496 496 pdf.SetFontStyle('B',9)
497 497 pdf.RDMCell(35+155,5, l(:label_related_issues) + ":", "LTR")
498 498 pdf.Ln
499 499 relations.each do |relation|
500 500 buf = ""
501 501 buf += "#{l(relation.label_for(issue))} "
502 502 if relation.delay && relation.delay != 0
503 503 buf += "(#{l('datetime.distance_in_words.x_days', :count => relation.delay)}) "
504 504 end
505 505 if Setting.cross_project_issue_relations?
506 506 buf += "#{relation.other_issue(issue).project} - "
507 507 end
508 508 buf += "#{relation.other_issue(issue).tracker}" +
509 509 " # #{relation.other_issue(issue).id}: #{relation.other_issue(issue).subject}"
510 510 buf = truncate(buf, :length => truncate_length)
511 511 pdf.SetFontStyle('', 8)
512 512 pdf.RDMCell(35+155-60, 5, buf, "L")
513 513 pdf.SetFontStyle('B',8)
514 514 pdf.RDMCell(20,5, relation.other_issue(issue).status.to_s, "")
515 515 pdf.RDMCell(20,5, format_date(relation.other_issue(issue).start_date), "")
516 516 pdf.RDMCell(20,5, format_date(relation.other_issue(issue).due_date), "R")
517 517 pdf.Ln
518 518 end
519 519 end
520 520 pdf.RDMCell(190,5, "", "T")
521 521 pdf.Ln
522 522
523 523 if issue.changesets.any? &&
524 524 User.current.allowed_to?(:view_changesets, issue.project)
525 525 pdf.SetFontStyle('B',9)
526 526 pdf.RDMCell(190,5, l(:label_associated_revisions), "B")
527 527 pdf.Ln
528 528 for changeset in issue.changesets
529 529 pdf.SetFontStyle('B',8)
530 530 csstr = "#{l(:label_revision)} #{changeset.format_identifier} - "
531 531 csstr += format_time(changeset.committed_on) + " - " + changeset.author.to_s
532 532 pdf.RDMCell(190, 5, csstr)
533 533 pdf.Ln
534 534 unless changeset.comments.blank?
535 535 pdf.SetFontStyle('',8)
536 536 pdf.RDMwriteHTMLCell(190,5,0,0,
537 537 changeset.comments.to_s, issue.attachments, "")
538 538 end
539 539 pdf.Ln
540 540 end
541 541 end
542 542
543 543 pdf.SetFontStyle('B',9)
544 544 pdf.RDMCell(190,5, l(:label_history), "B")
545 545 pdf.Ln
546 546 indice = 0
547 547 for journal in issue.journals.find(
548 548 :all, :include => [:user, :details],
549 549 :order => "#{Journal.table_name}.created_on ASC")
550 550 indice = indice + 1
551 551 pdf.SetFontStyle('B',8)
552 552 pdf.RDMCell(190,5,
553 553 "#" + indice.to_s +
554 554 " - " + format_time(journal.created_on) +
555 555 " - " + journal.user.name)
556 556 pdf.Ln
557 557 pdf.SetFontStyle('I',8)
558 558 details_to_strings(journal.details, true).each do |string|
559 559 pdf.RDMMultiCell(190,5, "- " + string)
560 560 end
561 561 if journal.notes?
562 562 pdf.Ln unless journal.details.empty?
563 563 pdf.SetFontStyle('',8)
564 564 pdf.RDMwriteHTMLCell(190,5,0,0,
565 565 journal.notes.to_s, issue.attachments, "")
566 566 end
567 567 pdf.Ln
568 568 end
569 569
570 570 if issue.attachments.any?
571 571 pdf.SetFontStyle('B',9)
572 572 pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
573 573 pdf.Ln
574 574 for attachment in issue.attachments
575 575 pdf.SetFontStyle('',8)
576 576 pdf.RDMCell(80,5, attachment.filename)
577 577 pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
578 578 pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
579 579 pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
580 580 pdf.Ln
581 581 end
582 582 end
583 583 pdf.Output
584 584 end
585 585
586 586 # Returns a PDF string of a set of wiki pages
587 587 def wiki_pages_to_pdf(pages, project)
588 588 pdf = ITCPDF.new(current_language)
589 589 pdf.SetTitle(project.name)
590 590 pdf.alias_nb_pages
591 591 pdf.footer_date = format_date(Date.today)
592 592 pdf.AddPage
593 593 pdf.SetFontStyle('B',11)
594 594 pdf.RDMMultiCell(190,5, project.name)
595 595 pdf.Ln
596 596 # Set resize image scale
597 597 pdf.SetImageScale(1.6)
598 598 pdf.SetFontStyle('',9)
599 599 write_page_hierarchy(pdf, pages.group_by(&:parent_id))
600 600 pdf.Output
601 601 end
602 602
603 603 # Returns a PDF string of a single wiki page
604 604 def wiki_page_to_pdf(page, project)
605 605 pdf = ITCPDF.new(current_language)
606 606 pdf.SetTitle("#{project} - #{page.title}")
607 607 pdf.alias_nb_pages
608 608 pdf.footer_date = format_date(Date.today)
609 609 pdf.AddPage
610 610 pdf.SetFontStyle('B',11)
611 611 pdf.RDMMultiCell(190,5,
612 612 "#{project} - #{page.title} - # #{page.content.version}")
613 613 pdf.Ln
614 614 # Set resize image scale
615 615 pdf.SetImageScale(1.6)
616 616 pdf.SetFontStyle('',9)
617 617 write_wiki_page(pdf, page)
618 618 pdf.Output
619 619 end
620 620
621 621 def write_page_hierarchy(pdf, pages, node=nil, level=0)
622 622 if pages[node]
623 623 pages[node].each do |page|
624 624 if @new_page
625 625 pdf.AddPage
626 626 else
627 627 @new_page = true
628 628 end
629 629 pdf.Bookmark page.title, level
630 630 write_wiki_page(pdf, page)
631 631 write_page_hierarchy(pdf, pages, page.id, level + 1) if pages[page.id]
632 632 end
633 633 end
634 634 end
635 635
636 636 def write_wiki_page(pdf, page)
637 637 pdf.RDMwriteHTMLCell(190,5,0,0,
638 638 page.content.text.to_s, page.attachments, 0)
639 639 if page.attachments.any?
640 640 pdf.Ln
641 641 pdf.SetFontStyle('B',9)
642 642 pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
643 643 pdf.Ln
644 644 for attachment in page.attachments
645 645 pdf.SetFontStyle('',8)
646 646 pdf.RDMCell(80,5, attachment.filename)
647 647 pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
648 648 pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
649 649 pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
650 650 pdf.Ln
651 651 end
652 652 end
653 653 end
654 654
655 655 class RDMPdfEncoding
656 656 def self.rdm_from_utf8(txt, encoding)
657 657 txt ||= ''
658 658 txt = Redmine::CodesetUtil.from_utf8(txt, encoding)
659 659 if txt.respond_to?(:force_encoding)
660 660 txt.force_encoding('ASCII-8BIT')
661 661 end
662 662 txt
663 663 end
664 664
665 665 def self.attach(attachments, filename, encoding)
666 666 filename_utf8 = Redmine::CodesetUtil.to_utf8(filename, encoding)
667 667 atta = nil
668 668 if filename_utf8 =~ /^[^\/"]+\.(gif|jpg|jpe|jpeg|png)$/i
669 669 atta = Attachment.latest_attach(attachments, filename_utf8)
670 670 end
671 671 if atta && atta.readable? && atta.visible?
672 672 return atta
673 673 else
674 674 return nil
675 675 end
676 676 end
677 677 end
678 678 end
679 679 end
680 680 end
General Comments 0
You need to be logged in to leave comments. Login now