##// END OF EJS Templates
pdf: enhanced issues list (#10464)...
Toshi MARUYAMA -
r9126:e55c8f6b67bc
parent child
Show More
@@ -234,6 +234,157 module Redmine
234 end
234 end
235 end
235 end
236
236
237 # fetch row values
238 def fetch_row_values(issue, query, level)
239 query.columns.collect do |column|
240 s = if column.is_a?(QueryCustomFieldColumn)
241 cv = issue.custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
242 show_value(cv)
243 else
244 value = issue.send(column.name)
245 if column.name == :subject
246 value = " " * level + value
247 end
248 if value.is_a?(Date)
249 format_date(value)
250 elsif value.is_a?(Time)
251 format_time(value)
252 else
253 value
254 end
255 end
256 s.to_s
257 end
258 end
259
260 # calculate columns width
261 def calc_col_width(issues, query, table_width, pdf)
262 # calculate statistics
263 # by captions
264 pdf.SetFontStyle('B',8)
265 col_padding = pdf.GetStringWidth('OO')
266 col_width_min = query.columns.map {|v| pdf.GetStringWidth(v.caption) + col_padding}
267 col_width_max = Array.new(col_width_min)
268 col_width_avg = Array.new(col_width_min)
269 word_width_max = query.columns.map {|c|
270 n = 10
271 c.caption.split.each {|w|
272 x = pdf.GetStringWidth(w) + col_padding
273 n = x if n < x
274 }
275 n
276 }
277
278 # by properties of issues
279 pdf.SetFontStyle('',8)
280 col_padding = pdf.GetStringWidth('OO')
281 k = 1
282 issue_list(issues) {|issue, level|
283 k += 1
284 values = fetch_row_values(issue, query, level)
285 values.each_with_index {|v,i|
286 n = pdf.GetStringWidth(v) + col_padding
287 col_width_max[i] = n if col_width_max[i] < n
288 col_width_min[i] = n if col_width_min[i] > n
289 col_width_avg[i] += n
290 v.split.each {|w|
291 x = pdf.GetStringWidth(w) + col_padding
292 word_width_max[i] = x if word_width_max[i] < x
293 }
294 }
295 }
296 col_width_avg.map! {|x| x / k}
297
298 # calculate columns width
299 ratio = table_width / col_width_avg.inject(0) {|s,w| s += w}
300 col_width = col_width_avg.map {|w| w * ratio}
301
302 # correct max word width if too many columns
303 ratio = table_width / word_width_max.inject(0) {|s,w| s += w}
304 word_width_max.map! {|v| v * ratio} if ratio < 1
305
306 # correct and lock width of some columns
307 done = 1
308 col_fix = []
309 col_width.each_with_index do |w,i|
310 if w > col_width_max[i]
311 col_width[i] = col_width_max[i]
312 col_fix[i] = 1
313 done = 0
314 elsif w < word_width_max[i]
315 col_width[i] = word_width_max[i]
316 col_fix[i] = 1
317 done = 0
318 else
319 col_fix[i] = 0
320 end
321 end
322
323 # iterate while need to correct and lock coluns width
324 while done == 0
325 # calculate free & locked columns width
326 done = 1
327 fix_col_width = 0
328 free_col_width = 0
329 col_width.each_with_index do |w,i|
330 if col_fix[i] == 1
331 fix_col_width += w
332 else
333 free_col_width += w
334 end
335 end
336
337 # calculate column normalizing ratio
338 if free_col_width == 0
339 ratio = table_width / col_width.inject(0) {|s,w| s += w}
340 else
341 ratio = (table_width - fix_col_width) / free_col_width
342 end
343
344 # correct columns width
345 col_width.each_with_index do |w,i|
346 if col_fix[i] == 0
347 col_width[i] = w * ratio
348
349 # check if column width less then max word width
350 if col_width[i] < word_width_max[i]
351 col_width[i] = word_width_max[i]
352 col_fix[i] = 1
353 done = 0
354 elsif col_width[i] > col_width_max[i]
355 col_width[i] = col_width_max[i]
356 col_fix[i] = 1
357 done = 0
358 end
359 end
360 end
361 end
362 col_width
363 end
364
365 def render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
366 # headers
367 pdf.SetFontStyle('B',8)
368 pdf.SetFillColor(230, 230, 230)
369
370 # render it background to find the max height used
371 base_x = pdf.GetX
372 base_y = pdf.GetY
373 max_height = issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
374 pdf.Rect(base_x, base_y, table_width + col_id_width, max_height, 'FD');
375 pdf.SetXY(base_x, base_y);
376
377 # write the cells on page
378 pdf.RDMCell(col_id_width, row_height, "#", "T", 0, 'C', 1)
379 issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
380 issues_to_pdf_draw_borders(pdf, base_x, base_y, base_y + max_height, col_id_width, col_width)
381 pdf.SetY(base_y + max_height);
382
383 # rows
384 pdf.SetFontStyle('',8)
385 pdf.SetFillColor(255, 255, 255)
386 end
387
237 # Returns a PDF string of a list of issues
388 # Returns a PDF string of a list of issues
238 def issues_to_pdf(issues, project, query)
389 def issues_to_pdf(issues, project, query)
239 pdf = ITCPDF.new(current_language)
390 pdf = ITCPDF.new(current_language)
@@ -251,77 +402,36 module Redmine
251 right_margin = 10
402 right_margin = 10
252 bottom_margin = 20
403 bottom_margin = 20
253 col_id_width = 10
404 col_id_width = 10
254 row_height = 5
405 row_height = 4
255
406
256 # column widths
407 # column widths
257 table_width = page_width - right_margin - 10 # fixed left margin
408 table_width = page_width - right_margin - 10 # fixed left margin
258 col_width = []
409 col_width = []
259 unless query.columns.empty?
410 unless query.columns.empty?
260 col_width = query.columns.collect do |c|
411 col_width = calc_col_width(issues, query, table_width - col_id_width, pdf)
261 (c.name == :subject || (c.is_a?(QueryCustomFieldColumn) &&
412 table_width = col_width.inject(0) {|s,v| s += v}
262 ['string', 'text'].include?(c.custom_field.field_format))) ? 4.0 : 1.0
263 end
264 ratio = (table_width - col_id_width) / col_width.inject(0) {|s,w| s += w}
265 col_width = col_width.collect {|w| w * ratio}
266 end
413 end
267
414
268 # title
415 # title
269 pdf.SetFontStyle('B',11)
416 pdf.SetFontStyle('B',11)
270 pdf.RDMCell(190,10, title)
417 pdf.RDMCell(190,10, title)
271 pdf.Ln
418 pdf.Ln
272
419 render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
273 # headers
274 pdf.SetFontStyle('B',8)
275 pdf.SetFillColor(230, 230, 230)
276
277 # render it background to find the max height used
278 base_x = pdf.GetX
279 base_y = pdf.GetY
280 max_height = issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
281 pdf.Rect(base_x, base_y, table_width, max_height, 'FD');
282 pdf.SetXY(base_x, base_y);
283
284 # write the cells on page
285 pdf.RDMCell(col_id_width, row_height, "#", "T", 0, 'C', 1)
286 issues_to_pdf_write_cells(pdf, query.columns, col_width, row_height, true)
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);
289
290 # rows
291 pdf.SetFontStyle('',8)
292 pdf.SetFillColor(255, 255, 255)
293 previous_group = false
420 previous_group = false
294 issue_list(issues) do |issue, level|
421 issue_list(issues) do |issue, level|
295 if query.grouped? &&
422 if query.grouped? &&
296 (group = query.group_by_column.value(issue)) != previous_group
423 (group = query.group_by_column.value(issue)) != previous_group
297 pdf.SetFontStyle('B',9)
424 pdf.SetFontStyle('B',10)
298 group_label = group.blank? ? 'None' : group.to_s
425 group_label = group.blank? ? 'None' : group.to_s
299 group_label << " (#{query.issue_count_by_group[group]})"
426 group_label << " (#{query.issue_count_by_group[group]})"
300 pdf.Bookmark group_label, 0, -1
427 pdf.Bookmark group_label, 0, -1
301 pdf.RDMCell(277, row_height, group_label, 1, 1, 'L')
428 pdf.RDMCell(table_width + col_id_width, row_height * 2, group_label, 1, 1, 'L')
302 pdf.SetFontStyle('',8)
429 pdf.SetFontStyle('',8)
303 previous_group = group
430 previous_group = group
304 end
431 end
305 # fetch all the row values
432
306 col_values = query.columns.collect do |column|
433 # fetch row values
307 s = if column.is_a?(QueryCustomFieldColumn)
434 col_values = fetch_row_values(issue, query, level)
308 cv = issue.custom_field_values.detect {|v| v.custom_field_id == column.custom_field.id}
309 show_value(cv)
310 else
311 value = issue.send(column.name)
312 if column.name == :subject
313 value = " " * level + value
314 end
315 if value.is_a?(Date)
316 format_date(value)
317 elsif value.is_a?(Time)
318 format_time(value)
319 else
320 value
321 end
322 end
323 s.to_s
324 end
325
435
326 # render it off-page to find the max height used
436 # render it off-page to find the max height used
327 base_x = pdf.GetX
437 base_x = pdf.GetX
@@ -334,6 +444,7 module Redmine
334 space_left = page_height - base_y - bottom_margin
444 space_left = page_height - base_y - bottom_margin
335 if max_height > space_left
445 if max_height > space_left
336 pdf.AddPage("L")
446 pdf.AddPage("L")
447 render_table_header(pdf, query, col_width, row_height, col_id_width, table_width)
337 base_x = pdf.GetX
448 base_x = pdf.GetX
338 base_y = pdf.GetY
449 base_y = pdf.GetY
339 end
450 end
General Comments 0
You need to be logged in to leave comments. Login now