diff --git a/src/main.py b/src/main.py index 47594be..e958fa2 100644 --- a/src/main.py +++ b/src/main.py @@ -1,12 +1,14 @@ -import tkinter as tk -from tkinter import ttk, messagebox import csv import os +import tkinter as tk from datetime import datetime -import pandas as pd +from tkinter import messagebox, ttk + import matplotlib.pyplot as plt +import pandas as pd from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg + class MedTrackerApp: def __init__(self, root): self.root = root @@ -23,55 +25,93 @@ class MedTrackerApp: input_frame = ttk.LabelFrame(main_frame, text="New Entry") input_frame.grid(row=0, column=0, padx=10, pady=10, sticky="ew") - ttk.Label(input_frame, text="Depression (1-10):").grid(row=0, column=0, sticky="w", padx=5, pady=2) + ttk.Label(input_frame, text="Depression (1-10):").grid( + row=0, column=0, sticky="w", padx=5, pady=2 + ) self.depression_var = tk.IntVar() - ttk.Scale(input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.depression_var).grid(row=0, column=1, sticky="ew") + ttk.Scale( + input_frame, + from_=1, + to=10, + orient=tk.HORIZONTAL, + variable=self.depression_var, + ).grid(row=0, column=1, sticky="ew") - ttk.Label(input_frame, text="Anxiety (1-10):").grid(row=1, column=0, sticky="w", padx=5, pady=2) + ttk.Label(input_frame, text="Anxiety (1-10):").grid( + row=1, column=0, sticky="w", padx=5, pady=2 + ) self.anxiety_var = tk.IntVar() - ttk.Scale(input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.anxiety_var).grid(row=1, column=1, sticky="ew") + ttk.Scale( + input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.anxiety_var + ).grid(row=1, column=1, sticky="ew") - ttk.Label(input_frame, text="Sleep Quality (1-10):").grid(row=2, column=0, sticky="w", padx=5, pady=2) + ttk.Label(input_frame, text="Sleep Quality (1-10):").grid( + row=2, column=0, sticky="w", padx=5, pady=2 + ) self.sleep_var = tk.IntVar() - ttk.Scale(input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.sleep_var).grid(row=2, column=1, sticky="ew") + ttk.Scale( + input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.sleep_var + ).grid(row=2, column=1, sticky="ew") - ttk.Label(input_frame, text="Appetite (1-10):").grid(row=3, column=0, sticky="w", padx=5, pady=2) + ttk.Label(input_frame, text="Appetite (1-10):").grid( + row=3, column=0, sticky="w", padx=5, pady=2 + ) self.appetite_var = tk.IntVar() - ttk.Scale(input_frame, from_=1, to=10, orient=tk.HORIZONTAL, variable=self.appetite_var).grid(row=3, column=1, sticky="ew") + ttk.Scale( + input_frame, + from_=1, + to=10, + orient=tk.HORIZONTAL, + variable=self.appetite_var, + ).grid(row=3, column=1, sticky="ew") - ttk.Label(input_frame, text="Note:").grid(row=4, column=0, sticky="w", padx=5, pady=2) + ttk.Label(input_frame, text="Note:").grid( + row=4, column=0, sticky="w", padx=5, pady=2 + ) self.note_var = tk.StringVar() - ttk.Entry(input_frame, textvariable=self.note_var).grid(row=4, column=1, sticky="ew", padx=5, pady=2) + ttk.Entry(input_frame, textvariable=self.note_var).grid( + row=4, column=1, sticky="ew", padx=5, pady=2 + ) button_frame = ttk.Frame(input_frame) button_frame.grid(row=5, column=0, columnspan=2, pady=10) - ttk.Button(button_frame, text="Add Entry", command=self.add_entry).pack(side="left", padx=5) - ttk.Button(button_frame, text="Quit", command=self.on_closing).pack(side="left", padx=5) + ttk.Button(button_frame, text="Add Entry", command=self.add_entry).pack( + side="left", padx=5 + ) + ttk.Button(button_frame, text="Quit", command=self.on_closing).pack( + side="left", padx=5 + ) # --- Table Frame --- table_frame = ttk.LabelFrame(main_frame, text="Log (Double-click to edit)") table_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew") - self.tree = ttk.Treeview(table_frame, columns=("Timestamp", "Depression", "Anxiety", "Sleep", "Appetite", "Note"), show="headings") + self.tree = ttk.Treeview( + table_frame, + columns=("Timestamp", "Depression", "Anxiety", "Sleep", "Appetite", "Note"), + show="headings", + ) self.tree.heading("Timestamp", text="Timestamp") self.tree.heading("Depression", text="Depression") self.tree.heading("Anxiety", text="Anxiety") self.tree.heading("Sleep", text="Sleep") self.tree.heading("Appetite", text="Appetite") self.tree.heading("Note", text="Note") - + # --- NEW: Bind double-click event --- self.tree.bind("", self.on_double_click) self.tree.pack(side="left", fill="both", expand=True) - scrollbar = ttk.Scrollbar(table_frame, orient="vertical", command=self.tree.yview) + scrollbar = ttk.Scrollbar( + table_frame, orient="vertical", command=self.tree.yview + ) self.tree.configure(yscrollcommand=scrollbar.set) scrollbar.pack(side="right", fill="y") # --- Graph Frame --- graph_frame = ttk.LabelFrame(main_frame, text="Evolution") graph_frame.grid(row=0, column=1, rowspan=2, padx=10, pady=10, sticky="nsew") - + self.fig, self.ax = plt.subplots() self.canvas = FigureCanvasTkAgg(self.fig, master=graph_frame) self.canvas.get_tk_widget().pack(fill="both", expand=True) @@ -101,29 +141,59 @@ class MedTrackerApp: slp_var = tk.IntVar(value=int(slp)) app_var = tk.IntVar(value=int(app)) note_var = tk.StringVar(value=note) - + # Create form widgets - ttk.Label(edit_win, text=f"Timestamp: {ts}").grid(row=0, column=0, columnspan=2, padx=5, pady=5) - - ttk.Label(edit_win, text="Depression:").grid(row=1, column=0, sticky="w", padx=5, pady=2) - ttk.Scale(edit_win, from_=1, to=10, variable=dep_var, orient=tk.HORIZONTAL).grid(row=1, column=1, sticky="ew") - - ttk.Label(edit_win, text="Anxiety:").grid(row=2, column=0, sticky="w", padx=5, pady=2) - ttk.Scale(edit_win, from_=1, to=10, variable=anx_var, orient=tk.HORIZONTAL).grid(row=2, column=1, sticky="ew") - - ttk.Label(edit_win, text="Sleep:").grid(row=3, column=0, sticky="w", padx=5, pady=2) - ttk.Scale(edit_win, from_=1, to=10, variable=slp_var, orient=tk.HORIZONTAL).grid(row=3, column=1, sticky="ew") + ttk.Label(edit_win, text=f"Timestamp: {ts}").grid( + row=0, column=0, columnspan=2, padx=5, pady=5 + ) - ttk.Label(edit_win, text="Appetite:").grid(row=4, column=0, sticky="w", padx=5, pady=2) - ttk.Scale(edit_win, from_=1, to=10, variable=app_var, orient=tk.HORIZONTAL).grid(row=4, column=1, sticky="ew") + ttk.Label(edit_win, text="Depression:").grid( + row=1, column=0, sticky="w", padx=5, pady=2 + ) + ttk.Scale( + edit_win, from_=1, to=10, variable=dep_var, orient=tk.HORIZONTAL + ).grid(row=1, column=1, sticky="ew") - ttk.Label(edit_win, text="Note:").grid(row=5, column=0, sticky="w", padx=5, pady=2) + ttk.Label(edit_win, text="Anxiety:").grid( + row=2, column=0, sticky="w", padx=5, pady=2 + ) + ttk.Scale( + edit_win, from_=1, to=10, variable=anx_var, orient=tk.HORIZONTAL + ).grid(row=2, column=1, sticky="ew") + + ttk.Label(edit_win, text="Sleep:").grid( + row=3, column=0, sticky="w", padx=5, pady=2 + ) + ttk.Scale( + edit_win, from_=1, to=10, variable=slp_var, orient=tk.HORIZONTAL + ).grid(row=3, column=1, sticky="ew") + + ttk.Label(edit_win, text="Appetite:").grid( + row=4, column=0, sticky="w", padx=5, pady=2 + ) + ttk.Scale( + edit_win, from_=1, to=10, variable=app_var, orient=tk.HORIZONTAL + ).grid(row=4, column=1, sticky="ew") + + ttk.Label(edit_win, text="Note:").grid( + row=5, column=0, sticky="w", padx=5, pady=2 + ) ttk.Entry(edit_win, textvariable=note_var).grid(row=5, column=1, sticky="ew") # Save and Cancel buttons - save_btn = ttk.Button(edit_win, text="Save", command=lambda: self.save_edit( - edit_win, ts, dep_var.get(), anx_var.get(), slp_var.get(), app_var.get(), note_var.get() - )) + save_btn = ttk.Button( + edit_win, + text="Save", + command=lambda: self.save_edit( + edit_win, + ts, + dep_var.get(), + anx_var.get(), + slp_var.get(), + app_var.get(), + note_var.get(), + ), + ) save_btn.grid(row=6, column=0, padx=5, pady=10) cancel_btn = ttk.Button(edit_win, text="Cancel", command=edit_win.destroy) @@ -133,10 +203,13 @@ class MedTrackerApp: """Save the edited data to the CSV file.""" df = pd.read_csv(self.filename) # Find the row to update using the timestamp as a unique identifier - df.loc[df['timestamp'] == timestamp, ['depression', 'anxiety', 'sleep', 'appetite', 'note']] = [dep, anx, slp, app, note] + df.loc[ + df["timestamp"] == timestamp, + ["depression", "anxiety", "sleep", "appetite", "note"], + ] = [dep, anx, slp, app, note] # Write the updated dataframe back to the CSV df.to_csv(self.filename, index=False) - + edit_win.destroy() messagebox.showinfo("Success", "Entry updated successfully!") self.load_data() @@ -148,20 +221,31 @@ class MedTrackerApp: def initialize_csv(self): if not os.path.exists(self.filename): - with open(self.filename, mode='w', newline='') as file: + with open(self.filename, mode="w", newline="") as file: writer = csv.writer(file) - writer.writerow(["timestamp", "depression", "anxiety", "sleep", "appetite", "note"]) + writer.writerow( + ["timestamp", "depression", "anxiety", "sleep", "appetite", "note"] + ) def add_entry(self): timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - with open(self.filename, mode='a', newline='') as file: + with open(self.filename, mode="a", newline="") as file: writer = csv.writer(file) - writer.writerow([timestamp, self.depression_var.get(), self.anxiety_var.get(), self.sleep_var.get(), self.appetite_var.get(), self.note_var.get()]) - + writer.writerow( + [ + timestamp, + self.depression_var.get(), + self.anxiety_var.get(), + self.sleep_var.get(), + self.appetite_var.get(), + self.note_var.get(), + ] + ) + messagebox.showinfo("Success", "Entry added successfully!") self.clear_entries() self.load_data() - + def clear_entries(self): self.depression_var.set(0) self.anxiety_var.set(0) @@ -172,12 +256,12 @@ class MedTrackerApp: def load_data(self): for i in self.tree.get_children(): self.tree.delete(i) - + if os.path.exists(self.filename) and os.path.getsize(self.filename) > 0: try: - df = pd.read_csv(self.filename, dtype={'note': str}).fillna('') + df = pd.read_csv(self.filename, dtype={"note": str}).fillna("") # Sort by timestamp to keep order consistent - df = df.sort_values(by='timestamp').reset_index(drop=True) + df = df.sort_values(by="timestamp").reset_index(drop=True) for index, row in df.iterrows(): self.tree.insert("", "end", values=list(row)) self.update_graph(df) @@ -187,12 +271,24 @@ class MedTrackerApp: def update_graph(self, df): self.ax.clear() if not df.empty: - df['timestamp'] = pd.to_datetime(df['timestamp']) - df.set_index('timestamp', inplace=True) - self.ax.plot(df.index, df['depression'], marker='o', linestyle='-', label='Depression') - self.ax.plot(df.index, df['anxiety'], marker='o', linestyle='-', label='Anxiety') - self.ax.plot(df.index, df['sleep'], marker='o', linestyle='-', label='Sleep') - self.ax.plot(df.index, df['appetite'], marker='o', linestyle='-', label='Appetite') + df["timestamp"] = pd.to_datetime(df["timestamp"]) + df.set_index("timestamp", inplace=True) + self.ax.plot( + df.index, + df["depression"], + marker="o", + linestyle="-", + label="Depression", + ) + self.ax.plot( + df.index, df["anxiety"], marker="o", linestyle="-", label="Anxiety" + ) + self.ax.plot( + df.index, df["sleep"], marker="o", linestyle="-", label="Sleep" + ) + self.ax.plot( + df.index, df["appetite"], marker="o", linestyle="-", label="Appetite" + ) self.ax.legend() self.ax.set_title("Medication Effects Over Time") self.ax.set_xlabel("Date") @@ -200,7 +296,8 @@ class MedTrackerApp: self.fig.autofmt_xdate() self.canvas.draw() + if __name__ == "__main__": root = tk.Tk() app = MedTrackerApp(root) - root.mainloop() \ No newline at end of file + root.mainloop()