aggiunta la nuova funzione per unire più file markdown in un unico file per creare il manuale completo

This commit is contained in:
VALLONGOL 2025-11-12 15:50:29 +01:00
parent f7f6286930
commit af94f256af
7 changed files with 687 additions and 11 deletions

View File

@ -3,7 +3,7 @@
"last_selected_profile": "radar_data_reader", "last_selected_profile": "radar_data_reader",
"profiles": { "profiles": {
"cpp_python_debug": { "cpp_python_debug": {
"template_path": "C:/src/____GitProjects/cpp_python_debug/doc/TemplateSumSample.docx", "template_path": "C:/src/____GitProjects/SXXXXXXX_CppPythonDebug /doc/TemplateSumSample.docx",
"values": { "values": {
"%%DOC_CUSTOMER%%": "INTERNO", "%%DOC_CUSTOMER%%": "INTERNO",
"%%DOC_DATE%%": "18/06/2025", "%%DOC_DATE%%": "18/06/2025",
@ -14,18 +14,18 @@
} }
}, },
"radar_data_reader": { "radar_data_reader": {
"template_path": "C:/src/____GitProjects/MarkdownConverter/TemplateSumSample.docx", "template_path": "C:/src/____GitProjects/SXXXXXXX_MarkdownConverter/TemplateSumSample.docx",
"values": { "values": {
"%%DOC_CUSTOMER%%": "INTERNAL", "%%DOC_CUSTOMER%%": "",
"%%DOC_DATE%%": "22/07/2025", "%%DOC_DATE%%": "",
"%%DOC_NUMBER%%": "90000002", "%%DOC_NUMBER%%": "",
"%%DOC_PROJECT%%": "RADAR DATA READER", "%%DOC_PROJECT%%": "",
"%%DOC_REV%%": "A", "%%DOC_REV%%": "",
"%%DOC_SECURITY%%": "INTERNAL" "%%DOC_SECURITY%%": ""
} }
}, },
"mark_converter": { "mark_converter": {
"template_path": "C:/src/____GitProjects/MarkdownConverter/TemplateSumSample.docx", "template_path": "C:/src/____GitProjects/SXXXXXXX_ MarkdownConverter/TemplateSumSample.docx",
"values": { "values": {
"%%DOC_CUSTOMER%%": "INTERNO", "%%DOC_CUSTOMER%%": "INTERNO",
"%%DOC_DATE%%": "22/07/2025", "%%DOC_DATE%%": "22/07/2025",

147
convert.py Normal file
View File

@ -0,0 +1,147 @@
import os
import subprocess
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
from pathlib import Path
class MarkdownToPDFApp:
def __init__(self, root):
self.root = root
self.root.title("Markdown → DOCX/PDF Converter")
self.root.geometry("650x480")
self.root.resizable(False, False)
self.folder_path = tk.StringVar()
self.output_name = tk.StringVar(value="manuale")
self.template_path = tk.StringVar()
self.use_template = tk.BooleanVar(value=False)
self.generate_pdf = tk.BooleanVar(value=True)
# --- UI ---
tk.Label(root, text="Cartella Markdown:").pack(anchor="w", padx=10, pady=(10, 0))
frame1 = tk.Frame(root)
frame1.pack(fill="x", padx=10)
tk.Entry(frame1, textvariable=self.folder_path, width=50).pack(side="left", fill="x", expand=True)
tk.Button(frame1, text="Sfoglia...", command=self.choose_folder).pack(side="right", padx=5)
tk.Label(root, text="Nome base file output (senza estensione):").pack(anchor="w", padx=10, pady=(10, 0))
tk.Entry(root, textvariable=self.output_name, width=40).pack(fill="x", padx=10)
tk.Checkbutton(root, text="Usa template DOCX", variable=self.use_template, command=self.toggle_template).pack(anchor="w", padx=10, pady=(10, 0))
frame2 = tk.Frame(root)
frame2.pack(fill="x", padx=10)
tk.Entry(frame2, textvariable=self.template_path, width=50, state="disabled").pack(side="left", fill="x", expand=True)
tk.Button(frame2, text="Seleziona template", command=self.choose_template, state="disabled").pack(side="right", padx=5)
self.template_frame = frame2
tk.Checkbutton(root, text="Genera anche PDF finale", variable=self.generate_pdf).pack(anchor="w", padx=10, pady=(10, 0))
tk.Button(root, text="Genera Documento", command=self.generate_output, bg="#3c9", fg="white").pack(pady=10)
tk.Label(root, text="Log:").pack(anchor="w", padx=10)
self.log_box = scrolledtext.ScrolledText(root, height=13, state="disabled")
self.log_box.pack(fill="both", expand=True, padx=10, pady=(0, 10))
# --- Utility methods ---
def log(self, text):
self.log_box.configure(state="normal")
self.log_box.insert(tk.END, text + "\n")
self.log_box.configure(state="disabled")
self.log_box.see(tk.END)
self.root.update_idletasks()
def choose_folder(self):
folder = filedialog.askdirectory(title="Seleziona la cartella Markdown")
if folder:
self.folder_path.set(folder)
def toggle_template(self):
state = "normal" if self.use_template.get() else "disabled"
for widget in self.template_frame.winfo_children():
widget.configure(state=state)
def choose_template(self):
file = filedialog.askopenfilename(title="Seleziona template DOCX", filetypes=[("Word Template", "*.docx")])
if file:
self.template_path.set(file)
def generate_output(self):
folder = self.folder_path.get().strip()
output_name = self.output_name.get().strip()
template = self.template_path.get().strip()
use_template = self.use_template.get()
make_pdf = self.generate_pdf.get()
if not folder:
messagebox.showwarning("Attenzione", "Seleziona una cartella contenente i file Markdown.")
return
folder_path = Path(folder)
output_docx = folder_path / f"{output_name}.docx"
output_pdf = folder_path / f"{output_name}.pdf"
# Trova i file Markdown numerati
md_files = sorted(folder_path.glob("[0-9][0-9]_*.md"))
if not md_files:
messagebox.showerror("Errore", "Nessun file Markdown numerato trovato nella cartella.")
return
self.log(f"Trovati {len(md_files)} file Markdown:")
for f in md_files:
self.log(f" - {f.name}")
combined_md = folder_path / "_manuale_unico_temp.md"
self.log(f"\nUnione dei file in {combined_md.name}...")
try:
with open(combined_md, "w", encoding="utf-8") as out:
for f in md_files:
out.write(f"\n\n# --- {f.name} ---\n\n")
out.write(f.read_text(encoding="utf-8"))
out.write("\n\n")
self.log("File unito con successo.")
except Exception as e:
messagebox.showerror("Errore durante unione", str(e))
return
# Comando Pandoc per generare DOCX
cmd_docx = ["pandoc", str(combined_md), "-o", str(output_docx)]
if use_template:
if not Path(template).exists():
messagebox.showerror("Template non trovato", f"Il file {template} non esiste.")
return
cmd_docx.extend(["--reference-doc", str(template)])
self.log("\nEsecuzione Pandoc (DOCX)...")
result = subprocess.run(cmd_docx, capture_output=True, text=True)
if result.returncode != 0:
self.log("❌ Errore Pandoc (DOCX):")
self.log(result.stderr)
messagebox.showerror("Errore Pandoc", result.stderr)
return
self.log(f"✅ DOCX generato correttamente: {output_docx}")
# Generazione PDF opzionale
if make_pdf:
self.log("\nGenerazione PDF dal DOCX...")
cmd_pdf = ["pandoc", str(output_docx), "-o", str(output_pdf)]
result = subprocess.run(cmd_pdf, capture_output=True, text=True)
if result.returncode == 0:
self.log(f"✅ PDF generato: {output_pdf}")
messagebox.showinfo("Completato", f"PDF generato: {output_pdf}")
else:
self.log("❌ Errore durante conversione PDF:")
self.log(result.stderr)
messagebox.showerror("Errore PDF", result.stderr)
else:
messagebox.showinfo("Completato", f"DOCX generato: {output_docx}")
# Pulisce file temporaneo
if combined_md.exists():
combined_md.unlink()
if __name__ == "__main__":
root = tk.Tk()
app = MarkdownToPDFApp(root)
root.mainloop()

78
doc/BATCH_CONVERTER.md Normal file
View File

@ -0,0 +1,78 @@
# MarkdownConverter - Aggiornamenti
## Nuova Funzionalità: Conversione Batch
### Descrizione
È stata aggiunta una nuova funzionalità che permette di convertire automaticamente più file Markdown in un unico documento DOCX e/o PDF.
### Interfaccia a Tab
L'applicazione ora presenta due tab:
#### 1. **Conversione Singola**
- La funzionalità originale per convertire singoli file Markdown
- Supporta l'uso di template con placeholder personalizzati
- Gestione dei profili per diversi tipi di documenti
- Conversione diretta a DOCX o PDF
- Possibilità di convertire DOCX in PDF
#### 2. **Conversione Batch**
- Conversione automatica di più file Markdown da una cartella
- I file devono seguire il pattern di numerazione: `01_*.md`, `02_*.md`, ecc.
- Combinazione automatica dei file in ordine alfabetico
- Generazione di un singolo DOCX con tutti i contenuti
- Opzione per generare anche il PDF finale
- Supporto per template DOCX (senza placeholder, come riferimento di stile)
### Utilizzo della Conversione Batch
1. **Seleziona la Cartella**
- Clicca su "Sfoglia..." per selezionare la cartella contenente i file Markdown
- I file devono essere numerati: `01_introduzione.md`, `02_capitolo1.md`, ecc.
2. **Configura le Opzioni**
- **Nome base output**: Il nome del file risultante (senza estensione)
- **Usa template DOCX**: Attiva per usare un template come riferimento di stile
- **Genera anche PDF finale**: Attiva per convertire automaticamente il DOCX in PDF
3. **Genera il Documento**
- Clicca su "Genera Documento"
- Controlla il log per vedere i progressi
- I file verranno salvati nella stessa cartella dei file sorgente
### Funzioni Core Aggiunte
Nel modulo `markdownconverter/core/core.py` sono state aggiunte due nuove funzioni:
#### `combine_markdown_files(markdown_files, output_path)`
Combina più file Markdown in un unico file.
**Parametri:**
- `markdown_files`: Lista di Path o stringhe che puntano ai file markdown
- `output_path`: Percorso dove salvare il file combinato
**Ritorna:**
- Percorso del file combinato
#### `convert_markdown_to_docx_with_pandoc(input_file, output_path, template_path=None)`
Converte Markdown in DOCX usando Pandoc con template opzionale.
Questa è una conversione più semplice senza sostituzione di placeholder.
**Parametri:**
- `input_file`: Percorso del file markdown
- `output_path`: Percorso dove salvare il DOCX
- `template_path`: Percorso opzionale a un template DOCX (reference-doc)
**Ritorna:**
- Percorso del file DOCX generato
### Note Tecniche
- La funzionalità batch è completamente isolata nel modulo `batch_converter.py`
- Utilizza le stesse funzioni core per la conversione PDF
- Mantiene piena compatibilità con le funzionalità esistenti
- Il sistema a tab permette di passare facilmente tra le due modalità
### Migrazione da convert.py
Il file originale `convert.py` può essere mantenuto per compatibilità o rimosso.
Tutte le sue funzionalità sono ora integrate nell'applicazione principale.

View File

@ -4,12 +4,12 @@ import os
import re import re
import sys import sys
import tempfile import tempfile
import subprocess
from datetime import date from datetime import date
import docx import docx
import pypandoc import pypandoc
import pdfkit import pdfkit
import markdown import markdown
import subprocess
from docx.enum.text import WD_BREAK from docx.enum.text import WD_BREAK
from docx2pdf import convert as convert_word from docx2pdf import convert as convert_word
from ..utils.logger import get_logger from ..utils.logger import get_logger
@ -444,6 +444,69 @@ def convert_docx_to_pdf(input_docx_path: str, output_pdf_path: str) -> str:
raise raise
def combine_markdown_files(markdown_files: list, output_path: str) -> str:
"""
Combines multiple markdown files into a single file.
Args:
markdown_files: List of Path objects or strings pointing to markdown files
output_path: Path where the combined markdown file will be saved
Returns:
Path to the combined markdown file
"""
log.info(f"Combining {len(markdown_files)} markdown files into {output_path}")
with open(output_path, "w", encoding="utf-8") as out:
for md_file in markdown_files:
file_name = os.path.basename(md_file)
log.debug(f"Adding file: {file_name}")
out.write(f"\n\n# --- {file_name} ---\n\n")
with open(md_file, "r", encoding="utf-8") as f:
out.write(f.read())
out.write("\n\n")
log.info(f"Successfully combined files into: {output_path}")
return output_path
def convert_markdown_to_docx_with_pandoc(
input_file: str,
output_path: str,
template_path: str = None
) -> str:
"""
Converts markdown to DOCX using Pandoc with optional template.
This is a simpler conversion without placeholder replacement.
Args:
input_file: Path to the markdown file
output_path: Path where the DOCX will be saved
template_path: Optional path to a DOCX template (reference-doc)
Returns:
Path to the generated DOCX file
"""
log.info(f"Converting '{os.path.basename(input_file)}' to DOCX using Pandoc.")
if not os.path.exists(input_file):
raise FileNotFoundError(f"Input file not found: {input_file}")
cmd = ["pandoc", str(input_file), "-o", str(output_path)]
if template_path and os.path.exists(template_path):
log.info(f"Using template: {os.path.basename(template_path)}")
cmd.extend(["--reference-doc", str(template_path)])
try:
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
log.info(f"DOCX successfully generated: {output_path}")
return output_path
except subprocess.CalledProcessError as e:
log.error(f"Pandoc conversion failed: {e.stderr}")
raise RuntimeError(f"Pandoc conversion failed: {e.stderr}")
def convert_markdown( def convert_markdown(
input_file: str, input_file: str,
output_path: str, output_path: str,

View File

@ -0,0 +1,332 @@
# markdownconverter/gui/batch_converter.py
import os
import tkinter as tk
from pathlib import Path
from tkinter import filedialog, messagebox, StringVar, BooleanVar
import ttkbootstrap as tb
from tkinter.scrolledtext import ScrolledText
from ttkbootstrap.constants import *
from ..core.core import (
combine_markdown_files,
convert_markdown_to_docx_with_pandoc,
convert_docx_to_pdf
)
from ..utils.logger import get_logger
log = get_logger(__name__)
class BatchConverterTab(tb.Frame):
"""
Tab per la conversione batch di file markdown da una cartella.
Trova tutti i file markdown numerati (es. 01_*.md, 02_*.md),
li combina in ordine alfabetico e genera DOCX e/o PDF.
"""
def __init__(self, parent):
super().__init__(parent, padding=10)
self.folder_path = StringVar()
self.output_name = StringVar(value="manuale")
self.template_path = StringVar()
self.use_template = BooleanVar(value=False)
self.generate_pdf = BooleanVar(value=True)
self._build_ui()
def _build_ui(self):
"""Costruisce l'interfaccia utente del tab batch."""
# Frame per la selezione della cartella
folder_frame = tb.Labelframe(self, text="Cartella Sorgente", padding=10)
folder_frame.pack(fill=tk.X, pady=(0, 10))
folder_frame.columnconfigure(1, weight=1)
tb.Label(folder_frame, text="Cartella Markdown:").grid(
row=0, column=0, padx=5, pady=5, sticky="w"
)
tb.Entry(folder_frame, textvariable=self.folder_path).grid(
row=0, column=1, padx=5, pady=5, sticky="ew"
)
tb.Button(
folder_frame,
text="Sfoglia...",
command=self._choose_folder,
bootstyle=PRIMARY
).grid(row=0, column=2, padx=5, pady=5)
# Frame per le opzioni
options_frame = tb.Labelframe(self, text="Opzioni di Conversione", padding=10)
options_frame.pack(fill=tk.X, pady=(0, 10))
options_frame.columnconfigure(1, weight=1)
tb.Label(options_frame, text="Nome base output:").grid(
row=0, column=0, padx=5, pady=5, sticky="w"
)
tb.Entry(options_frame, textvariable=self.output_name).grid(
row=0, column=1, padx=5, pady=5, sticky="ew"
)
# Checkbox per template
tb.Checkbutton(
options_frame,
text="Usa template DOCX",
variable=self.use_template,
command=self._toggle_template,
bootstyle="primary-round-toggle"
).grid(row=1, column=0, padx=5, pady=5, sticky="w")
# Frame per template
self.template_entry = tb.Entry(
options_frame,
textvariable=self.template_path,
state="disabled"
)
self.template_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
self.template_button = tb.Button(
options_frame,
text="Seleziona template",
command=self._choose_template,
state="disabled"
)
self.template_button.grid(row=1, column=2, padx=5, pady=5)
# Checkbox per PDF
tb.Checkbutton(
options_frame,
text="Genera anche PDF finale",
variable=self.generate_pdf,
bootstyle="primary-round-toggle"
).grid(row=2, column=0, columnspan=2, padx=5, pady=5, sticky="w")
# Pulsante di conversione
tb.Button(
self,
text="Genera Documento",
command=self._generate_output,
bootstyle=SUCCESS,
width=20
).pack(pady=10)
# Frame che mostra la lista dei file trovati nella cartella selezionata
files_frame = tb.Labelframe(self, text="File trovati (in ordine alfabetico)", padding=10)
files_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
files_frame.rowconfigure(0, weight=1); files_frame.columnconfigure(0, weight=1)
self.files_listbox = tk.Listbox(files_frame, height=8, exportselection=False)
self.files_listbox.grid(row=0, column=0, sticky="nsew")
files_scroll = tb.Scrollbar(files_frame, orient=tk.VERTICAL, command=self.files_listbox.yview)
files_scroll.grid(row=0, column=1, sticky="ns")
self.files_listbox.config(yscrollcommand=files_scroll.set)
# Log area
log_frame = tb.Labelframe(self, text="Log", padding=10)
log_frame.pack(fill=tk.BOTH, expand=True)
self.log_box = ScrolledText(log_frame, height=15, state="disabled", wrap=tk.WORD)
self.log_box.pack(fill=tk.BOTH, expand=True)
def _log(self, text):
"""Aggiunge un messaggio all'area log."""
self.log_box.configure(state="normal")
self.log_box.insert(tk.END, text + "\n")
self.log_box.configure(state="disabled")
self.log_box.see(tk.END)
self.update_idletasks()
def _choose_folder(self):
"""Apre il dialogo per selezionare la cartella."""
folder = filedialog.askdirectory(title="Seleziona la cartella Markdown")
if folder:
self.folder_path.set(folder)
self._log(f"Cartella selezionata: {folder}")
# Aggiorna immediatamente la lista dei file trovati
try:
self._scan_and_display_files(folder)
except Exception as e:
log.error(f"Errore durante la scansione della cartella: {e}", exc_info=True)
def _toggle_template(self):
"""Attiva/disattiva i controlli del template."""
state = "normal" if self.use_template.get() else "disabled"
self.template_entry.configure(state=state)
self.template_button.configure(state=state)
def _choose_template(self):
"""Apre il dialogo per selezionare il template."""
file = filedialog.askopenfilename(
title="Seleziona template DOCX",
filetypes=[("Word Documents", "*.docx"), ("Word Templates", "*.dotx")]
)
if file:
self.template_path.set(file)
self._log(f"Template selezionato: {os.path.basename(file)}")
def _generate_output(self):
"""Esegue la conversione batch dei file markdown."""
folder = self.folder_path.get().strip()
output_name = self.output_name.get().strip()
template = self.template_path.get().strip()
use_template = self.use_template.get()
make_pdf = self.generate_pdf.get()
# Validazione input
if not folder:
messagebox.showwarning(
"Attenzione",
"Seleziona una cartella contenente i file Markdown."
)
return
if not output_name:
messagebox.showwarning(
"Attenzione",
"Inserisci un nome per il file di output."
)
return
folder_path = Path(folder)
if not folder_path.exists():
messagebox.showerror("Errore", "La cartella selezionata non esiste.")
return
# Trova i file markdown numerati
md_files = sorted(folder_path.glob("[0-9][0-9]_*.md"))
if not md_files:
messagebox.showerror(
"Errore",
"Nessun file Markdown numerato trovato nella cartella.\n"
"I file devono seguire il pattern: 01_nome.md, 02_nome.md, ecc."
)
return
# Mostra una finestra di conferma con la lista dei file trovati
if not self._confirm_file_list(md_files):
self._log("Operazione annullata dall'utente dopo la visualizzazione dei file.")
return
self._log(f"\n{'='*60}")
self._log(f"INIZIO CONVERSIONE BATCH")
self._log(f"{'='*60}")
self._log(f"Trovati {len(md_files)} file Markdown:")
for f in md_files:
self._log(f" - {f.name}")
# Prepara i percorsi di output
output_docx = folder_path / f"{output_name}.docx"
output_pdf = folder_path / f"{output_name}.pdf"
combined_md = folder_path / "_manuale_unico_temp.md"
try:
# Combina i file markdown
self._log(f"\nUnione dei file in {combined_md.name}...")
combine_markdown_files(md_files, combined_md)
self._log("✅ File unito con successo.")
# Genera DOCX
self._log("\nGenerazione DOCX...")
if use_template:
if not Path(template).exists():
messagebox.showerror(
"Template non trovato",
f"Il file {template} non esiste."
)
return
convert_markdown_to_docx_with_pandoc(
str(combined_md),
str(output_docx),
template_path=template
)
else:
convert_markdown_to_docx_with_pandoc(
str(combined_md),
str(output_docx)
)
self._log(f"✅ DOCX generato: {output_docx.name}")
# Genera PDF opzionale
if make_pdf:
self._log("\nGenerazione PDF dal DOCX...")
convert_docx_to_pdf(str(output_docx), str(output_pdf))
self._log(f"✅ PDF generato: {output_pdf.name}")
messagebox.showinfo(
"Completato",
f"Conversione completata con successo!\n\n"
f"DOCX: {output_docx.name}\n"
f"PDF: {output_pdf.name}"
)
else:
messagebox.showinfo(
"Completato",
f"Conversione completata con successo!\n\n"
f"DOCX: {output_docx.name}"
)
self._log(f"\n{'='*60}")
self._log("CONVERSIONE COMPLETATA CON SUCCESSO")
self._log(f"{'='*60}\n")
except Exception as e:
log.error(f"Errore durante la conversione batch: {e}", exc_info=True)
self._log(f"\n❌ ERRORE: {str(e)}")
messagebox.showerror(
"Errore",
f"Si è verificato un errore durante la conversione:\n\n{str(e)}"
)
finally:
# Pulisce il file temporaneo
if combined_md.exists():
combined_md.unlink()
self._log(f"File temporaneo {combined_md.name} rimosso.")
def _scan_and_display_files(self, folder: str):
"""Scansiona la cartella e popola la listbox con i file markdown trovati.
Il pattern usato corrisponde ai file numerati: 01_nome.md, 02_nome.md, ...
"""
folder_path = Path(folder)
if not folder_path.exists():
raise FileNotFoundError("La cartella selezionata non esiste.")
md_files = sorted(folder_path.glob("[0-9][0-9]_*.md"))
# Pulisce la listbox
self.files_listbox.delete(0, tk.END)
for f in md_files:
self.files_listbox.insert(tk.END, f.name)
self._log(f"Scansionati {len(md_files)} file markdown nella cartella.")
def _confirm_file_list(self, md_files: list) -> bool:
"""Apre una finestra modale che mostra la lista dei file trovati e chiede conferma all'utente.
Restituisce True se l'utente conferma, False se annulla.
"""
dlg = tb.Toplevel(self, title="Conferma file trovati")
dlg.transient(self)
dlg.grab_set()
dlg.geometry("600x400")
tb.Label(dlg, text="I seguenti file sono stati trovati e saranno uniti in questo ordine:", bootstyle=INFO).pack(anchor="w", padx=10, pady=(10, 0))
list_frame = tb.Frame(dlg); list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
listbox = tk.Listbox(list_frame)
listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar = tb.Scrollbar(list_frame, orient=tk.VERTICAL, command=listbox.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
listbox.config(yscrollcommand=scrollbar.set)
for f in md_files:
listbox.insert(tk.END, f.name)
btn_frame = tb.Frame(dlg); btn_frame.pack(fill=tk.X, pady=(0, 10), padx=10)
confirmed = {"value": False}
def _on_confirm():
confirmed["value"] = True
dlg.grab_release(); dlg.destroy()
def _on_cancel():
dlg.grab_release(); dlg.destroy()
tb.Button(btn_frame, text="Conferma e procedi", bootstyle=SUCCESS, command=_on_confirm).pack(side=tk.RIGHT, padx=5)
tb.Button(btn_frame, text="Annulla", bootstyle=SECONDARY, command=_on_cancel).pack(side=tk.RIGHT)
self.wait_window(dlg)
return confirmed["value"]

View File

@ -27,6 +27,7 @@ from ..utils.logger import (
setup_basic_logging, add_tkinter_handler, setup_basic_logging, add_tkinter_handler,
shutdown_logging_system, get_logger shutdown_logging_system, get_logger
) )
from .batch_converter import BatchConverterTab
# EditorWindow non viene usato in questo file, ma lo lasciamo per coerenza # EditorWindow non viene usato in questo file, ma lo lasciamo per coerenza
# from .editor import EditorWindow # from .editor import EditorWindow
@ -169,7 +170,24 @@ class MarkdownConverterApp:
setup_basic_logging(root_tk_instance_for_processor=self.root, logging_config_dict=self.log_config) setup_basic_logging(root_tk_instance_for_processor=self.root, logging_config_dict=self.log_config)
def _build_ui(self): def _build_ui(self):
container = tb.Frame(self.root, padding=10); container.pack(fill=tk.BOTH, expand=True) # Crea il Notebook (sistema a tab)
self.notebook = tb.Notebook(self.root)
self.notebook.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
# Tab 1: Conversione Singola (funzionalità originale)
self.single_converter_tab = tb.Frame(self.notebook, padding=10)
self.notebook.add(self.single_converter_tab, text="Conversione Singola")
# Tab 2: Conversione Batch
self.batch_converter_tab = BatchConverterTab(self.notebook)
self.notebook.add(self.batch_converter_tab, text="Conversione Batch")
# Costruisce la UI del tab singolo nel container
self._build_single_converter_ui()
def _build_single_converter_ui(self):
"""Costruisce l'interfaccia per la conversione singola."""
container = self.single_converter_tab
profile_frame = tb.Labelframe(container, text="Profile & Source File", padding=10) profile_frame = tb.Labelframe(container, text="Profile & Source File", padding=10)
profile_frame.pack(fill=tk.X, pady=(0, 10)); profile_frame.columnconfigure(1, weight=1) profile_frame.pack(fill=tk.X, pady=(0, 10)); profile_frame.columnconfigure(1, weight=1)
tb.Label(profile_frame, text="Active Profile:").grid(row=0, column=0, padx=5, pady=5, sticky="w") tb.Label(profile_frame, text="Active Profile:").grid(row=0, column=0, padx=5, pady=5, sticky="w")

38
test_integration.py Normal file
View File

@ -0,0 +1,38 @@
# Test script per verificare l'integrazione del batch converter
import sys
import os
# Aggiungi il percorso del modulo al path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
try:
# Test import dei moduli principali
print("Testing imports...")
from markdownconverter.gui.gui import MarkdownConverterApp
from markdownconverter.gui.batch_converter import BatchConverterTab
from markdownconverter.core.core import (
combine_markdown_files,
convert_markdown_to_docx_with_pandoc,
convert_markdown,
convert_docx_to_pdf
)
print("✅ All imports successful!")
# Test avvio GUI (opzionale - commentato per non bloccare)
print("\nTo test the GUI, uncomment the following lines:")
print("# import ttkbootstrap as tb")
print("# root = tb.Window(themename='sandstone')")
print("# app = MarkdownConverterApp(root)")
print("# root.mainloop()")
print("\n✅ Integration test passed!")
print("\nYou can now run the application with:")
print(" python -m markdownconverter")
except ImportError as e:
print(f"❌ Import error: {e}")
sys.exit(1)
except Exception as e:
print(f"❌ Error: {e}")
sys.exit(1)