Spaces:
Sleeping
Sleeping
Update pages/1_π_Text_to_PPT.py
Browse files- pages/1_π_Text_to_PPT.py +62 -46
pages/1_π_Text_to_PPT.py
CHANGED
@@ -1325,7 +1325,7 @@ def add_title_separator(slide, title_shape, accent_color):
|
|
1325 |
line.line.fill.background()
|
1326 |
|
1327 |
def create_question_slide(prs, question, question_num, theme):
|
1328 |
-
"""Create a slide for a single question"""
|
1329 |
# Try to use Title + Content layout, fallback to blank if not available
|
1330 |
try:
|
1331 |
slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title + Content layout
|
@@ -1338,27 +1338,32 @@ def create_question_slide(prs, question, question_num, theme):
|
|
1338 |
sp = shape._element
|
1339 |
sp.getparent().remove(sp)
|
1340 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1341 |
# Set title
|
1342 |
title = slide.shapes.title if hasattr(slide.shapes, 'title') else None
|
1343 |
if title:
|
1344 |
title.text = f"Question {question_num}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1345 |
|
1346 |
-
#
|
1347 |
-
if "template_path" not in theme and title:
|
1348 |
-
title.text_frame.paragraphs[0].font.color.rgb = theme["accent"]
|
1349 |
-
title.text_frame.paragraphs[0].font.size = Pt(36)
|
1350 |
-
title.text_frame.paragraphs[0].font.bold = True
|
1351 |
-
if "title_font" in theme:
|
1352 |
-
title.text_frame.paragraphs[0].font.name = theme["title_font"]
|
1353 |
-
|
1354 |
-
# Add decorative line under title
|
1355 |
-
add_title_separator(slide, title, theme["accent"])
|
1356 |
-
|
1357 |
-
# Create content
|
1358 |
left = Inches(1)
|
1359 |
top = Inches(2) if title else Inches(0.5)
|
1360 |
width = prs.slide_width - Inches(2)
|
1361 |
-
height = prs.slide_height - Inches(
|
1362 |
|
1363 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1364 |
tf = content_box.text_frame
|
@@ -1370,14 +1375,14 @@ def create_question_slide(prs, question, question_num, theme):
|
|
1370 |
p.font.bold = True
|
1371 |
p.space_after = Pt(24)
|
1372 |
|
1373 |
-
#
|
1374 |
if "template_path" not in theme:
|
1375 |
p.font.color.rgb = theme["text_color"]
|
1376 |
p.font.size = Pt(24)
|
1377 |
if "text_font" in theme:
|
1378 |
p.font.name = theme["text_font"]
|
1379 |
|
1380 |
-
# Add options
|
1381 |
for j, opt in enumerate(question['options']):
|
1382 |
p = tf.add_paragraph()
|
1383 |
p.text = f"{chr(65+j)}. {opt}"
|
@@ -1385,7 +1390,7 @@ def create_question_slide(prs, question, question_num, theme):
|
|
1385 |
p.space_before = Pt(12)
|
1386 |
p.space_after = Pt(12)
|
1387 |
|
1388 |
-
#
|
1389 |
if "template_path" not in theme:
|
1390 |
p.font.color.rgb = theme["text_color"]
|
1391 |
p.font.size = Pt(20)
|
@@ -1402,13 +1407,20 @@ def create_question_slide(prs, question, question_num, theme):
|
|
1402 |
return slide
|
1403 |
|
1404 |
def create_answer_key_slide(prs, questions, theme):
|
1405 |
-
"""Create answer key slide with
|
1406 |
# Try to use Title + Content layout, fallback to blank if not available
|
1407 |
try:
|
1408 |
slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title + Content layout
|
1409 |
except IndexError:
|
1410 |
slide = prs.slides.add_slide(prs.slide_layouts[6]) # Blank layout
|
1411 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1412 |
# Remove unused placeholders
|
1413 |
for shape in slide.shapes:
|
1414 |
if shape.has_text_frame and not shape.text.strip():
|
@@ -1419,23 +1431,21 @@ def create_answer_key_slide(prs, questions, theme):
|
|
1419 |
title = slide.shapes.title if hasattr(slide.shapes, 'title') else None
|
1420 |
if title:
|
1421 |
title.text = "Answer Key"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1422 |
|
1423 |
-
#
|
1424 |
-
if "template_path" not in theme and title:
|
1425 |
-
title.text_frame.paragraphs[0].font.color.rgb = theme["accent"]
|
1426 |
-
title.text_frame.paragraphs[0].font.size = Pt(36)
|
1427 |
-
title.text_frame.paragraphs[0].font.bold = True
|
1428 |
-
if "title_font" in theme:
|
1429 |
-
title.text_frame.paragraphs[0].font.name = theme["title_font"]
|
1430 |
-
|
1431 |
-
# Add decorative line under title
|
1432 |
-
add_title_separator(slide, title, theme["accent"])
|
1433 |
-
|
1434 |
-
# Create content
|
1435 |
left = Inches(1.5)
|
1436 |
top = Inches(2) if title else Inches(0.5)
|
1437 |
width = prs.slide_width - Inches(3)
|
1438 |
-
height = prs.slide_height - Inches(
|
1439 |
|
1440 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1441 |
tf = content_box.text_frame
|
@@ -1448,7 +1458,7 @@ def create_answer_key_slide(prs, questions, theme):
|
|
1448 |
p.level = 0
|
1449 |
p.space_after = Pt(18)
|
1450 |
|
1451 |
-
#
|
1452 |
if "template_path" not in theme:
|
1453 |
p.font.color.rgb = theme["text_color"]
|
1454 |
p.font.size = Pt(24)
|
@@ -1496,6 +1506,13 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, p
|
|
1496 |
except IndexError:
|
1497 |
slide = prs.slides.add_slide(prs.slide_layouts[default_layout_idx])
|
1498 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1499 |
# Remove unused placeholders
|
1500 |
for shape in slide.shapes:
|
1501 |
if shape.has_text_frame and not shape.text.strip():
|
@@ -1539,14 +1556,6 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, p
|
|
1539 |
if "title_color" in theme:
|
1540 |
p.font.color.rgb = theme["title_color"]
|
1541 |
|
1542 |
-
# Only apply custom formatting if not using a template
|
1543 |
-
if "template_path" not in theme:
|
1544 |
-
# Apply background
|
1545 |
-
background = slide.background
|
1546 |
-
fill = background.fill
|
1547 |
-
fill.solid()
|
1548 |
-
fill.fore_color.rgb = theme["background"]
|
1549 |
-
|
1550 |
# Set content based on layout
|
1551 |
if layout == 'two-column':
|
1552 |
content = slide_info.get('content', [])
|
@@ -1556,9 +1565,9 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, p
|
|
1556 |
|
1557 |
# Create left column
|
1558 |
left = Inches(0.5)
|
1559 |
-
top = Inches(
|
1560 |
width = prs.slide_width / 2 - Inches(1)
|
1561 |
-
height = prs.slide_height - Inches(
|
1562 |
left_box = slide.shapes.add_textbox(left, top, width, height)
|
1563 |
left_tf = left_box.text_frame
|
1564 |
|
@@ -1584,9 +1593,9 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, p
|
|
1584 |
elif layout != 'title-only': # Content slides
|
1585 |
# Create content area
|
1586 |
left = Inches(1)
|
1587 |
-
top = Inches(
|
1588 |
width = prs.slide_width - Inches(2)
|
1589 |
-
height = prs.slide_height - Inches(
|
1590 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1591 |
tf = content_box.text_frame
|
1592 |
|
@@ -1609,14 +1618,21 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, p
|
|
1609 |
if hasattr(notes_slide, 'notes_text_frame'):
|
1610 |
notes_slide.notes_text_frame.text = slide_info['notes']
|
1611 |
|
1612 |
-
# Add question slides (one per question)
|
1613 |
if questions:
|
1614 |
-
# Add section header
|
1615 |
try:
|
1616 |
section_slide = prs.slides.add_slide(prs.slide_layouts[2]) # Section header layout
|
1617 |
except IndexError:
|
1618 |
section_slide = prs.slides.add_slide(prs.slide_layouts[0]) # Fallback to title slide
|
1619 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1620 |
title_placeholder = section_slide.shapes.title if hasattr(section_slide.shapes, 'title') else None
|
1621 |
if title_placeholder is not None:
|
1622 |
title_placeholder.text = "Knowledge Check"
|
|
|
1325 |
line.line.fill.background()
|
1326 |
|
1327 |
def create_question_slide(prs, question, question_num, theme):
|
1328 |
+
"""Create a slide for a single question with proper theme support"""
|
1329 |
# Try to use Title + Content layout, fallback to blank if not available
|
1330 |
try:
|
1331 |
slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title + Content layout
|
|
|
1338 |
sp = shape._element
|
1339 |
sp.getparent().remove(sp)
|
1340 |
|
1341 |
+
# Apply background if using custom theme
|
1342 |
+
if "template_path" not in theme:
|
1343 |
+
background = slide.background
|
1344 |
+
fill = background.fill
|
1345 |
+
fill.solid()
|
1346 |
+
fill.fore_color.rgb = theme["background"]
|
1347 |
+
|
1348 |
# Set title
|
1349 |
title = slide.shapes.title if hasattr(slide.shapes, 'title') else None
|
1350 |
if title:
|
1351 |
title.text = f"Question {question_num}"
|
1352 |
+
if "template_path" not in theme:
|
1353 |
+
title.text_frame.paragraphs[0].font.color.rgb = theme["accent"]
|
1354 |
+
title.text_frame.paragraphs[0].font.size = Pt(36)
|
1355 |
+
title.text_frame.paragraphs[0].font.bold = True
|
1356 |
+
if "title_font" in theme:
|
1357 |
+
title.text_frame.paragraphs[0].font.name = theme["title_font"]
|
1358 |
+
|
1359 |
+
# Add decorative line under title
|
1360 |
+
add_title_separator(slide, title, theme["accent"])
|
1361 |
|
1362 |
+
# Create content area with proper spacing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1363 |
left = Inches(1)
|
1364 |
top = Inches(2) if title else Inches(0.5)
|
1365 |
width = prs.slide_width - Inches(2)
|
1366 |
+
height = prs.slide_height - top - Inches(1) # Leave 1 inch at bottom
|
1367 |
|
1368 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1369 |
tf = content_box.text_frame
|
|
|
1375 |
p.font.bold = True
|
1376 |
p.space_after = Pt(24)
|
1377 |
|
1378 |
+
# Apply text formatting
|
1379 |
if "template_path" not in theme:
|
1380 |
p.font.color.rgb = theme["text_color"]
|
1381 |
p.font.size = Pt(24)
|
1382 |
if "text_font" in theme:
|
1383 |
p.font.name = theme["text_font"]
|
1384 |
|
1385 |
+
# Add options with proper spacing
|
1386 |
for j, opt in enumerate(question['options']):
|
1387 |
p = tf.add_paragraph()
|
1388 |
p.text = f"{chr(65+j)}. {opt}"
|
|
|
1390 |
p.space_before = Pt(12)
|
1391 |
p.space_after = Pt(12)
|
1392 |
|
1393 |
+
# Apply text formatting
|
1394 |
if "template_path" not in theme:
|
1395 |
p.font.color.rgb = theme["text_color"]
|
1396 |
p.font.size = Pt(20)
|
|
|
1407 |
return slide
|
1408 |
|
1409 |
def create_answer_key_slide(prs, questions, theme):
|
1410 |
+
"""Create answer key slide with proper theme support"""
|
1411 |
# Try to use Title + Content layout, fallback to blank if not available
|
1412 |
try:
|
1413 |
slide = prs.slides.add_slide(prs.slide_layouts[1]) # Title + Content layout
|
1414 |
except IndexError:
|
1415 |
slide = prs.slides.add_slide(prs.slide_layouts[6]) # Blank layout
|
1416 |
|
1417 |
+
# Apply background if using custom theme
|
1418 |
+
if "template_path" not in theme:
|
1419 |
+
background = slide.background
|
1420 |
+
fill = background.fill
|
1421 |
+
fill.solid()
|
1422 |
+
fill.fore_color.rgb = theme["background"]
|
1423 |
+
|
1424 |
# Remove unused placeholders
|
1425 |
for shape in slide.shapes:
|
1426 |
if shape.has_text_frame and not shape.text.strip():
|
|
|
1431 |
title = slide.shapes.title if hasattr(slide.shapes, 'title') else None
|
1432 |
if title:
|
1433 |
title.text = "Answer Key"
|
1434 |
+
if "template_path" not in theme:
|
1435 |
+
title.text_frame.paragraphs[0].font.color.rgb = theme["accent"]
|
1436 |
+
title.text_frame.paragraphs[0].font.size = Pt(36)
|
1437 |
+
title.text_frame.paragraphs[0].font.bold = True
|
1438 |
+
if "title_font" in theme:
|
1439 |
+
title.text_frame.paragraphs[0].font.name = theme["title_font"]
|
1440 |
+
|
1441 |
+
# Add decorative line under title
|
1442 |
+
add_title_separator(slide, title, theme["accent"])
|
1443 |
|
1444 |
+
# Create content area with proper spacing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1445 |
left = Inches(1.5)
|
1446 |
top = Inches(2) if title else Inches(0.5)
|
1447 |
width = prs.slide_width - Inches(3)
|
1448 |
+
height = prs.slide_height - top - Inches(1) # Leave 1 inch at bottom
|
1449 |
|
1450 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1451 |
tf = content_box.text_frame
|
|
|
1458 |
p.level = 0
|
1459 |
p.space_after = Pt(18)
|
1460 |
|
1461 |
+
# Apply text formatting
|
1462 |
if "template_path" not in theme:
|
1463 |
p.font.color.rgb = theme["text_color"]
|
1464 |
p.font.size = Pt(24)
|
|
|
1506 |
except IndexError:
|
1507 |
slide = prs.slides.add_slide(prs.slide_layouts[default_layout_idx])
|
1508 |
|
1509 |
+
# Apply background if using custom theme
|
1510 |
+
if "template_path" not in theme:
|
1511 |
+
background = slide.background
|
1512 |
+
fill = background.fill
|
1513 |
+
fill.solid()
|
1514 |
+
fill.fore_color.rgb = theme["background"]
|
1515 |
+
|
1516 |
# Remove unused placeholders
|
1517 |
for shape in slide.shapes:
|
1518 |
if shape.has_text_frame and not shape.text.strip():
|
|
|
1556 |
if "title_color" in theme:
|
1557 |
p.font.color.rgb = theme["title_color"]
|
1558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1559 |
# Set content based on layout
|
1560 |
if layout == 'two-column':
|
1561 |
content = slide_info.get('content', [])
|
|
|
1565 |
|
1566 |
# Create left column
|
1567 |
left = Inches(0.5)
|
1568 |
+
top = Inches(1.5)
|
1569 |
width = prs.slide_width / 2 - Inches(1)
|
1570 |
+
height = prs.slide_height - Inches(2.5) # Leave space at bottom
|
1571 |
left_box = slide.shapes.add_textbox(left, top, width, height)
|
1572 |
left_tf = left_box.text_frame
|
1573 |
|
|
|
1593 |
elif layout != 'title-only': # Content slides
|
1594 |
# Create content area
|
1595 |
left = Inches(1)
|
1596 |
+
top = Inches(1.5)
|
1597 |
width = prs.slide_width - Inches(2)
|
1598 |
+
height = prs.slide_height - Inches(2.5) # Leave space at bottom
|
1599 |
content_box = slide.shapes.add_textbox(left, top, width, height)
|
1600 |
tf = content_box.text_frame
|
1601 |
|
|
|
1618 |
if hasattr(notes_slide, 'notes_text_frame'):
|
1619 |
notes_slide.notes_text_frame.text = slide_info['notes']
|
1620 |
|
1621 |
+
# Add question slides (one per question) with consistent theme
|
1622 |
if questions:
|
1623 |
+
# Add section header with consistent theme
|
1624 |
try:
|
1625 |
section_slide = prs.slides.add_slide(prs.slide_layouts[2]) # Section header layout
|
1626 |
except IndexError:
|
1627 |
section_slide = prs.slides.add_slide(prs.slide_layouts[0]) # Fallback to title slide
|
1628 |
|
1629 |
+
# Apply background if using custom theme
|
1630 |
+
if "template_path" not in theme:
|
1631 |
+
background = section_slide.background
|
1632 |
+
fill = background.fill
|
1633 |
+
fill.solid()
|
1634 |
+
fill.fore_color.rgb = theme["background"]
|
1635 |
+
|
1636 |
title_placeholder = section_slide.shapes.title if hasattr(section_slide.shapes, 'title') else None
|
1637 |
if title_placeholder is not None:
|
1638 |
title_placeholder.text = "Knowledge Check"
|