import os import time import threading import tkinter as tk from tkinter import ttk from tkcalendar import DateEntry from datetime import date from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import oracledb import getpass # Use thin mode (pure Python, no Oracle Client needed) # Oracle DB connection config DB_USERNAME = "Enter Database Username Here" DB_PASSWORD = "Enter Database Password Here" DB_HOST = "Enter Database Hostname Here" DB_SERVICENAME = "Enter Database Servicename here" sys_username = getpass.getuser() BASE_FOLDER = r"folder/path/here" def create_new_watch_folder(base_folder): """Create a new folder with numeric name, starting at 10001, incrementing each run.""" existing = [f for f in os.listdir(base_folder) if f.isdigit()] existing_nums = sorted([int(f) for f in existing]) global next_num if existing_nums: next_num = existing_nums[-1] + 1 else: next_num = 10001 new_folder = os.path.join(base_folder, str(next_num)) os.makedirs(new_folder, exist_ok=False) prompt_user() return new_folder # --- Custom Dialog with Dropdown --- class CustomInputDialog(tk.Toplevel): def __init__(self, parent): super().__init__(parent) self.title("File Info Input") self.result = None tk.Label(self, text = "Data for patient " +str(next_num)).pack(padx=10,pady=5) tk.Label(self, text="Enter the patient's first and last name:").pack(padx=10, pady=5) self.name_entry = tk.Entry(self) self.name_entry.pack(padx=10, pady=5) tk.Label(self, text="Sex of patient:").pack(padx=10, pady=5) self.sex_combo = ttk.Combobox(self, values=["Male", "Female"], state="readonly") self.sex_combo.current(0) self.sex_combo.pack(padx=10, pady=5) tk.Label(self, text="Race/ethnicity of patient:").pack(padx=10, pady=5) self.race_combo = ttk.Combobox(self, values=["American Native", "Asian", "Black", "Hispanic", "Middle Eastern", "Hawaiian or Pacific", "White"], state="readonly") self.race_combo.current(0) self.race_combo.pack(padx=10, pady=5) tk.Label(self, text="History of SHD:").pack(padx=10, pady=5) self.hiss_combo = ttk.Combobox(self, values=[0, 1], state="readonly") self.hiss_combo.current(0) self.hiss_combo.pack(padx=10, pady=5) tk.Label(self, text="History/Presence of AS").pack(padx=10, pady=5) self.hisa_combo = ttk.Combobox(self, values=[0, 1, 2, 3], state="readonly") self.hisa_combo.current(0) self.hisa_combo.pack(padx=10, pady=5) tk.Label(self, text="Patient date of birth:").pack(pady=5) self.date_picker = DateEntry(self, width=12, background='darkblue',foreground='white', borderwidth=2,date_pattern='yyyy-mm-dd') self.date_picker.pack(pady=5) button_frame = tk.Frame(self) button_frame.pack(pady=10) tk.Button(button_frame, text="OK", command=self.on_ok).pack(side=tk.LEFT, padx=5) tk.Button(button_frame, text="Cancel", command=self.on_cancel).pack(side=tk.LEFT, padx=5) self.protocol("WM_DELETE_WINDOW", self.on_cancel) self.grab_set() self.name_entry.focus_set() self.wait_window() def on_ok(self): self.result = { 'name': self.name_entry.get(), 'sex': self.sex_combo.get(), 'race': self.race_combo.get(), 'hiss': self.hiss_combo.get(), 'hisa': self.hisa_combo.get(), 'dob': self.date_picker.get_date() } self.destroy() def on_cancel(self): self.result = None self.destroy() # --- Prompt Function --- def prompt_user(): dialog = CustomInputDialog(root) if dialog.result is None: print("User cancelled input.") return global user_name user_name = dialog.result['name'] global sex sex = dialog.result['sex'] global race race = dialog.result['race'] global hiss hiss = dialog.result['hiss'] global hisa hisa = dialog.result['hisa'] global dob dob = dialog.result['dob'] today = date.today() global age age = (today - dob).days / 365.25 def insert_into_db(filename,filepath): try: with oracledb.connect(user=DB_USERNAME, password=DB_PASSWORD, host=DB_HOST, port=1521, service_name = DB_SERVICENAME) as conn: with conn.cursor() as cursor: cursor.execute(""" INSERT INTO table_name_here (name, dob, age, sex, race_eth, shd_hist, as_hist, file_path, study_date, usr_info, study_id) VALUES (:name, :dob, :age, :sex, :race, :hiss, :hisa, :path, SYSTIMESTAMP, :sys_user, :study_id) """, { 'name': user_name, 'dob': dob, 'age': age, 'sex': sex, 'race': race, 'hiss': hiss, 'hisa': hisa, 'path': filepath, 'sys_user': sys_username, 'study_id': int(filepath[27:32]) }) conn.commit() print(f"Inserted record for {filename}") except oracledb.Error as e: print("Oracle error:", e) # --- File Watcher Class --- class FileHandler(FileSystemEventHandler): def __init__(self, tk_root): self.tk_root = tk_root def on_created(self, event): if event.is_directory: return filepath = event.src_path filename = os.path.basename(filepath) print(f"[Watchdog] New file detected in {os.path.dirname(filepath)}") print(f" Name: {filename}") self.tk_root.after(0, lambda: insert_into_db(filename, filepath)) # --- Main Setup --- if __name__ == "__main__": root = tk.Tk() root.withdraw() # Step 1: Create new folder WATCHED_FOLDER = create_new_watch_folder(BASE_FOLDER) print(f"[Setup] Created and monitoring folder: {WATCHED_FOLDER}") # Step 2: Start watchdog event_handler = FileHandler(root) observer = Observer() observer.schedule(event_handler, path=WATCHED_FOLDER, recursive=False) observer.start() try: root.mainloop() except KeyboardInterrupt: observer.stop() observer.join()