Initial commit: organize Primary song slides repo
One folder per song under songs/. Tracks PPTX slide files and Python generation scripts. PDFs and videos excluded (too large for git; originals are in Google Drive). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
from pptx import Presentation
|
||||
from pptx.util import Inches, Pt
|
||||
from pptx.dml.color import RGBColor
|
||||
from pptx.enum.text import PP_ALIGN
|
||||
from pptx.oxml.ns import qn
|
||||
from lxml import etree
|
||||
|
||||
OUT_PATH = r"C:\Users\jhodgkin\Documents\dev\primary-song-slides\MyCountryTisOfThee.pptx"
|
||||
|
||||
SLIDE_W = Inches(13.333)
|
||||
SLIDE_H = Inches(7.5)
|
||||
|
||||
NAVY = RGBColor(0x0D, 0x27, 0x6D)
|
||||
GOLD = RGBColor(0xF5, 0xC5, 0x18)
|
||||
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
|
||||
|
||||
VERSES = [
|
||||
(
|
||||
"Verse 1",
|
||||
"My country, 'tis of thee,\n"
|
||||
"Sweet land of liberty,\n"
|
||||
"Of thee I sing;\n"
|
||||
"Land where my fathers died,\n"
|
||||
"Land of the pilgrims' pride,\n"
|
||||
"From ev'ry mountainside\n"
|
||||
"Let freedom ring!"
|
||||
),
|
||||
(
|
||||
"Verse 4",
|
||||
"Our fathers' God, to thee,\n"
|
||||
"Author of liberty,\n"
|
||||
"To thee we sing;\n"
|
||||
"Long may our land be bright\n"
|
||||
"With freedom's holy light.\n"
|
||||
"Protect us by thy might,\n"
|
||||
"Great God, our King!"
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def set_background_color(slide, color):
|
||||
"""Fill slide background with a solid color."""
|
||||
bg = slide.background
|
||||
fill = bg.fill
|
||||
fill.solid()
|
||||
fill.fore_color.rgb = color
|
||||
|
||||
|
||||
def add_text_paragraph(tf, text, font_size, color, bold=False, space_before=0):
|
||||
p = tf.add_paragraph()
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
if space_before:
|
||||
pPr = p._pPr
|
||||
if pPr is None:
|
||||
pPr = p._p.get_or_add_pPr()
|
||||
pPr.set(qn("a:spcBef"), None)
|
||||
spcBef = etree.SubElement(pPr, qn("a:spcBef"))
|
||||
spcPts = etree.SubElement(spcBef, qn("a:spcPts"))
|
||||
spcPts.set("val", str(space_before * 100))
|
||||
run = p.add_run()
|
||||
run.text = text
|
||||
run.font.size = font_size
|
||||
run.font.color.rgb = color
|
||||
run.font.bold = bold
|
||||
return p
|
||||
|
||||
|
||||
def add_slide(prs, blank_layout, verse_label, verse_text):
|
||||
slide = prs.slides.add_slide(blank_layout)
|
||||
set_background_color(slide, NAVY)
|
||||
|
||||
# Gold decorative rule above title
|
||||
rule_top = Inches(0.55)
|
||||
rule_h = Inches(0.06)
|
||||
rule = slide.shapes.add_shape(
|
||||
1, # MSO_SHAPE_TYPE.RECTANGLE
|
||||
Inches(1.5), rule_top, SLIDE_W - Inches(3.0), rule_h
|
||||
)
|
||||
rule.fill.solid()
|
||||
rule.fill.fore_color.rgb = GOLD
|
||||
rule.line.fill.background()
|
||||
|
||||
# Song title
|
||||
title_box = slide.shapes.add_textbox(Inches(0.5), Inches(0.65), SLIDE_W - Inches(1.0), Inches(0.85))
|
||||
tf = title_box.text_frame
|
||||
tf.word_wrap = False
|
||||
p = tf.paragraphs[0]
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
run = p.add_run()
|
||||
run.text = "My Country, 'Tis of Thee"
|
||||
run.font.size = Pt(36)
|
||||
run.font.color.rgb = GOLD
|
||||
run.font.bold = True
|
||||
|
||||
# Verse label
|
||||
label_box = slide.shapes.add_textbox(Inches(0.5), Inches(1.45), SLIDE_W - Inches(1.0), Inches(0.5))
|
||||
tf2 = label_box.text_frame
|
||||
p2 = tf2.paragraphs[0]
|
||||
p2.alignment = PP_ALIGN.CENTER
|
||||
run2 = p2.add_run()
|
||||
run2.text = verse_label
|
||||
run2.font.size = Pt(22)
|
||||
run2.font.color.rgb = WHITE
|
||||
run2.font.bold = False
|
||||
run2.font.italic = True
|
||||
|
||||
# Gold rule below label
|
||||
rule2 = slide.shapes.add_shape(
|
||||
1,
|
||||
Inches(1.5), Inches(1.95), SLIDE_W - Inches(3.0), rule_h
|
||||
)
|
||||
rule2.fill.solid()
|
||||
rule2.fill.fore_color.rgb = GOLD
|
||||
rule2.line.fill.background()
|
||||
|
||||
# Verse lyrics
|
||||
lyric_box = slide.shapes.add_textbox(Inches(0.5), Inches(2.1), SLIDE_W - Inches(1.0), Inches(5.0))
|
||||
tf3 = lyric_box.text_frame
|
||||
tf3.word_wrap = True
|
||||
lines = verse_text.split("\n")
|
||||
for i, line in enumerate(lines):
|
||||
if i == 0:
|
||||
p = tf3.paragraphs[0]
|
||||
else:
|
||||
p = tf3.add_paragraph()
|
||||
p.alignment = PP_ALIGN.CENTER
|
||||
run = p.add_run()
|
||||
run.text = line
|
||||
run.font.size = Pt(40)
|
||||
run.font.color.rgb = WHITE
|
||||
run.font.bold = False
|
||||
|
||||
print(f" Added: {verse_label}")
|
||||
|
||||
|
||||
def main():
|
||||
prs = Presentation()
|
||||
prs.slide_width = SLIDE_W
|
||||
prs.slide_height = SLIDE_H
|
||||
blank_layout = prs.slide_layouts[6]
|
||||
|
||||
for label, text in VERSES:
|
||||
add_slide(prs, blank_layout, label, text)
|
||||
|
||||
prs.save(OUT_PATH)
|
||||
print(f"\nSaved: {OUT_PATH} ({len(VERSES)} slides)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user