171 lines
6.3 KiB
Python
171 lines
6.3 KiB
Python
from reportlab.lib.pagesizes import A4
|
|
from reportlab.lib import colors
|
|
from reportlab.pdfgen import canvas
|
|
from reportlab.lib.units import mm
|
|
from datetime import datetime
|
|
import os
|
|
import re
|
|
import textwrap
|
|
|
|
# Konstanten für die Abmessungen
|
|
CIRCLE_RADIUS = 3 * mm
|
|
CIRCLE_DISTANCE = 80 * mm
|
|
TOP_MARGIN_TO_CENTER = 12 * mm
|
|
IMAGE_TOP_MARGIN = 28 * mm
|
|
IMAGE_HEIGHT = 60 * mm
|
|
TEXT_MARGIN = 5 * mm
|
|
LEFT_MARGIN_TO_CENTER = (A4[0] / 4) - (CIRCLE_DISTANCE / 2) # Zentriert zwischen den Tagen
|
|
IMAGE_SHIFT_UP = 1 * mm # Bild nach oben verschieben
|
|
DATE_SHIFT_DOWN = 8 * mm # Datum nach unten verschieben
|
|
TEXT_SHIFT_DOWN = 8 * mm # Text nach unten verschieben
|
|
|
|
def get_dates_from_images(image_directory):
|
|
# Regular expression to match files with a date format YYYY-MM-DD
|
|
date_pattern = re.compile(r'(\d{4}-\d{2}-\d{2})')
|
|
|
|
# List to store the dates
|
|
dates = []
|
|
|
|
# Iterate over each file in the images directory
|
|
for filename in os.listdir(image_directory):
|
|
# Search for the pattern in the filename
|
|
match = date_pattern.search(filename)
|
|
if match:
|
|
# Extract the date from the filename
|
|
try:
|
|
date = datetime.strptime(match.group(), '%Y-%m-%d')
|
|
dates.append(date)
|
|
except ValueError:
|
|
# If the date format is incorrect, ignore the file
|
|
continue
|
|
|
|
# Return the sorted list of dates
|
|
return sorted(dates)
|
|
|
|
def get_image_and_text_for_date(date, image_directory, text_directory):
|
|
formatted_date = date.strftime('%Y-%m-%d')
|
|
image_file = None
|
|
text_content = None
|
|
|
|
# Check for image file
|
|
for ext in ['jpg', 'jpeg', 'png']:
|
|
# Check using full path, but store relative path for HTML
|
|
image_full_path = os.path.join(image_directory, f"{formatted_date}.{ext}")
|
|
if os.path.isfile(image_full_path):
|
|
# Store the relative path from within the 'static' directory
|
|
image_file = f"images/{formatted_date}.{ext}"
|
|
break
|
|
|
|
# Check for text file
|
|
text_path = os.path.join(text_directory, f"{formatted_date}.txt")
|
|
if os.path.isfile(text_path):
|
|
with open(text_path, 'r') as file:
|
|
text_content = file.read()
|
|
|
|
return image_file, text_content
|
|
|
|
def draw_circle(c, x, y):
|
|
c.circle(x, y, CIRCLE_RADIUS, stroke=1, fill=0)
|
|
|
|
def create_pdf(pages_data, output_filename):
|
|
c = canvas.Canvas(output_filename, pagesize=A4)
|
|
c.setCreator('Lorenz B.')
|
|
c.setTitle('Calendar')
|
|
c.setAuthor('Lorenz B.')
|
|
c.setSubject('calendar generator')
|
|
width, height = A4
|
|
|
|
max_text_width = (width / 2) - (2 * TEXT_MARGIN)
|
|
DATE_FONT_SIZE = 20
|
|
DATE_FONT = "Helvetica-Bold"
|
|
|
|
for page in pages_data:
|
|
for index, day in enumerate(page):
|
|
c.setDash(1, 0)
|
|
c.setStrokeColor(colors.black)
|
|
|
|
# Berechnung der Positionen für jeden Tag
|
|
x = (index % 2) * (width / 2)
|
|
y = height - (index // 2 + 1) * (height / 2)
|
|
|
|
# Höhere Position für das Bild
|
|
image_y_position = y + (height / 2 - IMAGE_TOP_MARGIN - IMAGE_HEIGHT) + IMAGE_SHIFT_UP
|
|
|
|
# Kreise zeichnen
|
|
draw_circle(c, x + LEFT_MARGIN_TO_CENTER, y + height / 2 - TOP_MARGIN_TO_CENTER)
|
|
draw_circle(c, x + width / 2 - LEFT_MARGIN_TO_CENTER, y + height / 2 - TOP_MARGIN_TO_CENTER)
|
|
|
|
# Bild einfügen
|
|
if day['image_file']:
|
|
c.drawImage(day['image_file'], x, image_y_position, width=width / 2, height=IMAGE_HEIGHT, preserveAspectRatio=True, anchor='n')
|
|
|
|
# Datum direkt unter dem Bild einfügen
|
|
date_x_position = x + (width / 4) # Zentrum des Tagesbereichs
|
|
date_y_position = image_y_position - DATE_SHIFT_DOWN
|
|
date_str = day['date'].strftime('%A, %d.%m.%Y')
|
|
c.setFont(DATE_FONT, DATE_FONT_SIZE) # Schriftart und Schriftgröße setzen
|
|
date_width = c.stringWidth(date_str, DATE_FONT, DATE_FONT_SIZE)
|
|
c.drawString(date_x_position - (date_width / 2), date_y_position, date_str)
|
|
|
|
# Text unter dem Datum einfügen
|
|
text_y_position = date_y_position - TEXT_SHIFT_DOWN - 5 * mm # Extra Abstand nach einem größeren Datum
|
|
if day['text_content']:
|
|
c.setFont("Helvetica", 12) # Schriftart zurücksetzen für den Text
|
|
wrapped_text = textwrap.fill(day['text_content'], width=50) # Anpassen für die passende Zeilenlänge
|
|
text = c.beginText(x + TEXT_MARGIN, text_y_position)
|
|
for line in wrapped_text.split('\n'):
|
|
text.textLine(line)
|
|
c.drawText(text)
|
|
|
|
# Gestrichelte Linien zeichnen, falls notwendig
|
|
c.setDash(1, 2)
|
|
c.setStrokeColor(colors.grey)
|
|
if index % 2 == 0: # Vertikale Linie rechts für den Tag
|
|
c.line(x + width / 2, y, x + width / 2, y + height / 2)
|
|
if index < 2: # Horizontale Linie unten für den Tag
|
|
c.line(x, y, x + width / 2, y)
|
|
|
|
c.showPage()
|
|
c.save()
|
|
|
|
def main():
|
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
image_directory = os.path.join(BASE_DIR, 'images')
|
|
text_directory = os.path.join(BASE_DIR, 'texts')
|
|
|
|
# Get sorted dates from image files
|
|
dates = get_dates_from_images(image_directory)
|
|
if not dates:
|
|
print("No images found with the correct date format in the name.")
|
|
return
|
|
|
|
# Generate data for each date
|
|
pages_data = []
|
|
days_data = []
|
|
for date in dates:
|
|
image_file, text_content = get_image_and_text_for_date(date, image_directory, text_directory)
|
|
days_data.append({
|
|
'date': date,
|
|
'image_file': image_file,
|
|
'text_content': text_content
|
|
})
|
|
|
|
# Check if we have collected data for 4 days, then start a new page
|
|
if len(days_data) == 4:
|
|
pages_data.append(days_data)
|
|
days_data = []
|
|
|
|
# Add any remaining days to the last page
|
|
if days_data:
|
|
pages_data.append(days_data)
|
|
|
|
# Create the PDF
|
|
output_filename = os.path.join(BASE_DIR, 'calendar.pdf')
|
|
create_pdf(pages_data, output_filename)
|
|
|
|
print("PDF created successfully.")
|
|
|
|
if __name__ == '__main__':
|
|
main()
|