import hashlib import os import tkinter as tk from tkinter import filedialog, messagebox, ttk from concurrent.futures import ThreadPoolExecutor, as_completed from collections import defaultdict def hash_file(file_path): hasher = hashlib.sha256() with open(file_path, "rb") as file: while True: data = file.read(8192) if not data: break hasher.update(data) return hasher.hexdigest() def find_duplicate_files(directory): file_hash_dict = defaultdict(list) duplicate_files = [] all_files = [] for root, dirs, files in os.walk(directory): for filename in files: file_path = os.path.join(root, filename) file_hash = hash_file(file_path) file_hash_dict[file_hash].append(file_path) all_files.append(file_path) for file_hash, file_paths in file_hash_dict.items(): if len(file_paths) > 1: duplicate_files.append("Duplicate Files (Hash: {})".format(file_hash)) duplicate_files.extend(file_paths) duplicate_files.append("\n") non_duplicate_files = [file for file in all_files if file not in duplicate_files] if duplicate_files: return "\n".join(duplicate_files), "\n".join(non_duplicate_files) else: return "No duplicate files found.", "\n".join(non_duplicate_files) def delete_files(): selected_files = file_list.tag_ranges("sel") if selected_files: if messagebox.askyesno("Confirm Deletion", "Are you sure you want to delete the selected files?"): for i in range(0, len(selected_files), 2): start = selected_files[i] end = selected_files[i + 1] file_paths = file_list.get(start, end).strip().split("\n") for file_path in file_paths: try: os.remove(file_path) except OSError as e: messagebox.showerror("Deletion Error", str(e)) return messagebox.showinfo("Deletion Complete!") scan_drive() def delete_duplicates(): selected_duplicates = duplicate_list.tag_ranges("sel") if selected_duplicates: if messagebox.askyesno("Confirm Deletion", "Are you sure you want to delete the selected duplicates?"): for i in range(0, len(selected_duplicates), 2): start = selected_duplicates[i] end = selected_duplicates[i + 1] file_paths = duplicate_list.get(start, end).strip().split("\n") for file_path in file_paths: try: os.remove(file_path) except OSError as e: messagebox.showerror("Deletion Error", str(e)) return messagebox.showinfo("Deletion Complete!") scan_drive() def scan_drive(): selected_drive = filedialog.askdirectory() if not selected_drive: messagebox.showwarning("No Drive Selected", "Please select a drive to scan.") return file_list.delete("1.0", tk.END) duplicate_list.delete("1.0", tk.END) executor = ThreadPoolExecutor() future = executor.submit(find_duplicate_files, selected_drive) window.after(100, check_scan_complete, future) def check_scan_complete(future): if future.done(): duplicate_files, non_duplicate_files = future.result() file_list.delete("1.0", tk.END) duplicate_list.delete("1.0", tk.END) if duplicate_files.startswith("Duplicate Files"): duplicate_list.insert(tk.END, duplicate_files) else: file_list.insert(tk.END, duplicate_files) file_list.insert(tk.END, non_duplicate_files) else: window.after(100, check_scan_complete, future) def save_settings(): selected_drive = drive_var.get() multithreaded = multithread_var.get() settings = { "drive": selected_drive, "multithreaded": multithreaded } # Save settings to a file or database messagebox.showinfo("Settings Saved", "Settings have been saved.") def load_settings(): # Load settings from a file or database # Example settings settings = { "drive": "C:/", "multithreaded": True } drive_var.set(settings.get("drive", "")) multithread_var.set(settings.get("multithreaded", False)) window = tk.Tk() window.title("Viento Aura") tab_control = ttk.Notebook(window) # Scan Tab scan_tab = ttk.Frame(tab_control) tab_control.add(scan_tab, text="Scan") scan_button = tk.Button(scan_tab, text="Scan Drive", command=scan_drive) scan_button.pack() file_list = tk.Text(scan_tab, height=10, width=80) file_list.pack() delete_button1 = tk.Button(scan_tab, text="Delete Selected Files", command=delete_files) delete_button1.pack() duplicate_list = tk.Text(scan_tab, height=10, width=80) duplicate_list.pack() delete_button2 = tk.Button(scan_tab, text="Delete Selected Duplicates", command=delete_duplicates) delete_button2.pack() # Settings Tab settings_tab = ttk.Frame(tab_control) tab_control.add(settings_tab, text="Settings") drive_label = tk.Label(settings_tab, text="Selected Drive:") drive_label.pack() drive_var = tk.StringVar() drive_entry = tk.Entry(settings_tab, textvariable=drive_var) drive_entry.pack() multithread_var = tk.BooleanVar() multithread_check = tk.Checkbutton(settings_tab, text="Enable Multithreading", variable=multithread_var) multithread_check.pack() save_button = tk.Button(settings_tab, text="Save Settings", command=save_settings) save_button.pack() tab_control.pack(expand=1, fill="both") # Load settings load_settings() window.focus_force() window.mainloop()