PDF: affiche liste polices dispo, meilleurs messages d'erreur

This commit is contained in:
Emmanuel Viennet 2022-03-24 09:59:44 +01:00
parent 1b887858bb
commit 41778d5918
7 changed files with 104 additions and 95 deletions

View File

@ -6,15 +6,13 @@
"""Génération bulletin BUT au format PDF standard
"""
from reportlab.lib.colors import blue
from reportlab.lib.units import cm, mm
from reportlab.platypus import Paragraph, Spacer
from app.scodoc.sco_pdf import blue, cm, mm
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
from app.scodoc import gen_tables
from app.scodoc.sco_codes_parcours import UE_SPORT
from app.scodoc.sco_utils import fmt_note
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):

View File

@ -34,17 +34,19 @@
CE FORMAT N'EVOLUERA PLUS ET EST CONSIDERE COMME OBSOLETE.
"""
from reportlab.lib.colors import Color, blue
from reportlab.lib.units import cm, mm
from reportlab.platypus import Paragraph, Spacer, Table
import app.scodoc.sco_utils as scu
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_formsemestre
from app.scodoc import sco_pdf
from app.scodoc.sco_pdf import Color, Paragraph, Spacer, Table
from app.scodoc.sco_pdf import blue, cm, mm
from app.scodoc.sco_pdf import SU
from app.scodoc import sco_preferences
from app.scodoc import sco_bulletins_generator
from app.scodoc import sco_bulletins_pdf
from app.scodoc import sco_formsemestre
from app.scodoc.sco_permissions import Permission
from app.scodoc import sco_pdf
from app.scodoc.sco_pdf import SU
from app.scodoc import sco_preferences
import app.scodoc.sco_utils as scu
# Important: Le nom de la classe ne doit pas changer (bien le choisir), car il sera stocké en base de données (dans les préférences)
class BulletinGeneratorLegacy(sco_bulletins_generator.BulletinGenerator):

View File

@ -32,16 +32,12 @@ On redéfini la table centrale du bulletin de note et hérite de tout le reste d
E. Viennet, juillet 2011
"""
from reportlab.lib.colors import Color
from reportlab.lib.units import mm
import app.scodoc.sco_utils as scu
from app.scodoc.sco_pdf import blue, cm, mm
from app.scodoc.sco_pdf import Color, Paragraph, Spacer, Table
from app.scodoc import sco_preferences
from app.scodoc import sco_bulletins_generator
from app.scodoc import sco_bulletins_standard
from app.scodoc import gen_tables
from app.scodoc import sco_preferences
import app.scodoc.sco_utils as scu
class BulletinGeneratorUCAC(sco_bulletins_standard.BulletinGeneratorStandard):

View File

@ -44,22 +44,17 @@ import traceback
import unicodedata
import reportlab
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph, Frame
from reportlab.platypus.flowables import Flowable
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize # pylint: disable=no-name-in-module
from reportlab.lib.units import inch, cm, mm
from reportlab.lib.colors import pink, black, red, blue, green, magenta, red
from reportlab.lib.colors import Color
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.lib import styles
from reportlab.lib.pagesizes import letter, A4, landscape
from flask import g
import app.scodoc.sco_utils as scu
from app.scodoc.sco_utils import CONFIG
from app import log
from app.scodoc.sco_exceptions import ScoGenError, ScoValueError
@ -89,6 +84,12 @@ def SU(s):
return s
def get_available_font_names() -> list[str]:
"""List installed font names"""
can = canvas.Canvas(io.StringIO())
return can.getAvailableFonts()
def _splitPara(txt):
"split a string, returns a list of <para > ... </para>"
L = []
@ -147,12 +148,26 @@ def makeParas(txt, style, suppress_empty=False):
except Exception as e:
log(traceback.format_exc())
log("Invalid pdf para format: %s" % txt)
try:
result = [
Paragraph(
SU('<font color="red"><i>Erreur: format invalide</i></font>'),
style,
)
]
except ValueError as e: # probleme font ? essaye sans style
# recupere font en cause ?
m = re.match(r".*family/bold/italic for (.*)", e.args[0], re.DOTALL)
if m:
message = f"police non disponible: {m[1]}"
else:
message = "format invalide"
return [
Paragraph(
SU(f'<font color="red"><b>Erreur: {message}</b></font>'),
reportlab.lib.styles.ParagraphStyle({}),
)
]
return result
@ -166,7 +181,6 @@ def bold_paras(L, tag="b", close=None):
if hasattr(L, "keys"):
# L is a dict
for k in L:
x = L[k]
if k[0] != "_":
L[k] = b + L[k] or "" + close
return L
@ -256,7 +270,7 @@ class ScoDocPageTemplate(PageTemplate):
if logo is not None:
self.background_image_filename = logo.filepath
def beforeDrawPage(self, canvas, doc):
def beforeDrawPage(self, canv, doc):
"""Draws (optional) background, logo and contribution message on each page.
day : Day of the month as a decimal number [01,31]
@ -271,10 +285,10 @@ class ScoDocPageTemplate(PageTemplate):
"""
if not self.preferences:
return
canvas.saveState()
canv.saveState()
# ---- Background image
if self.background_image_filename and self.with_page_background:
canvas.drawImage(
canv.drawImage(
self.background_image_filename, 0, 0, doc.pagesize[0], doc.pagesize[1]
)
@ -285,32 +299,32 @@ class ScoDocPageTemplate(PageTemplate):
(width, height),
image,
) = self.logo
canvas.drawImage(image, inch, doc.pagesize[1] - inch, width, height)
canv.drawImage(image, inch, doc.pagesize[1] - inch, width, height)
# ---- Add some meta data and bookmarks
if self.pdfmeta_author:
canvas.setAuthor(SU(self.pdfmeta_author))
canv.setAuthor(SU(self.pdfmeta_author))
if self.pdfmeta_title:
canvas.setTitle(SU(self.pdfmeta_title))
canv.setTitle(SU(self.pdfmeta_title))
if self.pdfmeta_subject:
canvas.setSubject(SU(self.pdfmeta_subject))
canv.setSubject(SU(self.pdfmeta_subject))
bookmark = self.pagesbookmarks.get(doc.page, None)
if bookmark:
canvas.bookmarkPage(bookmark)
canvas.addOutlineEntry(SU(bookmark), bookmark)
canv.bookmarkPage(bookmark)
canv.addOutlineEntry(SU(bookmark), bookmark)
def draw_footer(self, canvas, content):
def draw_footer(self, canv, content):
"""Print the footer"""
canvas.setFont(
canv.setFont(
self.preferences["SCOLAR_FONT"], self.preferences["SCOLAR_FONT_SIZE_FOOT"]
)
canvas.drawString(
canv.drawString(
self.preferences["pdf_footer_x"] * mm,
self.preferences["pdf_footer_y"] * mm,
content,
)
canvas.restoreState()
canv.restoreState()
def footer_string(self) -> str:
"""String contenu du pied de page"""
@ -319,14 +333,14 @@ class ScoDocPageTemplate(PageTemplate):
d["server_url"] = self.server_name
return SU(self.footer_template % d)
def afterDrawPage(self, canvas, doc):
def afterDrawPage(self, canv, doc):
if not self.preferences:
return
# ---- Footer
foot_content = None
if hasattr(doc, "current_footer"):
foot_content = doc.current_footer
self.draw_footer(canvas, foot_content or self.footer_string())
self.draw_footer(canv, foot_content or self.footer_string())
# ---- Filigranne (texte en diagonal en haut a gauche de chaque page)
filigranne = None
if hasattr(doc, "filigranne"):
@ -338,13 +352,13 @@ class ScoDocPageTemplate(PageTemplate):
else:
filigranne = self.filigranne.get(doc.page, None)
if filigranne:
canvas.saveState()
canvas.translate(9 * cm, 27.6 * cm)
canvas.rotate(30)
canvas.scale(4.5, 4.5)
canvas.setFillColorRGB(1.0, 0.65, 0.65, alpha=0.6)
canvas.drawRightString(0, 0, SU(filigranne))
canvas.restoreState()
canv.saveState()
canv.translate(9 * cm, 27.6 * cm)
canv.rotate(30)
canv.scale(4.5, 4.5)
canv.setFillColorRGB(1.0, 0.65, 0.65, alpha=0.6)
canv.drawRightString(0, 0, SU(filigranne))
canv.restoreState()
doc.filigranne = None
def afterPage(self):
@ -443,8 +457,8 @@ class PDFLock(object):
return # deja lock pour ce thread
try:
self.Q.put(1, True, self.timeout)
except queue.Full:
raise ScoGenError(msg="Traitement PDF occupé: ré-essayez")
except queue.Full as e:
raise ScoGenError(msg="Traitement PDF occupé: ré-essayez") from e
self.current_thread = threading.get_ident()
self.nref = 1
log("PDFLock: granted to %s" % self.current_thread)
@ -471,7 +485,6 @@ class WatchLock:
def release(self):
t = threading.current_thread()
assert (self.native_id == t.native_id) and (self.ident == t.ident)
pass
class FakeLock:

View File

@ -121,6 +121,7 @@ from app import log
from app.scodoc.sco_exceptions import ScoValueError, ScoException
from app.scodoc.TrivialFormulator import TrivialFormulator
import app.scodoc.notesdb as ndb
from app.scodoc import sco_pdf
import app.scodoc.sco_utils as scu
@ -194,6 +195,8 @@ def _get_pref_default_value_from_config(name, pref_spec):
return value
_INSTALLED_FONTS = ", ".join(sco_pdf.get_available_font_names())
PREF_CATEGORIES = (
# sur page "Paramètres"
("general", {}),
@ -777,7 +780,7 @@ class BasePreferences(object):
{
"initvalue": "Helvetica",
"title": "Police de caractère principale",
"explanation": "pour les pdf (Helvetica est recommandée)",
"explanation": f"pour les pdf (Helvetica est recommandée, parmi {_INSTALLED_FONTS})",
"size": 25,
"category": "pdf",
},
@ -1140,7 +1143,7 @@ class BasePreferences(object):
{
"initvalue": "Times-Roman",
"title": "Police de caractère pour les PV",
"explanation": "pour les pdf",
"explanation": f"pour les pdf ({_INSTALLED_FONTS})",
"size": 25,
"category": "pvpdf",
},
@ -1542,7 +1545,7 @@ class BasePreferences(object):
{
"initvalue": "Times-Roman",
"title": "Police titres bulletins",
"explanation": "pour les pdf",
"explanation": f"pour les pdf ({_INSTALLED_FONTS})",
"size": 25,
"category": "bul",
},

View File

@ -28,15 +28,13 @@
"""Edition des PV de jury
"""
import io
import os
import re
import reportlab
from reportlab.lib.units import cm, mm
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Frame, PageBreak
from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
from reportlab.platypus.flowables import Flowable
from reportlab.lib.enums import TA_RIGHT, TA_JUSTIFY
from reportlab.platypus import Paragraph, Spacer, Frame, PageBreak
from reportlab.platypus import Table, TableStyle, Image
from reportlab.platypus.doctemplate import PageTemplate, BaseDocTemplate
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib import styles
@ -53,7 +51,6 @@ from app.scodoc import sco_preferences
from app.scodoc import sco_etud
import sco_version
from app.scodoc.sco_logos import find_logo
from app.scodoc.sco_pdf import PDFLOCK
from app.scodoc.sco_pdf import SU
LOGO_FOOTER_ASPECT = scu.CONFIG.LOGO_FOOTER_ASPECT # XXX A AUTOMATISER
@ -317,14 +314,14 @@ class PVTemplate(CourrierIndividuelTemplate):
self.with_footer = self.preferences["PV_WITH_FOOTER"]
self.with_page_background = self.preferences["PV_WITH_BACKGROUND"]
def afterDrawPage(self, canvas, doc):
def afterDrawPage(self, canv, doc):
"""Called after all flowables have been drawn on a page"""
pass
def beforeDrawPage(self, canvas, doc):
def beforeDrawPage(self, canv, doc):
"""Called before any flowables are drawn on a page"""
# If the page number is even, force a page break
CourrierIndividuelTemplate.beforeDrawPage(self, canvas, doc)
CourrierIndividuelTemplate.beforeDrawPage(self, canv, doc)
# Note: on cherche un moyen de generer un saut de page double
# (redémarrer sur page impaire, nouvelle feuille en recto/verso). Pas trouvé en Platypus.
#

View File

@ -33,20 +33,23 @@
import io
from reportlab.lib import colors
from reportlab.lib import pagesizes
from reportlab.lib.colors import black
from reportlab.lib.pagesizes import A4, A3
from reportlab.lib import styles
from reportlab.lib.pagesizes import landscape
from reportlab.lib.units import cm
from reportlab.platypus import KeepInFrame, Paragraph, Table, TableStyle
from reportlab.platypus.doctemplate import BaseDocTemplate
import app.scodoc.sco_utils as scu
from app import log
from app.scodoc import sco_abs
from app.scodoc import sco_etud
from app.scodoc.sco_exceptions import ScoPDFFormatError
from app.scodoc import sco_groups
from app.scodoc import sco_groups_view
from app.scodoc import sco_preferences
from app.scodoc import sco_trombino
from app.scodoc import sco_etud
from app.scodoc.sco_exceptions import ScoPDFFormatError
from app.scodoc.sco_pdf import *
import app.scodoc.sco_utils as scu
from app.scodoc.sco_pdf import SU, ScoDocPageTemplate
# Paramétrage de l'aspect graphique:
PHOTOWIDTH = 2.8 * cm
@ -55,7 +58,7 @@ N_PER_ROW = 5
def pdf_trombino_tours(
group_ids=[], # liste des groupes à afficher
group_ids=(), # liste des groupes à afficher
formsemestre_id=None, # utilisé si pas de groupes selectionné
):
"""Generation du trombinoscope en fichier PDF"""
@ -66,7 +69,6 @@ def pdf_trombino_tours(
DeptName = sco_preferences.get_preference("DeptName")
DeptFullName = sco_preferences.get_preference("DeptFullName")
UnivName = sco_preferences.get_preference("UnivName")
InstituteName = sco_preferences.get_preference("InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
@ -143,9 +145,7 @@ def pdf_trombino_tours(
for group_id in groups_infos.group_ids:
if group_id != "None":
members, group, group_tit, sem, nbdem = sco_groups.get_group_infos(
group_id, "I"
)
members, _, group_tit, sem, _ = sco_groups.get_group_infos(group_id, "I")
groups += " %s" % group_tit
L = []
currow = []
@ -286,14 +286,14 @@ def pdf_trombino_tours(
def pdf_feuille_releve_absences(
group_ids=[], # liste des groupes à afficher
group_ids=(), # liste des groupes à afficher
formsemestre_id=None, # utilisé si pas de groupes selectionné
):
"""Generation de la feuille d'absence en fichier PDF, avec photos"""
NB_CELL_AM = sco_preferences.get_preference("feuille_releve_abs_AM")
NB_CELL_PM = sco_preferences.get_preference("feuille_releve_abs_PM")
COLWIDTH = 0.85 * cm
col_width = 0.85 * cm
if sco_preferences.get_preference("feuille_releve_abs_samedi"):
days = sco_abs.DAYNAMES[:6] # Lundi, ..., Samedi
else:
@ -307,7 +307,6 @@ def pdf_feuille_releve_absences(
DeptName = sco_preferences.get_preference("DeptName")
DeptFullName = sco_preferences.get_preference("DeptFullName")
UnivName = sco_preferences.get_preference("UnivName")
InstituteName = sco_preferences.get_preference("InstituteName")
# Generate PDF page
StyleSheet = styles.getSampleStyleSheet()
@ -340,7 +339,7 @@ def pdf_feuille_releve_absences(
currow = [""] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)
elem_day = Table(
[currow],
colWidths=([COLWIDTH] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
colWidths=([col_width] * (NB_CELL_AM + 1 + NB_CELL_PM + 1)),
style=TableStyle(
[
("GRID", (0, 0), (NB_CELL_AM - 1, 0), 0.25, black),
@ -362,7 +361,7 @@ def pdf_feuille_releve_absences(
elem_week = Table(
W,
colWidths=([COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
style=TableStyle(
[
("LEFTPADDING", (0, 0), (-1, -1), 0),
@ -378,7 +377,7 @@ def pdf_feuille_releve_absences(
elem_day_name = Table(
[currow],
colWidths=([COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
colWidths=([col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1)] * nb_days),
style=TableStyle(
[
("LEFTPADDING", (0, 0), (-1, -1), 0),
@ -390,9 +389,7 @@ def pdf_feuille_releve_absences(
)
for group_id in groups_infos.group_ids:
members, group, group_tit, sem, nbdem = sco_groups.get_group_infos(
group_id, "I"
)
members, _, group_tit, _, _ = sco_groups.get_group_infos(group_id, "I")
L = []
currow = [
@ -429,7 +426,10 @@ def pdf_feuille_releve_absences(
T = Table(
L,
colWidths=(
[5.0 * cm, (COLWIDTH * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days)]
[
5.0 * cm,
(col_width * (NB_CELL_AM + 1 + NB_CELL_PM + 1) * nb_days),
]
),
style=TableStyle(
[