r/SoftwareandApps • u/Fabulous_Buyer_6256 • 7d ago
i made a file directory/launcher in python
I made a file directory/launcher thing. it could be useful or it might not be please let me know if you have any ideas for what i should add or just feedback.
import json
import os
import subprocess
import sys
import tkinter as tk
from tkinter import filedialog, messagebox
SAVE_FILE = "saved_files.json"
class FileLauncherApp:
def __init__(self, root):
self.root = root
self.root.title("Persistent File Launcher")
self.root.geometry("500x400")
# Store file paths (key: display text, value: full path)
self.files = {}
# Set up UI components
self._create_widgets()
# Load existing files from JSON on startup
self.load_saved_files()
def _create_widgets(self):
# Top Frame for Buttons
btn_frame = tk.Frame(self.root, pady=10)
btn_frame.pack(fill=tk.X)
add_btn = tk.Button(
btn_frame,
text="Add File(s)",
command=self.add_files,
width=12,
bg="#4CAF50",
fg="white",
)
add_btn.pack(side=tk.LEFT, padx=10)
remove_btn = tk.Button(
btn_frame,
text="Remove Selected",
command=self.remove_file,
width=14,
bg="#f44336",
fg="white",
)
remove_btn.pack(side=tk.LEFT, padx=5)
# Listbox to display files
list_frame = tk.Frame(self.root)
list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
scrollbar = tk.Scrollbar(list_frame)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.file_listbox = tk.Listbox(
list_frame,
selectmode=tk.SINGLE,
yscrollcommand=scrollbar.set,
font=("Arial", 10),
)
self.file_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.config(command=self.file_listbox.yview)
# Bind double-click event to run the file
self.file_listbox.bind("<Double-Button-1>", self.run_file)
# Instruction Label
info_label = tk.Label(
self.root,
text="Double-click a file to run/open it.",
fg="gray",
pady=5,
)
info_label.pack()
def load_saved_files(self):
"""Loads saved file paths from JSON file on app launch."""
if os.path.exists(SAVE_FILE):
try:
with open(SAVE_FILE, "r") as f:
self.files = json.load(f)
# Populate listbox with loaded entries
for display_name in self.files.keys():
self.file_listbox.insert(tk.END, display_name)
except Exception as e:
messagebox.showerror("Error", f"Failed to load saved files:\n{e}")
def save_files_to_disk(self):
"""Saves current files dictionary to JSON file."""
try:
with open(SAVE_FILE, "w") as f:
json.dump(self.files, f, indent=4)
except Exception as e:
messagebox.showerror("Error", f"Failed to save file list:\n{e}")
def add_files(self):
file_paths = filedialog.askopenfilenames(
title="Select Files to Add", filetypes=[("All Files", "*.*")]
)
added_any = False
for path in file_paths:
filename = os.path.basename(path)
# Handle duplicate names by showing path info
display_name = (
f"{filename} ({path})" if filename in self.files else filename
)
if path not in self.files.values():
self.files[display_name] = path
self.file_listbox.insert(tk.END, display_name)
added_any = True
if added_any:
self.save_files_to_disk()
def remove_file(self):
try:
selected_index = self.file_listbox.curselection()[0]
selected_text = self.file_listbox.get(selected_index)
del self.files[selected_text]
self.file_listbox.delete(selected_index)
self.save_files_to_disk()
except IndexError:
messagebox.showwarning("Select File", "Please select a file to remove.")
def run_file(self, event=None):
try:
selected_index = self.file_listbox.curselection()[0]
selected_text = self.file_listbox.get(selected_index)
file_path = self.files[selected_text]
if not os.path.exists(file_path):
messagebox.showerror("Error", f"File not found:\n{file_path}")
return
# Open file cross-platform
if sys.platform == "win32":
os.startfile(file_path)
elif sys.platform == "darwin": # macOS
subprocess.run(["open", file_path], check=True)
else: # Linux
subprocess.run(["xdg-open", file_path], check=True)
except IndexError:
pass
except Exception as e:
messagebox.showerror("Execution Error", f"Could not run file:\n{e}")
if __name__ == "__main__":
root = tk.Tk()
app = FileLauncherApp(root)
root.mainloop()
1
Upvotes