165 lines
5.9 KiB
Python
165 lines
5.9 KiB
Python
import tkinter as tk
|
|
from tkinter import scrolledtext, messagebox, filedialog, ttk
|
|
import markdown
|
|
from fpdf import FPDF
|
|
from typing import Optional
|
|
|
|
# It's better to manage this path from the main application later,
|
|
# but for now, we keep it simple.
|
|
HELP_MARKDOWN_FILE = "help.md"
|
|
|
|
class HelpWindow(tk.Toplevel):
|
|
"""
|
|
A Toplevel window that displays help content from a Markdown file.
|
|
|
|
The window provides options to export the content to HTML or PDF.
|
|
"""
|
|
|
|
def __init__(self, master: tk.Tk):
|
|
"""
|
|
Initializes the help window.
|
|
|
|
Args:
|
|
master: The parent tk.Tk window.
|
|
"""
|
|
super().__init__(master)
|
|
self.title("Radalyze - Help")
|
|
self.geometry("800x600")
|
|
|
|
self._help_content: Optional[str] = None
|
|
|
|
self._create_widgets()
|
|
self._load_and_display_help()
|
|
self._center_window()
|
|
|
|
def _create_widgets(self) -> None:
|
|
"""Creates and arranges the widgets in the window."""
|
|
# --- Toolbar ---
|
|
toolbar_frame = ttk.Frame(self)
|
|
toolbar_frame.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)
|
|
|
|
export_html_button = ttk.Button(
|
|
toolbar_frame, text="Export to HTML", command=self._export_to_html
|
|
)
|
|
export_html_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
export_pdf_button = ttk.Button(
|
|
toolbar_frame, text="Export to PDF", command=self._export_to_pdf
|
|
)
|
|
export_pdf_button.pack(side=tk.LEFT, padx=5)
|
|
|
|
# --- Text Area ---
|
|
self._text_widget = scrolledtext.ScrolledText(self, wrap=tk.WORD, padx=5)
|
|
self._text_widget.pack(expand=True, fill="both")
|
|
self._text_widget.config(state=tk.DISABLED) # Make it read-only
|
|
|
|
def _load_and_display_help(self) -> None:
|
|
"""Loads the content from the Markdown file and displays it."""
|
|
try:
|
|
with open(HELP_MARKDOWN_FILE, "r", encoding="utf-8") as f:
|
|
self._help_content = f.read()
|
|
|
|
self._text_widget.config(state=tk.NORMAL)
|
|
self._text_widget.delete("1.0", tk.END)
|
|
self._text_widget.insert(tk.INSERT, self._help_content)
|
|
self._text_widget.config(state=tk.DISABLED)
|
|
|
|
except FileNotFoundError:
|
|
self._show_error(f"Help file not found: '{HELP_MARKDOWN_FILE}'")
|
|
except Exception as e:
|
|
self._show_error(f"An error occurred while reading the help file: {e}")
|
|
|
|
def _export_to_html(self) -> None:
|
|
"""Exports the help content to an HTML file."""
|
|
if not self._help_content:
|
|
self._show_error("Help content is not loaded. Cannot export.")
|
|
return
|
|
|
|
save_path = filedialog.asksaveasfilename(
|
|
title="Save Help as HTML",
|
|
defaultextension=".html",
|
|
filetypes=[("HTML files", "*.html"), ("All files", "*.*")]
|
|
)
|
|
if not save_path:
|
|
return # User cancelled
|
|
|
|
try:
|
|
html_content = markdown.markdown(self._help_content)
|
|
with open(save_path, "w", encoding="utf-8") as f:
|
|
f.write(html_content)
|
|
messagebox.showinfo(
|
|
"Export Successful", f"Help content successfully saved to:\n{save_path}", parent=self
|
|
)
|
|
except Exception as e:
|
|
self._show_error(f"Failed to export to HTML: {e}")
|
|
|
|
def _export_to_pdf(self) -> None:
|
|
"""Exports the help content to a PDF file."""
|
|
if not self._help_content:
|
|
self._show_error("Help content is not loaded. Cannot export.")
|
|
return
|
|
|
|
save_path = filedialog.asksaveasfilename(
|
|
title="Save Help as PDF",
|
|
defaultextension=".pdf",
|
|
filetypes=[("PDF files", "*.pdf"), ("All files", "*.*")]
|
|
)
|
|
if not save_path:
|
|
return # User cancelled
|
|
|
|
try:
|
|
pdf = self._create_pdf_from_markdown(self._help_content)
|
|
pdf.output(save_path)
|
|
messagebox.showinfo(
|
|
"Export Successful", f"Help content successfully saved to:\n{save_path}", parent=self
|
|
)
|
|
except Exception as e:
|
|
self._show_error(f"Failed to export to PDF: {e}")
|
|
|
|
@staticmethod
|
|
def _create_pdf_from_markdown(markdown_text: str) -> FPDF:
|
|
"""
|
|
Creates an FPDF object from a Markdown string.
|
|
|
|
This is a basic parser and handles headings (#) and list items (*).
|
|
"""
|
|
pdf = FPDF()
|
|
pdf.add_page()
|
|
pdf.set_font("Arial", size=12)
|
|
|
|
for line in markdown_text.split('\n'):
|
|
line = line.strip()
|
|
if line.startswith('#'):
|
|
level = line.find(' ')
|
|
text = line[level:].strip()
|
|
size = max(12, 20 - 2 * level)
|
|
pdf.set_font("Arial", 'B', size=size)
|
|
pdf.multi_cell(0, 10, text, 0, 'L')
|
|
pdf.set_font("Arial", size=12)
|
|
elif line.startswith('*'):
|
|
text = line[1:].strip()
|
|
pdf.set_x(15)
|
|
pdf.multi_cell(0, 5, f"• {text}")
|
|
pdf.set_x(10)
|
|
else:
|
|
pdf.multi_cell(0, 5, line)
|
|
|
|
if not line: # Add a small space for empty lines
|
|
pdf.ln(5)
|
|
|
|
return pdf
|
|
|
|
def _center_window(self) -> None:
|
|
"""Centers the window on the screen."""
|
|
self.update_idletasks()
|
|
screen_width = self.winfo_screenwidth()
|
|
screen_height = self.winfo_screenheight()
|
|
window_width = self.winfo_width()
|
|
window_height = self.winfo_height()
|
|
pos_x = (screen_width // 2) - (window_width // 2)
|
|
pos_y = (screen_height // 2) - (window_height // 2)
|
|
self.geometry(f"+{pos_x}+{pos_y}")
|
|
|
|
def _show_error(self, message: str) -> None:
|
|
"""Convenience method to show an error message box."""
|
|
messagebox.showerror("Help Window Error", message, parent=self) |