130 lines
4.5 KiB
Python
130 lines
4.5 KiB
Python
# pyhasher/gui/gui.py
|
|
|
|
import tkinter as tk
|
|
from tkinter import filedialog, messagebox
|
|
import os
|
|
|
|
# Import the core logic function
|
|
from pyhasher.core.core import calculate_hashes_for_file
|
|
|
|
# Defines the order in which hashes will be displayed in the GUI.
|
|
# This must match the keys returned by the core function.
|
|
HASH_DISPLAY_ORDER = (
|
|
"CRC32",
|
|
"Adler-32",
|
|
"MD5",
|
|
"SHA-1",
|
|
"SHA-256",
|
|
"SHA-384",
|
|
"SHA-512",
|
|
"SHA3-256",
|
|
"BLAKE2b",
|
|
)
|
|
|
|
class PyHasherApp:
|
|
"""
|
|
The main GUI application class for PyHasher.
|
|
It handles the user interface and interactions.
|
|
"""
|
|
def __init__(self, root_window):
|
|
"""
|
|
Initialize the application.
|
|
|
|
Args:
|
|
root_window: The main tkinter window.
|
|
"""
|
|
self.root = root_window
|
|
self.root.title("PyHasher")
|
|
self.root.geometry("1024x400") # Increased height for more hashes
|
|
self.file_path = tk.StringVar()
|
|
|
|
# --- Main frame ---
|
|
main_frame = tk.Frame(self.root, padx=10, pady=10)
|
|
main_frame.pack(fill=tk.BOTH, expand=True)
|
|
|
|
# --- File selection widgets ---
|
|
self._create_file_selection_widgets(main_frame)
|
|
|
|
# --- Hash results widgets ---
|
|
self._create_hash_display_widgets(main_frame)
|
|
|
|
# --- Action buttons ---
|
|
self._create_action_buttons(main_frame)
|
|
|
|
def _create_file_selection_widgets(self, parent_frame):
|
|
"""Creates widgets for file selection."""
|
|
file_frame = tk.Frame(parent_frame)
|
|
file_frame.pack(fill=tk.X, pady=(0, 10))
|
|
|
|
file_label = tk.Label(file_frame, text="File:")
|
|
file_label.pack(side=tk.LEFT, padx=(0, 5))
|
|
|
|
file_entry = tk.Entry(file_frame, textvariable=self.file_path, state="readonly")
|
|
file_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
|
|
|
browse_button = tk.Button(file_frame, text="Browse...", command=self.select_file)
|
|
browse_button.pack(side=tk.LEFT, padx=(5, 0))
|
|
|
|
def _create_hash_display_widgets(self, parent_frame):
|
|
"""Creates labels and entry boxes for displaying hash results."""
|
|
results_frame = tk.Frame(parent_frame)
|
|
results_frame.pack(fill=tk.BOTH, expand=True)
|
|
|
|
# Dictionary to hold hash names and their corresponding tk.StringVar
|
|
self.hash_vars = {name: tk.StringVar() for name in HASH_DISPLAY_ORDER}
|
|
|
|
# Create labels and read-only entry widgets for each hash type
|
|
for i, name in enumerate(HASH_DISPLAY_ORDER):
|
|
label = tk.Label(results_frame, text=f"{name}:")
|
|
label.grid(row=i, column=0, sticky="w", pady=2)
|
|
|
|
entry = tk.Entry(results_frame, textvariable=self.hash_vars[name], state="readonly")
|
|
entry.grid(row=i, column=1, sticky="ew", pady=2, padx=(5, 0))
|
|
|
|
# Configure the grid to expand the entry column
|
|
results_frame.columnconfigure(1, weight=1)
|
|
|
|
def _create_action_buttons(self, parent_frame):
|
|
"""Creates the main action buttons."""
|
|
button_frame = tk.Frame(parent_frame)
|
|
button_frame.pack(fill=tk.X, pady=(10, 0), side=tk.BOTTOM)
|
|
|
|
calculate_button = tk.Button(
|
|
button_frame,
|
|
text="Calculate Hashes",
|
|
command=self.calculate_hashes
|
|
)
|
|
calculate_button.pack(side=tk.RIGHT)
|
|
|
|
def select_file(self):
|
|
"""Opens a file dialog to select a file and clears old results."""
|
|
path = filedialog.askopenfilename()
|
|
if path:
|
|
self.file_path.set(path)
|
|
# Clear previous results when a new file is selected
|
|
for var in self.hash_vars.values():
|
|
var.set("")
|
|
|
|
def calculate_hashes(self):
|
|
"""
|
|
Gets the file path, calls the core function to calculate hashes,
|
|
and displays the results in the GUI.
|
|
"""
|
|
current_file_path = self.file_path.get()
|
|
if not current_file_path or not os.path.exists(current_file_path):
|
|
messagebox.showerror("Error", "Please select a valid file first.")
|
|
return
|
|
|
|
try:
|
|
# Call the decoupled core function to do the heavy lifting
|
|
all_hashes = calculate_hashes_for_file(current_file_path)
|
|
|
|
# Update the GUI with the results from the core function
|
|
for name, value in all_hashes.items():
|
|
if name in self.hash_vars:
|
|
self.hash_vars[name].set(value)
|
|
|
|
except IOError as e:
|
|
messagebox.showerror("Error", f"Could not read file: {e}")
|
|
except Exception as e:
|
|
messagebox.showerror("Error", f"An unexpected error occurred: {e}") |