pptmaker_v2 / app.py
yashm's picture
Update app.py
50543ae verified
import streamlit as st
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from collections import OrderedDict
import os
# Define templates for different presentation types
templates = {
'Research Presentation': [
{"title": "Introduction", "content": ["Background", "Problem Statement", "Purpose"]},
{"title": "Literature Review", "content": ["Previous Studies", "Key Theories", "Gaps in Research"]},
{"title": "Methodology", "content": ["Research Design", "Data Collection", "Data Analysis"]},
{"title": "Results", "content": ["Data Presentation", "Statistical Analysis", "Interpretation"]},
{"title": "Discussion and Conclusion", "content": ["Summary of Findings", "Implications", "Recommendations for Future Research"]}
],
'Proposal Defense': [
{"title": "Introduction", "content": ["Background Context", "Problem Statement", "Research Questions", "Purpose and Significance"]},
{"title": "Literature Review", "content": ["Key Theories and Concepts", "Current State of Research", "Gaps in Literature"]},
{"title": "Research Design and Methodology", "content": ["Research Framework", "Data Collection Methods", "Analysis Plan", "Ethical Considerations"]},
{"title": "Expected Results", "content": ["Predicted Outcomes", "Potential Implications", "Limitations"]},
{"title": "Timeline", "content": ["Research Phases", "Key Milestones", "Completion Dates"]},
{"title": "Budget", "content": ["Estimated Costs", "Resource Allocation", "Justification"]},
{"title": "Conclusion", "content": ["Summary of Key Points", "Reiteration of Research Importance", "Next Steps"]},
{"title": "Questions and Discussion", "content": ["Anticipated Questions", "Potential Answers", "Further Clarifications"]}
],
'Project Update': [
{"title": "Overview", "content": ["Project Background", "Current Status", "Objectives"]},
{"title": "Progress", "content": ["Tasks Completed", "Milestones Achieved", "Challenges Faced"]},
{"title": "Next Steps", "content": ["Upcoming Tasks", "Milestones", "Deadlines"]},
{"title": "Risks and Issues", "content": ["Current Risks", "Mitigation Strategies", "Dependencies"]},
{"title": "Summary", "content": ["Key Takeaways", "Action Items", "Follow-up Dates"]}
],
'Thesis Defense': [
{"title": "Introduction", "content": ["Research Topic", "Research Questions", "Hypotheses"]},
{"title": "Methodology", "content": ["Research Design", "Data Collection Methods", "Data Analysis Procedures"]},
{"title": "Results", "content": ["Key Findings", "Data Interpretation", "Implications"]},
{"title": "Conclusion", "content": ["Summary of Findings", "Research Contributions", "Future Research"]},
{"title": "Questions and Discussion", "content": ["Common Questions", "Clarifications", "Further Explanations"]}
],
'Business Pitch': [
{"title": "Company Overview", "content": ["Company Background", "Mission and Vision", "Team"]},
{"title": "Market Analysis", "content": ["Industry Overview", "Target Market", "Competitor Analysis"]},
{"title": "Product/Service", "content": ["Product Description", "Unique Selling Points", "Value Proposition"]},
{"title": "Business Model", "content": ["Revenue Streams", "Pricing Strategy", "Sales Channels"]},
{"title": "Financial Plan", "content": ["Revenue Projections", "Cost Structure", "Funding Requirements"]},
{"title": "Conclusion", "content": ["Summary", "Call to Action", "Contact Information"]}
]
}
# Define themes
themes = {
"Corporate": {"font": "Arial", "font_size": 20, "color": "0000FF"},
"Casual": {"font": "Comic Sans MS", "font_size": 18, "color": "FF5733"},
# Add more themes as needed
}
# Function to create PowerPoint presentation based on user inputs
def create_presentation(title_slide_info, sections, theme_name, image_sections):
prs = Presentation()
# Apply theme
theme = themes[theme_name]
# Add a title slide
title_slide_layout = prs.slide_layouts[0]
title_slide = prs.slides.add_slide(title_slide_layout)
title = title_slide.shapes.title
subtitle = title_slide.placeholders[1]
title.text = title_slide_info['title']
subtitle.text = f"{title_slide_info['subtitle']}\n{title_slide_info['institution']}\n{title_slide_info['date']}"
# Add content slides based on sections and subsections
for section_title, section_info in sections.items():
for subsection_title, bullet_points in section_info.items():
slide = add_slide_with_layout(prs, 1, f"{section_title} - {subsection_title}", bullet_points)
# Check if this is the subsection where the image should be added
if section_title in image_sections and image_sections[section_title] == subsection_title:
image_path = os.path.join(os.getcwd(), uploaded_images[section_title].name)
with open(image_path, "wb") as f:
f.write(uploaded_images[section_title].getbuffer())
add_image_to_slide(slide, image_path)
# Save the presentation
filename = 'custom_presentation.pptx'
prs.save(filename)
return filename
# Function to style text
def style_text(paragraph, font_size, font_color):
run = paragraph.add_run()
font = run.font
font.size = Pt(font_size)
font.color.rgb = RGBColor.from_string(font_color)
# Function to add slide with custom layout
def add_slide_with_layout(prs, layout_index, title_text, content_points):
slide_layout = prs.slide_layouts[layout_index]
slide = prs.slides.add_slide(slide_layout)
title_placeholder = slide.shapes.title
body_placeholder = slide.placeholders[1]
title_placeholder.text = title_text
for point in content_points:
p = body_placeholder.text_frame.add_paragraph()
p.text = point
return slide
# Function to add image to a slide
def add_image_to_slide(slide, image_path):
slide.shapes.add_picture(image_path, Inches(1), Inches(1), width=Inches(5), height=Inches(3))
# Function to handle dynamic section addition
def add_new_section(section_counter):
new_section_title = f"Section {section_counter}"
st.session_state.sections[new_section_title] = OrderedDict({"Subsection": []})
st.session_state.section_counter += 1
# Function to handle dynamic subsection addition
def add_new_subsection(section_title):
new_subsection_title = f"Subsection {len(st.session_state.sections[section_title]) + 1}"
if new_subsection_title not in st.session_state.sections[section_title]:
st.session_state.sections[section_title][new_subsection_title] = []
# Streamlit UI setup
st.sidebar.title('Presentation Settings')
presentation_type = st.sidebar.selectbox('Select Presentation Type', list(templates.keys()))
# Reset sections when a new presentation type is selected
if 'last_presentation_type' not in st.session_state or st.session_state.last_presentation_type != presentation_type:
st.session_state.sections = OrderedDict()
st.session_state.section_counter = 1 # Counter for unique section names
for section in templates[presentation_type]:
st.session_state.sections[section['title']] = OrderedDict((content, []) for content in section['content'])
st.session_state.last_presentation_type = presentation_type # Update the last selected type
# Title slide configuration with expander
with st.sidebar.expander("Title Slide Options", expanded=False):
title_slide_info = {
'title': st.text_input("Title", "Your Presentation Title"),
'subtitle': st.text_input("Subtitle", "Your Name"),
'institution': st.text_input("Institution", "Your Institution"),
'date': st.text_input("Date", "Presentation Date")
}
# Theme selection
theme_name = st.sidebar.selectbox("Select Theme", list(themes.keys()))
# Option to add more sections dynamically
if st.sidebar.button("Add More Section"):
add_new_section(st.session_state.section_counter)
# Main page for sections and subsections configuration
st.title('Customize Your Presentation')
# Dictionary to keep track of which section/subsection should have an image
image_sections = {}
for section_title, subsections in list(st.session_state.sections.items()):
with st.expander(f"Section: {section_title}"):
# Edit section title
new_section_title = st.text_input(f"Edit Section Title:", value=section_title, key=f"section_title_{section_title}")
if new_section_title != section_title:
st.session_state.sections[new_section_title] = st.session_state.sections.pop(section_title)
section_title = new_section_title
for subsection_title, bullet_points in list(subsections.items()):
bullets = st.text_area(f"Subsection: {subsection_title} (Enter bullet points separated by newlines)",
value="\n".join(bullet_points),
height=150,
key=f"{section_title}_{subsection_title}").split('\n')
st.session_state.sections[section_title][subsection_title] = bullets
# Let the user choose if this is the subsection where the image should be added
add_image_here = st.checkbox(f"Add image to {subsection_title}?", key=f"checkbox_{section_title}_{subsection_title}")
if add_image_here:
image_sections[section_title] = subsection_title
# Add new subsection to the current section
if st.button(f"Add Subsection to {section_title}", key=f"add_subsection_{section_title}"):
add_new_subsection(section_title)
# Image upload for each section (images should only be uploaded if selected)
uploaded_images = {}
for section_title in st.session_state.sections:
if section_title in image_sections:
uploaded_image = st.file_uploader(f"Upload image for {section_title} (applied to subsection '{image_sections[section_title]}')", type=["png", "jpg", "jpeg"], key=f"image_{section_title}")
if uploaded_image is not None:
uploaded_images[section_title] = uploaded_image
# Generate and download presentation
if st.button('Generate Presentation'):
file_path = create_presentation(title_slide_info, st.session_state.sections, theme_name, image_sections)
with open(file_path, "rb") as file:
st.download_button(
label="Download Presentation",
data=file,
file_name='custom_presentation.pptx',
mime="application/vnd.openxmlformats-officedocument.presentationml.presentation"
)