Update app.py
Browse files
app.py
CHANGED
@@ -672,48 +672,108 @@ def make_image_sized_pdf(sources):
|
|
672 |
return None
|
673 |
|
674 |
|
675 |
-
|
676 |
-
# --- Sidebar Gallery Update Function (Keep from previous) --------
|
677 |
def update_gallery():
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
689 |
try:
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
716 |
|
|
|
717 |
|
718 |
# --- UI Elements -----------------------------------------
|
719 |
|
@@ -881,7 +941,7 @@ with tabs[0]:
|
|
881 |
st.image(Image.open(scan_name), caption=f"Scanned: {scan_name}", use_container_width=True)
|
882 |
if scan_name not in st.session_state['layout_snapshots']: st.session_state['layout_snapshots'].append(scan_name)
|
883 |
st.success(f"Scan saved as {scan_name}")
|
884 |
-
update_gallery();
|
885 |
except Exception as e: st.error(f"Failed to save scan: {e}"); logger.error(f"Failed to save camera scan {scan_name}: {e}")
|
886 |
|
887 |
layout_uploads = st.file_uploader("๐ Upload PNG/JPG Images for Layout PDF", type=["png","jpg","jpeg"], accept_multiple_files=True, key="layout_uploader")
|
@@ -959,7 +1019,7 @@ with tabs[1]:
|
|
959 |
try:
|
960 |
with open(filename, "wb") as f: f.write(cam0_img.getvalue())
|
961 |
st.session_state['cam0_file'] = filename; st.session_state['history'].append(f"Snapshot from Cam 0: {filename}"); st.image(Image.open(filename), caption="Camera 0 Snap", use_container_width=True); logger.info(f"Saved snapshot from Camera 0: {filename}"); st.success(f"Saved {filename}")
|
962 |
-
update_gallery();
|
963 |
except Exception as e:
|
964 |
st.error(f"Failed to save Cam 0 snap: {e}"); logger.error(f"Failed to save Cam 0 snap {filename}: {e}")
|
965 |
with cols[1]:
|
@@ -974,7 +1034,7 @@ with tabs[1]:
|
|
974 |
try:
|
975 |
with open(filename, "wb") as f: f.write(cam1_img.getvalue())
|
976 |
st.session_state['cam1_file'] = filename; st.session_state['history'].append(f"Snapshot from Cam 1: {filename}"); st.image(Image.open(filename), caption="Camera 1 Snap", use_container_width=True); logger.info(f"Saved snapshot from Camera 1: {filename}"); st.success(f"Saved {filename}")
|
977 |
-
update_gallery();
|
978 |
except Exception as e: st.error(f"Failed to save Cam 1 snap: {e}"); logger.error(f"Failed to save Cam 1 snap {filename}: {e}")
|
979 |
|
980 |
|
@@ -999,7 +1059,7 @@ with tabs[2]:
|
|
999 |
if download_pdf(url, output_path): st.session_state['downloaded_pdfs'][url] = output_path; logger.info(f"Downloaded PDF from {url} to {output_path}"); st.session_state['history'].append(f"Downloaded PDF: {output_path}"); st.session_state['asset_checkboxes'][output_path] = False; download_count += 1; existing_pdfs.append(output_path)
|
1000 |
else: st.error(f"Failed to download: {url}")
|
1001 |
status_text.success(f"Download process complete! Successfully downloaded {download_count} new PDFs.")
|
1002 |
-
if download_count > 0: update_gallery();
|
1003 |
|
1004 |
st.subheader("Create Snapshots from Gallery PDFs")
|
1005 |
snapshot_mode = st.selectbox("Snapshot Mode", ["First Page (High-Res)", "First Two Pages (High-Res)", "All Pages (High-Res)", "First Page (Low-Res Preview)"], key="pdf_snapshot_mode")
|
@@ -1019,7 +1079,7 @@ with tabs[2]:
|
|
1019 |
st.write(f"Snapshots for {os.path.basename(pdf_path)}:"); cols = st.columns(3)
|
1020 |
for i, snap_path in enumerate(new_snapshots):
|
1021 |
with cols[i % 3]: st.image(Image.open(snap_path), caption=os.path.basename(snap_path), use_container_width=True); st.session_state['asset_checkboxes'][snap_path] = False # Add to gallery
|
1022 |
-
if total_snapshots_generated > 0: st.success(f"Generated {total_snapshots_generated} snapshots from {snapshot_count} PDFs."); update_gallery();
|
1023 |
else: st.warning("No snapshots were generated. Check logs or PDF files.")
|
1024 |
|
1025 |
# --- Tab 4: Build Titan (Local Models) ---
|
@@ -1162,8 +1222,6 @@ with tabs[3]:
|
|
1162 |
finally:
|
1163 |
progress_bar_build.progress(1.0)
|
1164 |
status_text_build.empty()
|
1165 |
-
# Update sidebar selector
|
1166 |
-
st.rerun()
|
1167 |
|
1168 |
st.subheader("Manage Local Models")
|
1169 |
loaded_model_paths = list(st.session_state.get('local_models', {}).keys())
|
@@ -1196,7 +1254,6 @@ with tabs[3]:
|
|
1196 |
shutil.rmtree(path_to_delete)
|
1197 |
st.success(f"Deleted model '{model_to_delete}' and its files.")
|
1198 |
logger.info(f"Deleted local model: {path_to_delete}")
|
1199 |
-
st.rerun()
|
1200 |
except Exception as e:
|
1201 |
st.error(f"Failed to delete model '{model_to_delete}': {e}")
|
1202 |
logger.error(f"Failed to delete model {path_to_delete}: {e}")
|
|
|
672 |
return None
|
673 |
|
674 |
|
675 |
+
# --- Sidebar Gallery Update Function (MODIFIED) --------
|
|
|
676 |
def update_gallery():
|
677 |
+
st.sidebar.markdown("### Asset Gallery ๐ธ๐")
|
678 |
+
|
679 |
+
all_files = get_gallery_files() # Get currently available files
|
680 |
+
|
681 |
+
if not all_files:
|
682 |
+
st.sidebar.info("No assets (images, PDFs, text files) found yet.")
|
683 |
+
return
|
684 |
+
|
685 |
+
st.sidebar.caption(f"Found {len(all_files)} assets:")
|
686 |
+
|
687 |
+
for idx, file in enumerate(all_files):
|
688 |
+
st.session_state['unique_counter'] += 1
|
689 |
+
unique_id = st.session_state['unique_counter']
|
690 |
+
item_key_base = f"gallery_item_{os.path.basename(file)}_{unique_id}"
|
691 |
+
basename = os.path.basename(file)
|
692 |
+
st.sidebar.markdown(f"**{basename}**") # Display filename clearly
|
693 |
+
|
694 |
+
try:
|
695 |
+
file_ext = os.path.splitext(file)[1].lower()
|
696 |
+
# Display previews
|
697 |
+
if file_ext in ['.png', '.jpg', '.jpeg']:
|
698 |
+
# Add expander for large galleries
|
699 |
+
with st.sidebar.expander("Preview", expanded=False):
|
700 |
+
st.image(Image.open(file), use_container_width=True)
|
701 |
+
elif file_ext == '.pdf':
|
702 |
+
with st.sidebar.expander("Preview (Page 1)", expanded=False):
|
703 |
+
doc = fitz.open(file)
|
704 |
+
if len(doc) > 0:
|
705 |
+
pix = doc[0].get_pixmap(matrix=fitz.Matrix(0.5, 0.5)) # Smaller preview
|
706 |
+
img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
|
707 |
+
st.image(img, use_container_width=True)
|
708 |
+
else:
|
709 |
+
st.warning("Empty PDF")
|
710 |
+
doc.close()
|
711 |
+
elif file_ext in ['.md', '.txt']:
|
712 |
+
with st.sidebar.expander("Preview (Start)", expanded=False):
|
713 |
+
with open(file, 'r', encoding='utf-8', errors='ignore') as f:
|
714 |
+
content_preview = f.read(200) # Show first 200 chars
|
715 |
+
st.code(content_preview + "...", language='markdown' if file_ext == '.md' else 'text')
|
716 |
+
|
717 |
+
# --- Actions for the file (Select, Download, Delete) ---
|
718 |
+
action_cols = st.sidebar.columns(3) # Use columns for buttons
|
719 |
+
with action_cols[0]:
|
720 |
+
checkbox_key = f"cb_{item_key_base}"
|
721 |
+
st.session_state['asset_checkboxes'][file] = st.checkbox(
|
722 |
+
"Select",
|
723 |
+
value=st.session_state['asset_checkboxes'].get(file, False),
|
724 |
+
key=checkbox_key
|
725 |
+
)
|
726 |
+
with action_cols[1]:
|
727 |
+
mime_map = {'.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.pdf': 'application/pdf', '.txt': 'text/plain', '.md': 'text/markdown'}
|
728 |
+
mime_type = mime_map.get(file_ext, "application/octet-stream")
|
729 |
+
# Use button for download to avoid complex HTML link generation issues sometimes
|
730 |
+
dl_key = f"dl_{item_key_base}"
|
731 |
try:
|
732 |
+
with open(file, "rb") as fp:
|
733 |
+
st.download_button(
|
734 |
+
label="๐ฅ",
|
735 |
+
data=fp,
|
736 |
+
file_name=basename,
|
737 |
+
mime=mime_type,
|
738 |
+
key=dl_key,
|
739 |
+
help="Download this file"
|
740 |
+
)
|
741 |
+
except Exception as dl_e:
|
742 |
+
st.error(f"DL Err: {dl_e}")
|
743 |
+
|
744 |
+
with action_cols[2]:
|
745 |
+
delete_key = f"del_{item_key_base}"
|
746 |
+
if st.button("๐๏ธ", key=delete_key, help=f"Delete {basename}"):
|
747 |
+
try:
|
748 |
+
os.remove(file)
|
749 |
+
st.session_state['asset_checkboxes'].pop(file, None) # Remove from selection state
|
750 |
+
# Remove from layout_snapshots if present
|
751 |
+
if file in st.session_state.get('layout_snapshots', []):
|
752 |
+
st.session_state['layout_snapshots'].remove(file)
|
753 |
+
logger.info(f"Deleted asset: {file}")
|
754 |
+
st.toast(f"Deleted {basename}!", icon="โ
") # Use toast for less intrusive feedback
|
755 |
+
# REMOVED st.rerun() - Rely on file watcher
|
756 |
+
except OSError as e:
|
757 |
+
logger.error(f"Error deleting file {file}: {e}")
|
758 |
+
st.error(f"Could not delete {basename}")
|
759 |
+
# Trigger a rerun MANUALLY after deletion completes if file watcher is unreliable
|
760 |
+
st.rerun()
|
761 |
+
|
762 |
+
|
763 |
+
except (fitz.fitz.FileNotFoundError, FileNotFoundError):
|
764 |
+
st.sidebar.error(f"File not found: {basename}")
|
765 |
+
st.session_state['asset_checkboxes'].pop(file, None) # Clean up state
|
766 |
+
except (fitz.fitz.FileDataError, fitz.fitz.RuntimeException) as pdf_err:
|
767 |
+
st.sidebar.error(f"Corrupt PDF: {basename}")
|
768 |
+
logger.warning(f"Error opening PDF {file}: {pdf_err}")
|
769 |
+
except UnidentifiedImageError:
|
770 |
+
st.sidebar.error(f"Invalid Image: {basename}")
|
771 |
+
logger.warning(f"Cannot identify image file {file}")
|
772 |
+
except Exception as e:
|
773 |
+
st.sidebar.error(f"Error: {basename}")
|
774 |
+
logger.error(f"Error displaying asset {file}: {e}")
|
775 |
|
776 |
+
st.sidebar.markdown("---") # Separator between items
|
777 |
|
778 |
# --- UI Elements -----------------------------------------
|
779 |
|
|
|
941 |
st.image(Image.open(scan_name), caption=f"Scanned: {scan_name}", use_container_width=True)
|
942 |
if scan_name not in st.session_state['layout_snapshots']: st.session_state['layout_snapshots'].append(scan_name)
|
943 |
st.success(f"Scan saved as {scan_name}")
|
944 |
+
update_gallery(); # Add to gallery
|
945 |
except Exception as e: st.error(f"Failed to save scan: {e}"); logger.error(f"Failed to save camera scan {scan_name}: {e}")
|
946 |
|
947 |
layout_uploads = st.file_uploader("๐ Upload PNG/JPG Images for Layout PDF", type=["png","jpg","jpeg"], accept_multiple_files=True, key="layout_uploader")
|
|
|
1019 |
try:
|
1020 |
with open(filename, "wb") as f: f.write(cam0_img.getvalue())
|
1021 |
st.session_state['cam0_file'] = filename; st.session_state['history'].append(f"Snapshot from Cam 0: {filename}"); st.image(Image.open(filename), caption="Camera 0 Snap", use_container_width=True); logger.info(f"Saved snapshot from Camera 0: {filename}"); st.success(f"Saved {filename}")
|
1022 |
+
update_gallery();
|
1023 |
except Exception as e:
|
1024 |
st.error(f"Failed to save Cam 0 snap: {e}"); logger.error(f"Failed to save Cam 0 snap {filename}: {e}")
|
1025 |
with cols[1]:
|
|
|
1034 |
try:
|
1035 |
with open(filename, "wb") as f: f.write(cam1_img.getvalue())
|
1036 |
st.session_state['cam1_file'] = filename; st.session_state['history'].append(f"Snapshot from Cam 1: {filename}"); st.image(Image.open(filename), caption="Camera 1 Snap", use_container_width=True); logger.info(f"Saved snapshot from Camera 1: {filename}"); st.success(f"Saved {filename}")
|
1037 |
+
update_gallery();
|
1038 |
except Exception as e: st.error(f"Failed to save Cam 1 snap: {e}"); logger.error(f"Failed to save Cam 1 snap {filename}: {e}")
|
1039 |
|
1040 |
|
|
|
1059 |
if download_pdf(url, output_path): st.session_state['downloaded_pdfs'][url] = output_path; logger.info(f"Downloaded PDF from {url} to {output_path}"); st.session_state['history'].append(f"Downloaded PDF: {output_path}"); st.session_state['asset_checkboxes'][output_path] = False; download_count += 1; existing_pdfs.append(output_path)
|
1060 |
else: st.error(f"Failed to download: {url}")
|
1061 |
status_text.success(f"Download process complete! Successfully downloaded {download_count} new PDFs.")
|
1062 |
+
if download_count > 0: update_gallery();
|
1063 |
|
1064 |
st.subheader("Create Snapshots from Gallery PDFs")
|
1065 |
snapshot_mode = st.selectbox("Snapshot Mode", ["First Page (High-Res)", "First Two Pages (High-Res)", "All Pages (High-Res)", "First Page (Low-Res Preview)"], key="pdf_snapshot_mode")
|
|
|
1079 |
st.write(f"Snapshots for {os.path.basename(pdf_path)}:"); cols = st.columns(3)
|
1080 |
for i, snap_path in enumerate(new_snapshots):
|
1081 |
with cols[i % 3]: st.image(Image.open(snap_path), caption=os.path.basename(snap_path), use_container_width=True); st.session_state['asset_checkboxes'][snap_path] = False # Add to gallery
|
1082 |
+
if total_snapshots_generated > 0: st.success(f"Generated {total_snapshots_generated} snapshots from {snapshot_count} PDFs."); update_gallery();
|
1083 |
else: st.warning("No snapshots were generated. Check logs or PDF files.")
|
1084 |
|
1085 |
# --- Tab 4: Build Titan (Local Models) ---
|
|
|
1222 |
finally:
|
1223 |
progress_bar_build.progress(1.0)
|
1224 |
status_text_build.empty()
|
|
|
|
|
1225 |
|
1226 |
st.subheader("Manage Local Models")
|
1227 |
loaded_model_paths = list(st.session_state.get('local_models', {}).keys())
|
|
|
1254 |
shutil.rmtree(path_to_delete)
|
1255 |
st.success(f"Deleted model '{model_to_delete}' and its files.")
|
1256 |
logger.info(f"Deleted local model: {path_to_delete}")
|
|
|
1257 |
except Exception as e:
|
1258 |
st.error(f"Failed to delete model '{model_to_delete}': {e}")
|
1259 |
logger.error(f"Failed to delete model {path_to_delete}: {e}")
|