DaniFera commited on
Commit
31df732
·
verified ·
1 Parent(s): e3f0aa4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -83
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # Versión 1.1: UI Avanzada con gestión de estado
2
  import gradio as gr
3
  import pandas as pd
4
  import config
@@ -6,130 +6,116 @@ from core import PDFEngine
6
 
7
  engine = PDFEngine()
8
 
9
- # --- FUNCIONES AUXILIARES UNIR ---
10
  def update_file_list(files):
11
- """Crea un Dataframe para mostrar los archivos subidos y sus índices."""
12
- if not files:
13
- return pd.DataFrame(), ""
14
-
15
- # files es una lista de objetos o rutas dependiendo de la config.
16
- # En Gradio 4, si file_count="multiple", suele ser lista de rutas.
17
- data = []
18
- for idx, f_path in enumerate(files):
19
- name = f_path.split("/")[-1] # Obtener nombre simple
20
- data.append([idx, name])
21
-
22
  default_order = ",".join([str(i) for i in range(len(files))])
23
- return pd.DataFrame(data, columns=["ID", "Nombre del Archivo"]), default_order
24
 
25
  def process_merge_ordered(files, order_str):
26
- if not files:
27
- return None
28
  try:
29
- # Convertir string "0, 2, 1" a lista de enteros [0, 2, 1]
30
  indices = [int(x.strip()) for x in order_str.split(",") if x.strip().isdigit()]
31
  return engine.merge_pdfs(files, indices)
32
  except Exception as e:
33
- raise gr.Error(f"Error en el orden: {str(e)}")
34
 
35
- # --- FUNCIONES AUXILIARES DIVIDIR ---
36
  def load_pdf_info(file):
37
- if not file:
38
- return None, None, gr.update(visible=False)
39
-
40
  info = engine.get_pdf_info(file)
41
- msg = f"Documento cargado: {info['name']} ({info['pages']} páginas)."
42
- return msg, info['pages'], gr.update(visible=True)
43
 
44
  def update_preview(file, range_str, total_pages):
45
- if not file or not range_str:
46
- return None
47
 
48
- # Parseamos para ver qué páginas quiere el usuario
49
- # Solo previsualizamos la primera y última del rango para no saturar memoria
50
- indices = engine.parse_range_string(range_str, total_pages)
51
- if not indices:
52
- return None
53
 
54
- first_idx = indices[0] + 1 # Convertir a 1-based para visualización
55
- last_idx = indices[-1] + 1
56
 
57
- images = []
58
- # Generar imagen de inicio
59
- img1 = engine.generate_preview(file, first_idx)
60
- if img1: images.append((img1, f"Página {first_idx}"))
61
 
62
- # Generar imagen de fin si es distinta
63
- if last_idx != first_idx:
64
- img2 = engine.generate_preview(file, last_idx)
65
- if img2: images.append((img2, f"Página {last_idx}"))
66
-
67
- return images
 
68
 
69
  def process_split_range(file, range_str):
70
- return engine.split_pdf_custom(file, range_str)
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
  # --- UI PRINCIPAL ---
73
  with gr.Blocks(title=config.APP_TITLE, theme=gr.themes.Soft()) as demo:
74
  gr.Markdown(f"# {config.APP_TITLE}")
75
 
76
  with gr.Tabs():
77
- # TAB 1: UNIR (Con reordenamiento manual)
78
  with gr.TabItem("Unir PDF"):
79
- gr.Markdown("Sube los archivos, revisa sus IDs en la tabla y escribe el orden deseado (ej: 2,0,1).")
80
-
81
  with gr.Row():
82
  with gr.Column(scale=1):
83
  merge_files = gr.File(file_count="multiple", label="Archivos", file_types=[".pdf"])
84
  with gr.Column(scale=2):
85
- file_table = gr.Dataframe(headers=["ID", "Nombre del Archivo"], interactive=False)
86
- order_input = gr.Textbox(label="Orden de unión (IDs separados por coma)")
87
- merge_btn = gr.Button("Unir en este orden", variant="primary")
88
-
89
  merge_output = gr.File(label="Resultado")
90
-
91
- # Eventos
92
  merge_files.change(fn=update_file_list, inputs=merge_files, outputs=[file_table, order_input])
93
  merge_btn.click(fn=process_merge_ordered, inputs=[merge_files, order_input], outputs=merge_output)
94
 
95
- # TAB 2: DIVIDIR (Con Rangos y Preview)
96
- with gr.TabItem("Extraer/Dividir PDF"):
97
- gr.Markdown("Extrae páginas específicas. Ejemplos de rango: '1-5', '1,3,5', '1-3, 8'.")
98
-
99
  with gr.Row():
100
  with gr.Column():
101
  split_file = gr.File(label="PDF Origen", file_types=[".pdf"])
102
- info_text = gr.Markdown("Esperando archivo...")
103
- # Estado oculto para guardar número total de páginas
104
- page_count_state = gr.State(0)
105
-
106
- range_input = gr.Textbox(label="Rango de páginas", placeholder="Ej: 1-3, 5")
107
- preview_btn = gr.Button("Previsualizar Selección")
108
- split_btn = gr.Button("Extraer Páginas", variant="primary")
109
 
 
 
 
 
110
  with gr.Column():
111
- preview_gallery = gr.Gallery(label="Vista previa (Inicio/Fin)", columns=2, height=300, object_fit="contain")
112
- split_output = gr.File(label="PDF Extraído")
 
113
 
114
- # Eventos
115
- split_file.change(fn=load_pdf_info, inputs=split_file, outputs=[info_text, page_count_state, split_output])
116
-
117
- preview_btn.click(
118
- fn=update_preview,
119
- inputs=[split_file, range_input, page_count_state],
120
- outputs=preview_gallery
121
- )
122
-
123
- split_btn.click(
124
- fn=process_split_range,
125
- inputs=[split_file, range_input],
126
- outputs=split_output
127
- )
128
 
129
- # TAB 3: PROTEGER (Igual que antes)
130
  with gr.TabItem("Proteger PDF"):
131
- # (Mantener el código de la UI de proteger de la versión 1.0)
132
- pass
 
 
 
 
 
 
 
 
133
 
134
  if __name__ == "__main__":
135
  demo.launch()
 
1
+ # Versión 1.2: Corrección de UI y Preview Avanzada
2
  import gradio as gr
3
  import pandas as pd
4
  import config
 
6
 
7
  engine = PDFEngine()
8
 
9
+ # --- FUNCIONES UNIR ---
10
  def update_file_list(files):
11
+ if not files: return pd.DataFrame(), ""
12
+ data = [[i, f.split("/")[-1]] for i, f in enumerate(files)]
 
 
 
 
 
 
 
 
 
13
  default_order = ",".join([str(i) for i in range(len(files))])
14
+ return pd.DataFrame(data, columns=["ID", "Archivo"]), default_order
15
 
16
  def process_merge_ordered(files, order_str):
17
+ if not files: return None
 
18
  try:
 
19
  indices = [int(x.strip()) for x in order_str.split(",") if x.strip().isdigit()]
20
  return engine.merge_pdfs(files, indices)
21
  except Exception as e:
22
+ raise gr.Error(f"Error: {str(e)}")
23
 
24
+ # --- FUNCIONES DIVIDIR ---
25
  def load_pdf_info(file):
26
+ if not file: return None, 0, gr.update(visible=False)
 
 
27
  info = engine.get_pdf_info(file)
28
+ return f"Cargado: {info['name']} ({info['pages']} págs).", info['pages'], gr.update(visible=True)
 
29
 
30
  def update_preview(file, range_str, total_pages):
31
+ if not file or not range_str: return None
 
32
 
33
+ # NUEVO: Obtenemos los hitos clave (inicio/fin) de cada rango
34
+ key_pages = engine.get_preview_indices_from_string(range_str, total_pages)
 
 
 
35
 
36
+ if not key_pages: return None
 
37
 
38
+ # Limitamos a 8 previews para no saturar
39
+ key_pages = key_pages[:8]
 
 
40
 
41
+ gallery_data = []
42
+ for page_num in key_pages:
43
+ img_path = engine.generate_preview(file, page_num)
44
+ if img_path:
45
+ gallery_data.append((img_path, f"Pág {page_num}"))
46
+
47
+ return gallery_data
48
 
49
  def process_split_range(file, range_str):
50
+ if not file: return None
51
+ try:
52
+ return engine.split_pdf_custom(file, range_str)
53
+ except Exception as e:
54
+ raise gr.Error(str(e))
55
+
56
+ # --- FUNCIONES PROTEGER ---
57
+ def interface_protect(file, password):
58
+ if not file or not password: return None
59
+ try:
60
+ return engine.protect_pdf(file, password)
61
+ except Exception as e:
62
+ raise gr.Error(str(e))
63
 
64
  # --- UI PRINCIPAL ---
65
  with gr.Blocks(title=config.APP_TITLE, theme=gr.themes.Soft()) as demo:
66
  gr.Markdown(f"# {config.APP_TITLE}")
67
 
68
  with gr.Tabs():
69
+ # TAB 1: UNIR
70
  with gr.TabItem("Unir PDF"):
71
+ gr.Markdown(config.TXT_MERGE)
 
72
  with gr.Row():
73
  with gr.Column(scale=1):
74
  merge_files = gr.File(file_count="multiple", label="Archivos", file_types=[".pdf"])
75
  with gr.Column(scale=2):
76
+ file_table = gr.Dataframe(headers=["ID", "Archivo"], interactive=False)
77
+ order_input = gr.Textbox(label="Orden (IDs separados por coma)", placeholder="Ej: 0, 2, 1")
78
+ merge_btn = gr.Button("Unir PDF", variant="primary")
 
79
  merge_output = gr.File(label="Resultado")
80
+
 
81
  merge_files.change(fn=update_file_list, inputs=merge_files, outputs=[file_table, order_input])
82
  merge_btn.click(fn=process_merge_ordered, inputs=[merge_files, order_input], outputs=merge_output)
83
 
84
+ # TAB 2: DIVIDIR (Mejorado)
85
+ with gr.TabItem("Dividir PDF"):
86
+ gr.Markdown(config.TXT_SPLIT)
 
87
  with gr.Row():
88
  with gr.Column():
89
  split_file = gr.File(label="PDF Origen", file_types=[".pdf"])
90
+ info_txt = gr.Markdown("")
91
+ page_count = gr.State(0)
92
+ range_in = gr.Textbox(label="Rangos", placeholder="Ej: 1-3, 5, 8-10")
 
 
 
 
93
 
94
+ with gr.Row():
95
+ prev_btn = gr.Button("Ver Páginas Clave")
96
+ split_btn = gr.Button("Extraer", variant="primary")
97
+
98
  with gr.Column():
99
+ # Galería dinámica para mostrar múltiples páginas
100
+ preview_gal = gr.Gallery(label="Hitos del Rango", columns=3, height=350, object_fit="contain")
101
+ split_out = gr.File(label="PDF Resultante")
102
 
103
+ split_file.change(fn=load_pdf_info, inputs=split_file, outputs=[info_txt, page_count, split_out])
104
+ prev_btn.click(fn=update_preview, inputs=[split_file, range_in, page_count], outputs=preview_gal)
105
+ split_btn.click(fn=process_split_range, inputs=[split_file, range_in], outputs=split_out)
 
 
 
 
 
 
 
 
 
 
 
106
 
107
+ # TAB 3: PROTEGER (Restaurado)
108
  with gr.TabItem("Proteger PDF"):
109
+ gr.Markdown(config.TXT_PROTECT)
110
+ with gr.Row():
111
+ with gr.Column():
112
+ prot_file = gr.File(label="PDF a proteger", file_types=[".pdf"])
113
+ pass_in = gr.Textbox(label="Contraseña", type="password")
114
+ prot_btn = gr.Button("Encriptar", variant="primary")
115
+ with gr.Column():
116
+ prot_out = gr.File(label="PDF Encriptado")
117
+
118
+ prot_btn.click(fn=interface_protect, inputs=[prot_file, pass_in], outputs=prot_out)
119
 
120
  if __name__ == "__main__":
121
  demo.launch()