- Revised the Kiosk-Mode section in SUMMARY.md to include recent changes related to SSL support and improved user experience. - Clarified instructions for setting up kiosk mode with the new SSL configuration. - Ensured consistency in formatting and alignment for better readability.
587 lines
18 KiB
Python
587 lines
18 KiB
Python
import os
|
|
import io
|
|
import requests
|
|
from PIL import Image
|
|
from pptx import Presentation
|
|
from pptx.util import Inches, Pt
|
|
from pptx.dml.color import RGBColor
|
|
from pptx.enum.text import PP_ALIGN
|
|
|
|
# Stile und Konstanten
|
|
TITLE_FONT = 'Helvetica Neue'
|
|
BODY_FONT = 'Helvetica Neue'
|
|
PRIMARY_COLOR = RGBColor(0, 122, 255) # Apple Blau
|
|
SECONDARY_COLOR = RGBColor(88, 86, 214) # Apple Lila
|
|
ACCENT_COLOR = RGBColor(255, 149, 0) # Apple Orange
|
|
DARK_TEXT = RGBColor(50, 50, 50)
|
|
LIGHT_TEXT = RGBColor(240, 240, 240)
|
|
BACKGROUND_COLOR = RGBColor(250, 250, 250)
|
|
SLIDE_WIDTH = Inches(13.333)
|
|
SLIDE_HEIGHT = Inches(7.5)
|
|
|
|
# Ausgabepfad
|
|
output_dir = os.path.dirname(os.path.abspath(__file__))
|
|
output_path = os.path.join(output_dir, 'MYP_Backend_Schulung_Enhanced.pptx')
|
|
images_dir = os.path.join(output_dir, 'presentation_images')
|
|
|
|
# Verzeichnis für Bilder erstellen, falls es nicht existiert
|
|
os.makedirs(images_dir, exist_ok=True)
|
|
|
|
# Funktion zum Herunterladen von Stock-Bildern (nur Beispiel, Sie können auch eigene Bilder verwenden)
|
|
def download_stock_image(url, filename):
|
|
try:
|
|
image_path = os.path.join(images_dir, filename)
|
|
# Wenn das Bild bereits existiert, nicht erneut herunterladen
|
|
if os.path.exists(image_path):
|
|
return image_path
|
|
|
|
response = requests.get(url, stream=True)
|
|
if response.status_code == 200:
|
|
with open(image_path, 'wb') as f:
|
|
f.write(response.content)
|
|
return image_path
|
|
else:
|
|
print(f"Fehler beim Herunterladen des Bildes: {response.status_code}")
|
|
return None
|
|
except Exception as e:
|
|
print(f"Fehler: {e}")
|
|
return None
|
|
|
|
# Platzhalterbilder für die Präsentation
|
|
# Im echten Einsatz würden Sie eigene Bilder oder lizenzfreie Bilder verwenden
|
|
image_urls = {
|
|
"header": "https://cdn.pixabay.com/photo/2017/08/10/02/05/tiles-shapes-2617112_1280.jpg",
|
|
"3d_printer": "https://cdn.pixabay.com/photo/2019/07/06/11/15/3d-printer-4320296_1280.jpg",
|
|
"backend": "https://cdn.pixabay.com/photo/2016/11/27/21/42/stock-1863880_1280.jpg",
|
|
"database": "https://cdn.pixabay.com/photo/2017/06/14/16/20/network-2402637_1280.jpg",
|
|
"api": "https://cdn.pixabay.com/photo/2018/05/04/20/01/website-3374825_1280.jpg",
|
|
"scheduler": "https://cdn.pixabay.com/photo/2018/01/17/07/06/laptop-3087585_1280.jpg",
|
|
"security": "https://cdn.pixabay.com/photo/2017/11/19/23/56/cyber-security-2965030_1280.jpg",
|
|
"summary": "https://cdn.pixabay.com/photo/2019/04/14/10/27/book-4126483_1280.jpg"
|
|
}
|
|
|
|
# Bilder herunterladen
|
|
image_paths = {}
|
|
for key, url in image_urls.items():
|
|
filename = f"{key}.jpg"
|
|
image_path = download_stock_image(url, filename)
|
|
if image_path:
|
|
image_paths[key] = image_path
|
|
else:
|
|
print(f"Konnte Bild {key} nicht herunterladen")
|
|
|
|
# Neue Präsentation erstellen
|
|
prs = Presentation()
|
|
|
|
# Foliengröße auf 16:9 setzen
|
|
prs.slide_width = SLIDE_WIDTH
|
|
prs.slide_height = SLIDE_HEIGHT
|
|
|
|
# Hilfsfunktion für einheitliche Formatierung
|
|
def apply_text_style(paragraph, font_size, bold=False, color=DARK_TEXT, alignment=PP_ALIGN.LEFT):
|
|
paragraph.alignment = alignment
|
|
run = paragraph.runs[0]
|
|
run.font.name = BODY_FONT
|
|
run.font.size = Pt(font_size)
|
|
run.font.bold = bold
|
|
run.font.color.rgb = color
|
|
|
|
# Hilfsfunktion zum Hinzufügen eines Bildes zu einer Folie
|
|
def add_image_to_slide(slide, image_path, left, top, width, height=None, keep_ratio=True):
|
|
if not os.path.exists(image_path):
|
|
print(f"Bildpfad existiert nicht: {image_path}")
|
|
return None
|
|
|
|
img = Image.open(image_path)
|
|
width_inches = width
|
|
|
|
if keep_ratio and height is None:
|
|
# Seitenverhältnis beibehalten
|
|
img_ratio = img.height / img.width
|
|
height_inches = width_inches * img_ratio
|
|
else:
|
|
height_inches = height
|
|
|
|
return slide.shapes.add_picture(image_path, left, top, width=width_inches, height=height_inches)
|
|
|
|
# Hilfsfunktion zum Erstellen eines abgerundeten Farbbereichs (als Ersatz für abgerundete Rechtecke)
|
|
def add_rectangle_to_slide(slide, left, top, width, height, color=PRIMARY_COLOR):
|
|
shape = slide.shapes.add_shape(1, left, top, width, height) # 1 = Rechteck
|
|
shape.fill.solid()
|
|
shape.fill.fore_color.rgb = color
|
|
shape.line.fill.solid()
|
|
shape.line.fill.fore_color.rgb = color
|
|
return shape
|
|
|
|
# ------------- FOLIE 1: TITELFOLIE -------------
|
|
slide_layout = prs.slide_layouts[0] # Titelfolie
|
|
slide = prs.slides.add_slide(slide_layout)
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
# Hintergrundbild (wenn verfügbar)
|
|
if "header" in image_paths:
|
|
header_img = add_image_to_slide(slide,
|
|
image_paths["header"],
|
|
Inches(0),
|
|
Inches(0),
|
|
SLIDE_WIDTH,
|
|
SLIDE_HEIGHT,
|
|
keep_ratio=False)
|
|
# Bild in den Hintergrund
|
|
if header_img:
|
|
header_img.z_order = 0
|
|
|
|
# Halbtransparentes Overlay
|
|
overlay = add_rectangle_to_slide(slide,
|
|
Inches(0),
|
|
Inches(0),
|
|
SLIDE_WIDTH,
|
|
SLIDE_HEIGHT,
|
|
RGBColor(0, 0, 0))
|
|
overlay.fill.transparency = 0.4 # 40% Transparenz
|
|
overlay.z_order = 1
|
|
|
|
# Titel hinzufügen
|
|
title_shape = slide.shapes.title
|
|
title_shape.text = "MYP Platform"
|
|
title_paragraph = title_shape.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 64, bold=True, color=LIGHT_TEXT, alignment=PP_ALIGN.CENTER)
|
|
title_shape.z_order = 2
|
|
|
|
# Untertitel hinzufügen
|
|
subtitle_shape = slide.placeholders[1]
|
|
subtitle_shape.text = "3D-Drucker Reservierungssystem\nBackend-Schulung"
|
|
subtitle_paragraph = subtitle_shape.text_frame.paragraphs[0]
|
|
apply_text_style(subtitle_paragraph, 36, color=LIGHT_TEXT, alignment=PP_ALIGN.CENTER)
|
|
subtitle_shape.z_order = 2
|
|
|
|
# ------------- FOLIE 2: ÜBERBLICK -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Systemüberblick"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Reservierungssystem für 3D-Drucker"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Automatische Steuerung von Smart Plugs"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Echtzeit-Überwachung von Druckaufträgen"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Administrationsfunktionen"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Statistik und Analyse"
|
|
apply_text_style(p, 28)
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "3d_printer" in image_paths:
|
|
printer_img = add_image_to_slide(slide,
|
|
image_paths["3d_printer"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 3: TECHNOLOGIE-STACK -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Technologie-Stack"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Backend: Python 3.11 mit Flask"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Frontend: HTML/CSS/JavaScript mit Tailwind CSS"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Datenbank: SQLite mit SQLAlchemy ORM"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Authentifizierung: Flask-Login"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Hardware-Integration: PyP110 für Tapo Smart Plug Steuerung"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Automatisierung: Integrierter Job-Scheduler"
|
|
apply_text_style(p, 28)
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "backend" in image_paths:
|
|
backend_img = add_image_to_slide(slide,
|
|
image_paths["backend"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 4: ARCHITEKTUR -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Backend-Architektur"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Flask-App: Zentrale Anwendungslogik"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = PRIMARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Blueprints: Modulare Strukturierung (auth, user, kiosk)"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Models: SQLAlchemy ORM für Datenbankkommunikation"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Utils: Job-Scheduler, Logging, Template-Helpers"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• API: RESTful-Endpunkte für Frontend-Kommunikation"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
# ------------- FOLIE 5: DATENMODELL -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Datenmodell"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• User: Benutzer mit Rollen und Authentifizierung"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Printer: 3D-Drucker mit Smart-Plug-Konfigurationen"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Job: Druckaufträge mit Status und Zeitplanung"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Stats: Systemstatistiken und Metriken"
|
|
apply_text_style(p, 28)
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "database" in image_paths:
|
|
db_img = add_image_to_slide(slide,
|
|
image_paths["database"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 6: API-ENDPUNKTE -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "API-Endpunkte"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• /api/jobs: Druckaufträge verwalten"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• /api/printers: Drucker verwalten"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• /api/users: Benutzer verwalten"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• /api/stats: Statistiken abrufen"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• /api/scheduler: Scheduler steuern"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = PRIMARY_COLOR
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "api" in image_paths:
|
|
api_img = add_image_to_slide(slide,
|
|
image_paths["api"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 7: JOB-SCHEDULER -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Job-Scheduler"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Automatische Steuerung der Drucker"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Einschalten bei Auftragsstart"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Ausschalten bei Auftragsende"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Statusüberwachung und -aktualisierung"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Sammeln von Statistiken"
|
|
apply_text_style(p, 28)
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "scheduler" in image_paths:
|
|
scheduler_img = add_image_to_slide(slide,
|
|
image_paths["scheduler"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 8: LOGGING-SYSTEM -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Logging-System"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Separate Logs für verschiedene Bereiche:"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.bold = True
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = " - App-Logs: Allgemeine Anwendungslogs"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = " - Auth-Logs: Authentifizierungsereignisse"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = " - Job-Logs: Druckauftragsoperationen"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = " - Printer-Logs: Druckerstatusänderungen"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = " - Scheduler-Logs: Automatisierungsaktionen"
|
|
apply_text_style(p, 28)
|
|
|
|
# ------------- FOLIE 9: SICHERHEITSKONZEPT -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Sicherheitskonzept"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Benutzerauthentifizierung mit bcrypt"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Rollenbasierte Zugriffskontrolle"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• CSRF-Schutz bei Formularen"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Besitzer-Check für Druckaufträge"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Sichere HTTP-Header"
|
|
apply_text_style(p, 28)
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "security" in image_paths:
|
|
security_img = add_image_to_slide(slide,
|
|
image_paths["security"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# ------------- FOLIE 10: ZUSAMMENFASSUNG -------------
|
|
slide = prs.slides.add_slide(prs.slide_layouts[1])
|
|
|
|
# Hintergrund anpassen
|
|
background = slide.background
|
|
fill = background.fill
|
|
fill.solid()
|
|
fill.fore_color.rgb = BACKGROUND_COLOR
|
|
|
|
title = slide.shapes.title
|
|
title.text = "Zusammenfassung"
|
|
title_paragraph = title.text_frame.paragraphs[0]
|
|
apply_text_style(title_paragraph, 44, bold=True, color=PRIMARY_COLOR, alignment=PP_ALIGN.LEFT)
|
|
|
|
# Inhalt
|
|
content = slide.placeholders[1]
|
|
tf = content.text_frame
|
|
|
|
p = tf.paragraphs[0]
|
|
p.text = "• Vollständige Lösung für 3D-Drucker-Management"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.bold = True
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Modulare Architektur für einfache Erweiterbarkeit"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Robuste Sicherheitskonzepte"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = SECONDARY_COLOR
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Umfassendes Logging und Überwachung"
|
|
apply_text_style(p, 28)
|
|
|
|
p = tf.add_paragraph()
|
|
p.text = "• Automatisierung von Routineaufgaben"
|
|
apply_text_style(p, 28)
|
|
p.runs[0].font.color.rgb = ACCENT_COLOR
|
|
|
|
# Bild einfügen (wenn verfügbar)
|
|
if "summary" in image_paths:
|
|
summary_img = add_image_to_slide(slide,
|
|
image_paths["summary"],
|
|
Inches(7),
|
|
Inches(2),
|
|
Inches(5))
|
|
|
|
# Präsentation speichern
|
|
prs.save(output_path)
|
|
print(f"Verbesserte Präsentation wurde erstellt: {output_path}") |