YashMK89 commited on
Commit
eff08af
Β·
verified Β·
1 Parent(s): 1a4b73f

update ppt side formate

Browse files
Files changed (1) hide show
  1. pages/1_πŸ“Š_Text_to_PPT.py +190 -55
pages/1_πŸ“Š_Text_to_PPT.py CHANGED
@@ -1010,7 +1010,6 @@
1010
 
1011
 
1012
  ###################################################################################################################################################################
1013
-
1014
  import streamlit as st
1015
  import google.generativeai as genai
1016
  from pptx import Presentation
@@ -1025,6 +1024,9 @@ import re
1025
  import tempfile
1026
  import os
1027
  from PIL import Image
 
 
 
1028
 
1029
  # Load the API key securely from environment variable
1030
  api_key = os.getenv("GOOGLE_API_KEY")
@@ -1069,6 +1071,13 @@ DEFAULT_THEMES = {
1069
  }
1070
  }
1071
 
 
 
 
 
 
 
 
1072
  def hex_to_rgb(hex_color):
1073
  """Convert hex color to RGBColor"""
1074
  hex_color = hex_color.lstrip('#')
@@ -1128,8 +1137,12 @@ def extract_theme_from_pptx(uploaded_file):
1128
 
1129
  return theme
1130
 
1131
- def generate_slide_content(topic, slide_count):
1132
- model = genai.GenerativeModel('gemini-2.0-flash')
 
 
 
 
1133
  prompt = f"""Create a comprehensive presentation on '{topic}' with exactly {slide_count} slides.
1134
  For each slide, provide:
1135
  1. A clear title in [Title:] format
@@ -1200,7 +1213,7 @@ def generate_slide_content(topic, slide_count):
1200
  Begin the content generation now.
1201
  """
1202
 
1203
- response = model.generate_content(prompt)
1204
  return response.text
1205
 
1206
  def parse_slide_content(slide_text):
@@ -1433,7 +1446,7 @@ def create_answer_key_slide(prs, questions, theme):
1433
 
1434
  return slide
1435
 
1436
- def create_detailed_pptx(slides_data, questions, theme, branding_options=None):
1437
  """Create PowerPoint using the uploaded template"""
1438
  # Use the template if one was uploaded
1439
  if "template_path" in theme and os.path.exists(theme["template_path"]):
@@ -1441,9 +1454,10 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None):
1441
  else:
1442
  prs = Presentation()
1443
 
1444
- # Set widescreen layout (16:9 aspect ratio)
1445
- prs.slide_width = Inches(13.33)
1446
- prs.slide_height = Inches(7.5)
 
1447
 
1448
  # Layout mapping
1449
  layout_indices = {
@@ -1461,7 +1475,7 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None):
1461
  default_layout_idx = available_layouts.get('title-content', 0)
1462
 
1463
  # Create main slides
1464
- for slide_info in slides_data:
1465
  layout = slide_info.get('layout', 'title-content').lower()
1466
  layout_idx = available_layouts.get(layout, default_layout_idx)
1467
 
@@ -1580,6 +1594,53 @@ def create_detailed_pptx(slides_data, questions, theme, branding_options=None):
1580
 
1581
  return pptx_io
1582
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1583
  def main():
1584
  st.set_page_config(page_title="Advanced PPTX Generator", layout="wide")
1585
 
@@ -1590,6 +1651,18 @@ def main():
1590
  if 'custom_themes' not in st.session_state:
1591
  st.session_state.custom_themes = {}
1592
 
 
 
 
 
 
 
 
 
 
 
 
 
1593
  # Combine default and custom themes
1594
  ALL_THEMES = {**DEFAULT_THEMES, **st.session_state.custom_themes}
1595
  col1, col2 = st.columns([3, 1])
@@ -1648,6 +1721,14 @@ def main():
1648
  st.success("Theme extracted from template!")
1649
  else:
1650
  st.info("Please upload a PowerPoint file to extract its theme")
 
 
 
 
 
 
 
 
1651
 
1652
  with col2:
1653
  st.markdown("### Instructions")
@@ -1655,6 +1736,7 @@ def main():
1655
  st.markdown("2. Select slide count and theme")
1656
  st.markdown("3. Click 'Generate Presentation'")
1657
  st.markdown("4. Download your PowerPoint file")
 
1658
 
1659
  if st.button("Generate Presentation", type="primary", key="generate_btn"):
1660
  if not topic:
@@ -1662,53 +1744,106 @@ def main():
1662
  elif theme_option == "Example-Based Theme" and not uploaded_file:
1663
  st.warning("Please upload a PowerPoint template file first")
1664
  else:
1665
- with st.spinner(f"Creating {slide_count}-slide presentation about '{topic}'..."):
1666
- try:
1667
- slide_text = generate_slide_content(topic, slide_count)
1668
- slides_data, questionnaire, answer_key = parse_slide_content(slide_text)
1669
-
1670
- # Show slide overview with detailed content
1671
- with st.expander("Slide Overview (Detailed)"):
1672
- st.markdown(f"**Total Slides:** {len(slides_data)} content slides + {len(questionnaire)} question slides + 1 answer key slide")
1673
-
1674
- for i, slide in enumerate(slides_data, 1):
1675
- st.subheader(f"Slide {i}: {slide['title']}")
1676
- st.markdown("**Content:**")
1677
- for point in slide.get('content', []):
1678
- st.markdown(f"- {point}")
1679
- if slide.get('notes'):
1680
- st.markdown(f"**Notes:** {slide['notes']}")
1681
- st.markdown("---")
1682
-
1683
- if questionnaire:
1684
- st.subheader("Questionnaire")
1685
- st.markdown(f"**Total Questions:** {len(questionnaire)}")
1686
- for i, q in enumerate(questionnaire, 1):
1687
- st.subheader(f"Question {i}")
1688
- st.markdown(f"**{q['text']}**")
1689
- for j, opt in enumerate(q['options']):
1690
- st.markdown(f"{chr(65+j)}. {opt}")
1691
- st.markdown(f"*Correct: {q['correct']}*")
1692
- st.markdown("---")
1693
-
1694
- if answer_key:
1695
- st.subheader("Answer Key")
1696
- for i, ans in enumerate(answer_key, 1):
1697
- st.markdown(f"{i}. {ans}")
1698
-
1699
- pptx_file = create_detailed_pptx(slides_data, questionnaire, theme)
1700
-
1701
- st.success("Presentation generated successfully!")
1702
-
1703
- st.download_button(
1704
- label="Download PowerPoint",
1705
- data=pptx_file,
1706
- file_name=f"{topic.replace(' ', '_')}_presentation.pptx",
1707
- mime="application/vnd.openxmlformats-officedocument.presentationml.presentation"
1708
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
1709
 
1710
- except Exception as e:
1711
- st.error(f"An error occurred: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1712
 
1713
  if __name__ == "__main__":
1714
  main()
 
1010
 
1011
 
1012
  ###################################################################################################################################################################
 
1013
  import streamlit as st
1014
  import google.generativeai as genai
1015
  from pptx import Presentation
 
1024
  import tempfile
1025
  import os
1026
  from PIL import Image
1027
+ import time
1028
+ import json
1029
+ from hashlib import sha256
1030
 
1031
  # Load the API key securely from environment variable
1032
  api_key = os.getenv("GOOGLE_API_KEY")
 
1071
  }
1072
  }
1073
 
1074
+ # PowerPoint compatibility options
1075
+ PPT_VERSIONS = {
1076
+ "Modern (2013+)": {"aspect_ratio": (13.33, 7.5)},
1077
+ "Standard (2007-2013)": {"aspect_ratio": (10, 7.5)},
1078
+ "Legacy (2003)": {"aspect_ratio": (10, 7.5)}
1079
+ }
1080
+
1081
  def hex_to_rgb(hex_color):
1082
  """Convert hex color to RGBColor"""
1083
  hex_color = hex_color.lstrip('#')
 
1137
 
1138
  return theme
1139
 
1140
+ @st.cache_data(ttl=3600, show_spinner="Generating slide content...")
1141
+ def generate_slide_content(topic, slide_count, _model=None):
1142
+ """Generate slide content with caching"""
1143
+ if _model is None:
1144
+ _model = genai.GenerativeModel('gemini-2.0-flash')
1145
+
1146
  prompt = f"""Create a comprehensive presentation on '{topic}' with exactly {slide_count} slides.
1147
  For each slide, provide:
1148
  1. A clear title in [Title:] format
 
1213
  Begin the content generation now.
1214
  """
1215
 
1216
+ response = _model.generate_content(prompt)
1217
  return response.text
1218
 
1219
  def parse_slide_content(slide_text):
 
1446
 
1447
  return slide
1448
 
1449
+ def create_detailed_pptx(slides_data, questions, theme, branding_options=None, ppt_version="Modern (2013+)"):
1450
  """Create PowerPoint using the uploaded template"""
1451
  # Use the template if one was uploaded
1452
  if "template_path" in theme and os.path.exists(theme["template_path"]):
 
1454
  else:
1455
  prs = Presentation()
1456
 
1457
+ # Set aspect ratio based on selected version
1458
+ aspect_ratio = PPT_VERSIONS[ppt_version]["aspect_ratio"]
1459
+ prs.slide_width = Inches(aspect_ratio[0])
1460
+ prs.slide_height = Inches(aspect_ratio[1])
1461
 
1462
  # Layout mapping
1463
  layout_indices = {
 
1475
  default_layout_idx = available_layouts.get('title-content', 0)
1476
 
1477
  # Create main slides
1478
+ for i, slide_info in enumerate(slides_data, 1):
1479
  layout = slide_info.get('layout', 'title-content').lower()
1480
  layout_idx = available_layouts.get(layout, default_layout_idx)
1481
 
 
1594
 
1595
  return pptx_io
1596
 
1597
+ def regenerate_slide(slide_index, topic, slide_count, theme, ppt_version):
1598
+ """Regenerate a specific slide using AI"""
1599
+ model = genai.GenerativeModel('gemini-2.0-flash')
1600
+ prompt = f"""We are creating a presentation on '{topic}' with {slide_count} slides.
1601
+ Please regenerate only slide number {slide_index+1} with the same structure as the others.
1602
+ The slide should have:
1603
+ - A clear title in [Title:] format
1604
+ - 3-5 detailed bullet points in [Content:] format
1605
+ - Optional speaker notes in [Notes:] format
1606
+ - Layout suggestion in [Layout:] format
1607
+
1608
+ Format:
1609
+ [Title:] Slide Title
1610
+ [Layout:] layout-type
1611
+ [Content:]
1612
+ - Point 1
1613
+ - Point 2
1614
+ [Notes:] Optional notes
1615
+
1616
+ Make sure the content is relevant to the overall topic and flows with the presentation.
1617
+ """
1618
+
1619
+ response = model.generate_content(prompt)
1620
+ new_slide_text = response.text
1621
+
1622
+ # Parse the new slide
1623
+ new_slide = {'title': '', 'content': [], 'notes': '', 'layout': 'title-content'}
1624
+ for line in new_slide_text.split('\n'):
1625
+ line = line.strip()
1626
+ if line.startswith('[Title:]'):
1627
+ new_slide['title'] = line.replace('[Title:]', '').strip()
1628
+ elif line.startswith('[Content:]'):
1629
+ pass # Content follows on subsequent lines
1630
+ elif line.startswith('[Notes:]'):
1631
+ new_slide['notes'] = line.replace('[Notes:]', '').strip()
1632
+ elif line.startswith('[Layout:]'):
1633
+ layout = line.replace('[Layout:]', '').strip().lower()
1634
+ valid_layouts = ['title-only', 'title-content', 'two-column', 'section-header']
1635
+ new_slide['layout'] = layout if layout in valid_layouts else 'title-content'
1636
+ elif line.startswith('-'):
1637
+ point = line[1:].strip()
1638
+ if ':' in point:
1639
+ point = point.split(':')[0].strip()
1640
+ new_slide['content'].append(point)
1641
+
1642
+ return new_slide
1643
+
1644
  def main():
1645
  st.set_page_config(page_title="Advanced PPTX Generator", layout="wide")
1646
 
 
1651
  if 'custom_themes' not in st.session_state:
1652
  st.session_state.custom_themes = {}
1653
 
1654
+ # Initialize session state for presentation data
1655
+ if 'slides_data' not in st.session_state:
1656
+ st.session_state.slides_data = []
1657
+ if 'questionnaire' not in st.session_state:
1658
+ st.session_state.questionnaire = []
1659
+ if 'answer_key' not in st.session_state:
1660
+ st.session_state.answer_key = []
1661
+ if 'pptx_file' not in st.session_state:
1662
+ st.session_state.pptx_file = None
1663
+ if 'regenerate_map' not in st.session_state:
1664
+ st.session_state.regenerate_map = {}
1665
+
1666
  # Combine default and custom themes
1667
  ALL_THEMES = {**DEFAULT_THEMES, **st.session_state.custom_themes}
1668
  col1, col2 = st.columns([3, 1])
 
1721
  st.success("Theme extracted from template!")
1722
  else:
1723
  st.info("Please upload a PowerPoint file to extract its theme")
1724
+
1725
+ # PowerPoint version compatibility
1726
+ ppt_version = st.selectbox(
1727
+ "PowerPoint Version Compatibility:",
1728
+ list(PPT_VERSIONS.keys()),
1729
+ index=0
1730
+ )
1731
+ st.caption("Modern (2013+): Widescreen (16:9)\nStandard (2007-2013): Standard (4:3)\nLegacy (2003): Standard (4:3)")
1732
 
1733
  with col2:
1734
  st.markdown("### Instructions")
 
1736
  st.markdown("2. Select slide count and theme")
1737
  st.markdown("3. Click 'Generate Presentation'")
1738
  st.markdown("4. Download your PowerPoint file")
1739
+ st.markdown("5. Use 'Regenerate' buttons to improve specific slides")
1740
 
1741
  if st.button("Generate Presentation", type="primary", key="generate_btn"):
1742
  if not topic:
 
1744
  elif theme_option == "Example-Based Theme" and not uploaded_file:
1745
  st.warning("Please upload a PowerPoint template file first")
1746
  else:
1747
+ progress_bar = st.progress(0)
1748
+ status_text = st.empty()
1749
+
1750
+ # Generate slide content
1751
+ status_text.text("Generating content with AI...")
1752
+ progress_bar.progress(20)
1753
+ model = genai.GenerativeModel('gemini-2.0-flash')
1754
+ slide_text = generate_slide_content(topic, slide_count, _model=model)
1755
+
1756
+ # Parse slide content
1757
+ status_text.text("Parsing slide content...")
1758
+ progress_bar.progress(40)
1759
+ slides_data, questionnaire, answer_key = parse_slide_content(slide_text)
1760
+
1761
+ # Store in session state
1762
+ st.session_state.slides_data = slides_data
1763
+ st.session_state.questionnaire = questionnaire
1764
+ st.session_state.answer_key = answer_key
1765
+ st.session_state.regenerate_map = {i: False for i in range(len(slides_data))}
1766
+
1767
+ # Create PowerPoint
1768
+ status_text.text("Creating PowerPoint file...")
1769
+ progress_bar.progress(70)
1770
+ pptx_file = create_detailed_pptx(slides_data, questionnaire, theme, ppt_version=ppt_version)
1771
+ st.session_state.pptx_file = pptx_file
1772
+
1773
+ progress_bar.progress(100)
1774
+ status_text.text("Done!")
1775
+ time.sleep(0.5)
1776
+ progress_bar.empty()
1777
+ status_text.empty()
1778
+
1779
+ st.success("Presentation generated successfully!")
1780
+
1781
+ # Show slide overview with regeneration options
1782
+ if st.session_state.slides_data:
1783
+ with st.expander("Slide Overview (Click to Expand)", expanded=True):
1784
+ st.markdown(f"**Total Slides:** {len(st.session_state.slides_data)} content slides + "
1785
+ f"{len(st.session_state.questionnaire)} question slides + 1 answer key slide")
1786
+
1787
+ for i, slide in enumerate(st.session_state.slides_data):
1788
+ col1, col2 = st.columns([4, 1])
1789
+ with col1:
1790
+ st.subheader(f"Slide {i+1}: {slide['title']}")
1791
+ st.markdown("**Content:**")
1792
+ for point in slide.get('content', []):
1793
+ st.markdown(f"- {point}")
1794
+ if slide.get('notes'):
1795
+ st.markdown(f"**Notes:** {slide['notes']}")
1796
+
1797
+ with col2:
1798
+ if st.button(f"Regenerate", key=f"reg_{i}"):
1799
+ with st.spinner(f"Regenerating slide {i+1}..."):
1800
+ new_slide = regenerate_slide(i, topic, slide_count, theme, ppt_version)
1801
+ st.session_state.slides_data[i] = new_slide
1802
+ st.session_state.regenerate_map[i] = True
1803
+ st.rerun()
1804
 
1805
+ # Show regeneration status
1806
+ if st.session_state.regenerate_map.get(i, False):
1807
+ st.success("Regenerated!")
1808
+
1809
+ st.markdown("---")
1810
+
1811
+ if st.session_state.questionnaire:
1812
+ st.subheader("Questionnaire")
1813
+ st.markdown(f"**Total Questions:** {len(st.session_state.questionnaire)}")
1814
+ for i, q in enumerate(st.session_state.questionnaire, 1):
1815
+ st.subheader(f"Question {i}")
1816
+ st.markdown(f"**{q['text']}**")
1817
+ for j, opt in enumerate(q['options']):
1818
+ st.markdown(f"{chr(65+j)}. {opt}")
1819
+ st.markdown(f"*Correct: {q['correct']}*")
1820
+ st.markdown("---")
1821
+
1822
+ if st.session_state.answer_key:
1823
+ st.subheader("Answer Key")
1824
+ for i, ans in enumerate(st.session_state.answer_key, 1):
1825
+ st.markdown(f"{i}. {ans}")
1826
+
1827
+ # Rebuild PPTX if any slides were regenerated
1828
+ if any(st.session_state.regenerate_map.values()):
1829
+ with st.spinner("Updating presentation with regenerated slides..."):
1830
+ pptx_file = create_detailed_pptx(
1831
+ st.session_state.slides_data,
1832
+ st.session_state.questionnaire,
1833
+ theme,
1834
+ ppt_version=ppt_version
1835
+ )
1836
+ st.session_state.pptx_file = pptx_file
1837
+ st.success("Presentation updated with regenerated slides!")
1838
+
1839
+ # Download button
1840
+ if st.session_state.pptx_file:
1841
+ st.download_button(
1842
+ label="Download PowerPoint",
1843
+ data=st.session_state.pptx_file,
1844
+ file_name=f"{topic.replace(' ', '_')}_presentation.pptx",
1845
+ mime="application/vnd.openxmlformats-officedocument.presentationml.presentation"
1846
+ )
1847
 
1848
  if __name__ == "__main__":
1849
  main()