198 lines
9.0 KiB
Python
198 lines
9.0 KiB
Python
# markdownconverter/gui/gui.py
|
|
|
|
import os
|
|
import sys
|
|
import logging
|
|
import subprocess
|
|
import tkinter as tk
|
|
import ttkbootstrap as tb
|
|
from tkinter.scrolledtext import ScrolledText
|
|
from ttkbootstrap.constants import *
|
|
from tkinter import filedialog, messagebox, StringVar, BooleanVar
|
|
|
|
from ..core.core import convert_markdown
|
|
from ..utils.config import save_configuration, load_configuration
|
|
from ..utils.logger import (
|
|
setup_basic_logging,
|
|
add_tkinter_handler,
|
|
shutdown_logging_system,
|
|
get_logger
|
|
)
|
|
from .editor import EditorWindow
|
|
|
|
log = get_logger(__name__)
|
|
|
|
def open_with_default_app(filepath):
|
|
if not filepath:
|
|
log.warning("Open file/folder requested, but no path was provided.")
|
|
messagebox.showwarning("Warning", "No output file or folder to open.")
|
|
return
|
|
try:
|
|
log.info(f"Opening '{filepath}' with default application.")
|
|
if sys.platform == "win32":
|
|
os.startfile(filepath)
|
|
elif sys.platform == "darwin":
|
|
subprocess.run(["open", filepath], check=True)
|
|
else:
|
|
subprocess.run(["xdg-open", filepath], check=True)
|
|
except Exception as e:
|
|
log.error(f"Failed to open '{filepath}': {e}", exc_info=True)
|
|
messagebox.showerror("Error", f"Could not open the file/folder:\n{str(e)}")
|
|
|
|
def open_output_folder(filepath):
|
|
if not filepath:
|
|
log.warning("Open folder requested, but no output file has been generated yet.")
|
|
messagebox.showwarning("Warning", "No output file has been generated yet.")
|
|
return
|
|
folder = os.path.dirname(filepath)
|
|
open_with_default_app(folder)
|
|
|
|
|
|
def run_app():
|
|
app = tb.Window(themename="sandstone")
|
|
app.title("Markdown Converter")
|
|
app.geometry("800x750")
|
|
app.resizable(True, True)
|
|
|
|
log_config = {
|
|
"default_root_level": logging.DEBUG,
|
|
"format": "%(asctime)s [%(levelname)-8s] %(name)-20s: %(message)s",
|
|
"date_format": "%H:%M:%S",
|
|
"enable_console": True, "enable_file": True,
|
|
"file_path": "markdown_converter.log",
|
|
"colors": {
|
|
logging.DEBUG: "gray", logging.INFO: "black", logging.WARNING: "orange",
|
|
logging.ERROR: "red", logging.CRITICAL: "purple",
|
|
},
|
|
}
|
|
setup_basic_logging(root_tk_instance_for_processor=app, logging_config_dict=log_config)
|
|
|
|
config = load_configuration()
|
|
metadata_config = config.get("metadata", {})
|
|
|
|
selected_file = StringVar(value=config.get("last_markdown_file", ""))
|
|
selected_template = StringVar(value=config.get("last_template_file", ""))
|
|
add_toc_var = BooleanVar(value=config.get("add_toc", True))
|
|
output_path = StringVar()
|
|
|
|
doc_security_var = StringVar(value=metadata_config.get("DOC_SECURITY", ""))
|
|
doc_number_var = StringVar(value=metadata_config.get("DOC_NUMBER", ""))
|
|
doc_rev_var = StringVar(value=metadata_config.get("DOC_REV", ""))
|
|
doc_project_var = StringVar(value=metadata_config.get("DOC_PROJECT", ""))
|
|
customer_var = StringVar(value=metadata_config.get("CUSTOMER", ""))
|
|
|
|
def open_editor():
|
|
file_path = selected_file.get()
|
|
if not file_path or not os.path.exists(file_path):
|
|
messagebox.showerror("Error", "Please select a valid Markdown file first.")
|
|
return
|
|
EditorWindow(parent=app, file_path=file_path)
|
|
|
|
def browse_markdown():
|
|
path = filedialog.askopenfilename(filetypes=[("Markdown files", "*.md"), ("All files", "*.*")])
|
|
if path:
|
|
selected_file.set(path)
|
|
|
|
def browse_template():
|
|
# --- CORREZIONE: Cerca prima i file .docx ---
|
|
path = filedialog.askopenfilename(
|
|
title="Select a Template Document",
|
|
filetypes=[("Word Documents", "*.docx"), ("All files", "*.*")]
|
|
)
|
|
if path:
|
|
selected_template.set(path)
|
|
|
|
def convert(fmt):
|
|
file_path = selected_file.get()
|
|
if not file_path:
|
|
messagebox.showerror("Error", "Please select a Markdown file.")
|
|
return
|
|
|
|
template = selected_template.get()
|
|
if fmt == "DOCX" and not template:
|
|
messagebox.showwarning("Warning", "A DOCX template is required.")
|
|
return
|
|
|
|
metadata_to_pass = {
|
|
'DOC_SECURITY': doc_security_var.get(),
|
|
'DOC_NUMBER': doc_number_var.get(),
|
|
'DOC_REV': doc_rev_var.get(),
|
|
'DOC_PROJECT': doc_project_var.get(),
|
|
'DOC_CUSTOMER': customer_var.get(),
|
|
}
|
|
|
|
try:
|
|
output = convert_markdown(
|
|
input_file=file_path, output_format=fmt, add_toc=add_toc_var.get(),
|
|
template_path=template, metadata=metadata_to_pass
|
|
)
|
|
output_path.set(output)
|
|
messagebox.showinfo("Success", f"File converted successfully:\n{output}")
|
|
|
|
save_configuration(
|
|
last_markdown=file_path, last_template=template,
|
|
add_toc=add_toc_var.get(), metadata=metadata_to_pass
|
|
)
|
|
except Exception as e:
|
|
log.critical(f"An error occurred during conversion: {e}", exc_info=True)
|
|
messagebox.showerror("Error", f"An error occurred during conversion:\n{str(e)}")
|
|
|
|
container = tb.Frame(app, padding=10)
|
|
container.pack(fill=tk.BOTH, expand=True)
|
|
top_frame = tb.Frame(container)
|
|
top_frame.pack(fill=tk.X, side=tk.TOP, pady=(0, 10))
|
|
|
|
tb.Label(top_frame, text="Markdown File:").grid(row=0, column=0, padx=(0, 10), pady=5, sticky="w")
|
|
tb.Entry(top_frame, textvariable=selected_file, width=70).grid(row=0, column=1, padx=5, sticky="ew")
|
|
file_button_frame = tb.Frame(top_frame)
|
|
file_button_frame.grid(row=0, column=2, sticky="w")
|
|
tb.Button(file_button_frame, text="Browse...", command=browse_markdown, bootstyle=PRIMARY).pack(side=tk.LEFT, padx=(0, 5))
|
|
tb.Button(file_button_frame, text="Edit...", command=open_editor, bootstyle=INFO).pack(side=tk.LEFT)
|
|
|
|
tb.Label(top_frame, text="Template File:").grid(row=1, column=0, padx=(0, 10), pady=5, sticky="w")
|
|
tb.Entry(top_frame, textvariable=selected_template, width=70).grid(row=1, column=1, padx=5, sticky="ew")
|
|
tb.Button(top_frame, text="Browse...", command=browse_template, bootstyle=SECONDARY).grid(row=1, column=2, padx=5)
|
|
|
|
metadata_frame = tb.Labelframe(top_frame, text="Template Placeholders", padding=10)
|
|
metadata_frame.grid(row=2, column=0, columnspan=3, padx=0, pady=10, sticky="ew")
|
|
|
|
tb.Label(metadata_frame, text="Document Number:").grid(row=0, column=0, padx=5, pady=3, sticky="w")
|
|
tb.Entry(metadata_frame, textvariable=doc_number_var).grid(row=0, column=1, padx=5, pady=3, sticky="ew")
|
|
tb.Label(metadata_frame, text="Revision:").grid(row=0, column=2, padx=(10, 5), pady=3, sticky="w")
|
|
tb.Entry(metadata_frame, textvariable=doc_rev_var).grid(row=0, column=3, padx=5, pady=3, sticky="ew")
|
|
tb.Label(metadata_frame, text="Project Name:").grid(row=1, column=0, padx=5, pady=3, sticky="w")
|
|
tb.Entry(metadata_frame, textvariable=doc_project_var).grid(row=1, column=1, padx=5, pady=3, sticky="ew")
|
|
tb.Label(metadata_frame, text="Customer:").grid(row=1, column=2, padx=(10, 5), pady=3, sticky="w")
|
|
tb.Entry(metadata_frame, textvariable=customer_var).grid(row=1, column=3, padx=5, pady=3, sticky="ew")
|
|
tb.Label(metadata_frame, text="Security Class:").grid(row=2, column=0, padx=5, pady=3, sticky="w")
|
|
tb.Entry(metadata_frame, textvariable=doc_security_var).grid(row=2, column=1, padx=5, pady=3, sticky="ew")
|
|
|
|
options_frame = tb.Frame(top_frame)
|
|
options_frame.grid(row=3, column=0, columnspan=3, pady=10, sticky="ew")
|
|
tb.Checkbutton(options_frame, text="Add Table of Contents", variable=add_toc_var, bootstyle="primary-round-toggle").pack(side=tk.LEFT, padx=(0, 20))
|
|
action_frame = tb.Frame(options_frame)
|
|
action_frame.pack(side=tk.LEFT)
|
|
tb.Button(action_frame, text="Convert to DOCX", command=lambda: convert("DOCX"), bootstyle=SUCCESS).pack(side=tk.LEFT, padx=5)
|
|
tb.Button(action_frame, text="Convert to PDF", command=lambda: convert("PDF"), bootstyle=SUCCESS).pack(side=tk.LEFT, padx=5)
|
|
tb.Button(action_frame, text="Open File", command=lambda: open_with_default_app(output_path.get()), bootstyle=WARNING).pack(side=tk.LEFT, padx=(20, 5))
|
|
tb.Button(action_frame, text="Open Folder", command=lambda: open_output_folder(output_path.get()), bootstyle=WARNING).pack(side=tk.LEFT, padx=5)
|
|
|
|
top_frame.columnconfigure(1, weight=1)
|
|
metadata_frame.columnconfigure(1, weight=1)
|
|
metadata_frame.columnconfigure(3, weight=1)
|
|
|
|
log_frame = tb.Labelframe(container, text="Log Viewer", padding=10)
|
|
log_frame.pack(fill=tk.BOTH, expand=True, side=tk.BOTTOM)
|
|
log_text_widget = ScrolledText(log_frame, wrap=tk.WORD, state=tk.DISABLED, height=10)
|
|
log_text_widget.pack(fill=tk.BOTH, expand=True)
|
|
|
|
add_tkinter_handler(gui_log_widget=log_text_widget, root_tk_instance_for_gui_handler=app, logging_config_dict=log_config)
|
|
|
|
def on_closing():
|
|
shutdown_logging_system()
|
|
app.destroy()
|
|
|
|
app.protocol("WM_DELETE_WINDOW", on_closing)
|
|
|
|
log.info("Application GUI initialized successfully.")
|
|
app.mainloop() |