import tkinter as tk from tkinter import ttk, messagebox import sqlite3 from pathlib import Path ROOT = Path(__file__).resolve().parent DB = ROOT / "address_book.db" root = tk.Tk() root.title("Address Book") root.geometry("620x620") root.resizable(False, False) def connect(): return sqlite3.connect(DB) def clear_entries(): f_name.delete(0, tk.END) s_name.delete(0, tk.END) mob.delete(0, tk.END) email.delete(0, tk.END) def submit(): values = ( f_name.get().strip(), s_name.get().strip(), mob.get().strip(), email.get().strip(), ) if not all(values): messagebox.showwarning("Missing data", "Please fill in all four fields.") return conn = connect() c = conn.cursor() c.execute( """ INSERT INTO address_book (f_name, s_name, mob, email) VALUES (?, ?, ?, ?) """, values, ) conn.commit() conn.close() clear_entries() search() def search(): conn = connect() c = conn.cursor() c.execute(""" SELECT f_name, s_name, mob, email, oid FROM address_book ORDER BY oid """) records = c.fetchall() conn.close() output.delete("1.0", tk.END) if not records: output.insert(tk.END, "No records found.") return for record in records: output.insert( tk.END, f"OID: {record[4]} | " f"{record[0]} {record[1]} | " f"Mobile: {record[2]} | " f"Email: {record[3]}\n" ) def delete_rec(): oid = id_no.get().strip() if not oid.isdigit(): messagebox.showwarning("Invalid OID", "Enter a valid numeric OID.") return conn = connect() c = conn.cursor() c.execute("DELETE FROM address_book WHERE oid = ?", (int(oid),)) deleted = c.rowcount conn.commit() conn.close() id_no.delete(0, tk.END) if deleted: messagebox.showinfo("Deleted", f"Record {oid} was deleted.") else: messagebox.showwarning("Not found", f"No record with OID {oid} exists.") search() def update_rec(): oid = id_no.get().strip() column = update_column.get() value = update_value.get().strip() allowed_columns = { "First Name": "f_name", "Surname": "s_name", "Mobile": "mob", "Email": "email", } if not oid.isdigit(): messagebox.showwarning("Invalid OID", "Enter a valid numeric OID.") return if not value: messagebox.showwarning("Missing value", "Enter the new value.") return # The column name cannot be passed as a normal SQL parameter, # so only a value from this fixed whitelist is allowed. db_column = allowed_columns[column] conn = connect() c = conn.cursor() sql = "UPDATE address_book SET {} = ? WHERE oid = ?".format(db_column) c.execute(sql, (value, int(oid))) updated = c.rowcount conn.commit() conn.close() if updated: messagebox.showinfo( "Updated", f"Record {oid} was updated successfully." ) id_no.delete(0, tk.END) update_value.delete(0, tk.END) search() else: messagebox.showwarning( "Not found", f"No record with OID {oid} exists." ) # Create database/table if it does not already exist. conn = connect() c = conn.cursor() c.execute(""" CREATE TABLE IF NOT EXISTS address_book ( f_name TEXT, s_name TEXT, mob TEXT, email TEXT ) """) conn.commit() conn.close() # ---------- GUI ---------- tk.Label(root, text="First Name").grid(row=0, column=0, sticky="e", padx=8, pady=6) f_name = tk.Entry(root, width=35) f_name.grid(row=0, column=1, padx=8, pady=6) tk.Label(root, text="Surname").grid(row=1, column=0, sticky="e", padx=8, pady=6) s_name = tk.Entry(root, width=35) s_name.grid(row=1, column=1, padx=8, pady=6) tk.Label(root, text="Mobile").grid(row=2, column=0, sticky="e", padx=8, pady=6) mob = tk.Entry(root, width=35) mob.grid(row=2, column=1, padx=8, pady=6) tk.Label(root, text="Email").grid(row=3, column=0, sticky="e", padx=8, pady=6) email = tk.Entry(root, width=35) email.grid(row=3, column=1, padx=8, pady=6) tk.Button(root, text="Save", command=submit, width=14).grid( row=4, column=0, padx=8, pady=10 ) tk.Button(root, text="Display all", command=search, width=14).grid( row=4, column=1, sticky="w", padx=8, pady=10 ) tk.Label(root, text="Enter OID").grid(row=5, column=0, sticky="e", padx=8, pady=6) id_no = tk.Entry(root, width=35) id_no.grid(row=5, column=1, padx=8, pady=6) tk.Button(root, text="Delete", command=delete_rec, width=14).grid( row=6, column=0, padx=8, pady=8 ) tk.Label(root, text="Update field").grid(row=7, column=0, sticky="e", padx=8, pady=6) update_column = ttk.Combobox( root, values=("First Name", "Surname", "Mobile", "Email"), state="readonly", width=32, ) update_column.current(0) update_column.grid(row=7, column=1, padx=8, pady=6) tk.Label(root, text="New value").grid(row=8, column=0, sticky="e", padx=8, pady=6) update_value = tk.Entry(root, width=35) update_value.grid(row=8, column=1, padx=8, pady=6) tk.Button(root, text="Update", command=update_rec, width=14).grid( row=9, column=0, columnspan=2, pady=8 ) output = tk.Text(root, width=72, height=13, wrap="word") output.grid(row=10, column=0, columnspan=2, padx=10, pady=12) search() root.mainloop()