Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -29,7 +29,7 @@ def delete_asset(path):
|
|
| 29 |
st.error(f"Error deleting file: {e}")
|
| 30 |
st.rerun()
|
| 31 |
|
| 32 |
-
# ---
|
| 33 |
def generate_combined_pdf(selected_asset_paths):
|
| 34 |
"""Generates a single PDF from selected markdown and image file paths."""
|
| 35 |
buf = io.BytesIO()
|
|
@@ -76,7 +76,7 @@ def generate_combined_pdf(selected_asset_paths):
|
|
| 76 |
c.setFont(font_family, font_size)
|
| 77 |
|
| 78 |
# Estimate line height and character width for text wrapping
|
| 79 |
-
# ReportLab
|
| 80 |
# A common approximation for average character width is font_size * 0.6
|
| 81 |
avg_char_width_points = font_size * 0.6
|
| 82 |
# wrap_width is the number of characters that fit in one line of a column
|
|
@@ -176,6 +176,7 @@ def generate_combined_pdf(selected_asset_paths):
|
|
| 176 |
c.showPage() # Start a new page for this image
|
| 177 |
|
| 178 |
# Draw the image onto the current page
|
|
|
|
| 179 |
c.drawImage(path, pos_x, pos_y, width=draw_w, height=draw_h, preserveAspectRatio=True)
|
| 180 |
|
| 181 |
except Exception as e:
|
|
@@ -190,7 +191,7 @@ def generate_combined_pdf(selected_asset_paths):
|
|
| 190 |
c.save() # Finalize the PDF
|
| 191 |
buf.seek(0) # Rewind the buffer to the beginning
|
| 192 |
return buf.getvalue() # Return the PDF bytes
|
| 193 |
-
# --- End of
|
| 194 |
|
| 195 |
|
| 196 |
# Tabs setup
|
|
@@ -371,15 +372,17 @@ with tab1:
|
|
| 371 |
|
| 372 |
st.markdown("---")
|
| 373 |
st.subheader("📂 Available Assets")
|
| 374 |
-
st.markdown("Select assets below
|
| 375 |
|
| 376 |
# Get all files and filter out unwanted ones
|
| 377 |
all_assets = glob.glob("*.*")
|
|
|
|
| 378 |
excluded_extensions = ['.py', '.ttf']
|
| 379 |
-
excluded_files = ['README.md', 'index.html']
|
| 380 |
|
| 381 |
assets = sorted([
|
| 382 |
a for a in all_assets
|
|
|
|
| 383 |
if not (a.lower().endswith(tuple(excluded_extensions)) or os.path.basename(a) in excluded_files)
|
| 384 |
])
|
| 385 |
|
|
@@ -430,24 +433,29 @@ with tab1:
|
|
| 430 |
# Audio player takes up too much space here, just offer download
|
| 431 |
with open(a, 'rb') as mp3:
|
| 432 |
cols[2].download_button("📥", data=mp3, file_name=a, mime="audio/mpeg", key=f"download_{a}")
|
| 433 |
-
#
|
| 434 |
-
elif ext in ['
|
| 435 |
-
|
|
|
|
|
|
|
|
|
|
| 436 |
with open(a, 'rb') as img_file:
|
| 437 |
cols[2].download_button("⬇️", data=img_file.read(), file_name=a, mime=f"image/{ext}", key=f"download_{a}")
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
# Handle other file types - maybe just offer download
|
| 443 |
else:
|
| 444 |
with open(a, 'rb') as other_file:
|
| 445 |
cols[2].download_button("⬇️", data=other_file.read(), file_name=a, key=f"download_{a}") # Mime type is guessed by streamlit
|
| 446 |
|
|
|
|
| 447 |
# Delete button in the fourth column
|
| 448 |
cols[3].button("🗑️", key=f"del_{a}", on_click=delete_asset, args=(a,))
|
| 449 |
except Exception as e:
|
| 450 |
-
|
|
|
|
| 451 |
|
| 452 |
|
| 453 |
# --- Combined PDF Generation Button ---
|
|
@@ -477,11 +485,62 @@ with tab1:
|
|
| 477 |
)
|
| 478 |
st.success("Combined PDF generated!")
|
| 479 |
else:
|
| 480 |
-
|
|
|
|
| 481 |
|
| 482 |
except Exception as e:
|
| 483 |
st.error(f"An unexpected error occurred during PDF generation: {e}")
|
| 484 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 485 |
|
| 486 |
with tab2:
|
| 487 |
st.header("🧪 Python Code Executor & Demo")
|
|
|
|
| 29 |
st.error(f"Error deleting file: {e}")
|
| 30 |
st.rerun()
|
| 31 |
|
| 32 |
+
# --- Function to Generate Combined PDF ---
|
| 33 |
def generate_combined_pdf(selected_asset_paths):
|
| 34 |
"""Generates a single PDF from selected markdown and image file paths."""
|
| 35 |
buf = io.BytesIO()
|
|
|
|
| 76 |
c.setFont(font_family, font_size)
|
| 77 |
|
| 78 |
# Estimate line height and character width for text wrapping
|
| 79 |
+
# ReportLab measures in points. Approximating char width for wrapping.
|
| 80 |
# A common approximation for average character width is font_size * 0.6
|
| 81 |
avg_char_width_points = font_size * 0.6
|
| 82 |
# wrap_width is the number of characters that fit in one line of a column
|
|
|
|
| 176 |
c.showPage() # Start a new page for this image
|
| 177 |
|
| 178 |
# Draw the image onto the current page
|
| 179 |
+
# Use the path directly with c.drawImage for files on disk
|
| 180 |
c.drawImage(path, pos_x, pos_y, width=draw_w, height=draw_h, preserveAspectRatio=True)
|
| 181 |
|
| 182 |
except Exception as e:
|
|
|
|
| 191 |
c.save() # Finalize the PDF
|
| 192 |
buf.seek(0) # Rewind the buffer to the beginning
|
| 193 |
return buf.getvalue() # Return the PDF bytes
|
| 194 |
+
# --- End of Combined PDF Function ---
|
| 195 |
|
| 196 |
|
| 197 |
# Tabs setup
|
|
|
|
| 372 |
|
| 373 |
st.markdown("---")
|
| 374 |
st.subheader("📂 Available Assets")
|
| 375 |
+
st.markdown("Select assets below to include in a combined PDF.")
|
| 376 |
|
| 377 |
# Get all files and filter out unwanted ones
|
| 378 |
all_assets = glob.glob("*.*")
|
| 379 |
+
# Removed '.txt' from excluded extensions
|
| 380 |
excluded_extensions = ['.py', '.ttf']
|
| 381 |
+
excluded_files = ['README.md', 'index.html']
|
| 382 |
|
| 383 |
assets = sorted([
|
| 384 |
a for a in all_assets
|
| 385 |
+
# Check if extension is in excluded list OR if the full name is in excluded files
|
| 386 |
if not (a.lower().endswith(tuple(excluded_extensions)) or os.path.basename(a) in excluded_files)
|
| 387 |
])
|
| 388 |
|
|
|
|
| 433 |
# Audio player takes up too much space here, just offer download
|
| 434 |
with open(a, 'rb') as mp3:
|
| 435 |
cols[2].download_button("📥", data=mp3, file_name=a, mime="audio/mpeg", key=f"download_{a}")
|
| 436 |
+
# Offer download for common text files like txt, csv etc.
|
| 437 |
+
elif ext in ['md', 'txt', 'csv', 'json', 'xml', 'log']:
|
| 438 |
+
with open(a, 'r', encoding='utf-8') as text_file:
|
| 439 |
+
cols[2].download_button("⬇️", data=text_file.read(), file_name=a, mime="text/plain", key=f"download_{a}")
|
| 440 |
+
# Offer download for common image files
|
| 441 |
+
elif ext in ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff']:
|
| 442 |
with open(a, 'rb') as img_file:
|
| 443 |
cols[2].download_button("⬇️", data=img_file.read(), file_name=a, mime=f"image/{ext}", key=f"download_{a}")
|
| 444 |
+
# Offer download for common video files (Streamlit doesn't have easy preview here)
|
| 445 |
+
elif ext in ['mp4', 'webm', 'ogg', 'avi', 'mov']:
|
| 446 |
+
with open(a, 'rb') as video_file:
|
| 447 |
+
cols[2].download_button("⬇️", data=video_file.read(), file_name=a, mime=f"video/{ext}", key=f"download_{a}")
|
| 448 |
+
# Handle other file types - maybe just offer download with guessed mime
|
| 449 |
else:
|
| 450 |
with open(a, 'rb') as other_file:
|
| 451 |
cols[2].download_button("⬇️", data=other_file.read(), file_name=a, key=f"download_{a}") # Mime type is guessed by streamlit
|
| 452 |
|
| 453 |
+
|
| 454 |
# Delete button in the fourth column
|
| 455 |
cols[3].button("🗑️", key=f"del_{a}", on_click=delete_asset, args=(a,))
|
| 456 |
except Exception as e:
|
| 457 |
+
# Display error next to the file if handling fails
|
| 458 |
+
cols[3].error(f"Error: {e}")
|
| 459 |
|
| 460 |
|
| 461 |
# --- Combined PDF Generation Button ---
|
|
|
|
| 485 |
)
|
| 486 |
st.success("Combined PDF generated!")
|
| 487 |
else:
|
| 488 |
+
# This case might happen if selected files couldn't be read/processed
|
| 489 |
+
st.warning("Generated PDF is empty. Check selected files or console for errors.")
|
| 490 |
|
| 491 |
except Exception as e:
|
| 492 |
st.error(f"An unexpected error occurred during PDF generation: {e}")
|
| 493 |
|
| 494 |
+
# --- Image Gallery ---
|
| 495 |
+
st.markdown("---")
|
| 496 |
+
st.subheader("🖼️ Image Gallery")
|
| 497 |
+
# Find common image file types
|
| 498 |
+
image_files = sorted(glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg") + glob.glob("*.gif") + glob.glob("*.bmp") + glob.glob("*.tiff"))
|
| 499 |
+
|
| 500 |
+
if not image_files:
|
| 501 |
+
st.info("No image files found in the directory.")
|
| 502 |
+
else:
|
| 503 |
+
# Slider to control the number of columns in the gallery
|
| 504 |
+
image_cols = st.slider("Image Gallery Columns", min_value=1, max_value=10, value=5)
|
| 505 |
+
# Ensure image_cols is at least 1
|
| 506 |
+
image_cols = max(1, image_cols)
|
| 507 |
+
|
| 508 |
+
# Display images in columns
|
| 509 |
+
cols = st.columns(image_cols)
|
| 510 |
+
for idx, image_file in enumerate(image_files):
|
| 511 |
+
with cols[idx % image_cols]: # Cycle through columns
|
| 512 |
+
try:
|
| 513 |
+
img = Image.open(image_file)
|
| 514 |
+
st.image(img, caption=os.path.basename(image_file), use_container_width=True)
|
| 515 |
+
except Exception as e:
|
| 516 |
+
st.warning(f"Could not display image {image_file}: {e}")
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
# --- Video Gallery ---
|
| 520 |
+
st.markdown("---")
|
| 521 |
+
st.subheader("🎥 Video Gallery")
|
| 522 |
+
# Find common video file types
|
| 523 |
+
video_files = sorted(glob.glob("*.mp4") + glob.glob("*.webm") + glob.glob("*.ogg") + glob.glob("*.avi") + glob.glob("*.mov"))
|
| 524 |
+
|
| 525 |
+
if not video_files:
|
| 526 |
+
st.info("No video files found in the directory.")
|
| 527 |
+
else:
|
| 528 |
+
# Slider to control the number of columns in the gallery
|
| 529 |
+
video_cols = st.slider("Video Gallery Columns", min_value=1, max_value=5, value=3)
|
| 530 |
+
# Ensure video_cols is at least 1
|
| 531 |
+
video_cols = max(1, video_cols)
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
# Display videos in columns
|
| 535 |
+
cols = st.columns(video_cols)
|
| 536 |
+
for idx, video_file in enumerate(video_files):
|
| 537 |
+
with cols[idx % video_cols]: # Cycle through columns
|
| 538 |
+
try:
|
| 539 |
+
# Streamlit's built-in video player is simpler than custom HTML
|
| 540 |
+
st.video(video_file, caption=os.path.basename(video_file))
|
| 541 |
+
except Exception as e:
|
| 542 |
+
st.warning(f"Could not display video {video_file}: {e}")
|
| 543 |
+
|
| 544 |
|
| 545 |
with tab2:
|
| 546 |
st.header("🧪 Python Code Executor & Demo")
|