|
| 1 | +import customtkinter |
| 2 | +from tkinter import * |
| 3 | +from tkinter import ttk |
| 4 | +import tkinter as tk |
| 5 | +from tkinter import messagebox, filedialog |
| 6 | +import database |
| 7 | +import csv |
| 8 | + |
| 9 | +app = customtkinter.CTk() |
| 10 | +app.title('Database Management System') |
| 11 | +app.geometry('1300x760') |
| 12 | +app.config(bg='#161C25') |
| 13 | +app.resizable(False, False) |
| 14 | + |
| 15 | +font1 = ('Arial', 20, 'bold') |
| 16 | +font2 = ('Arial', 12, 'bold') |
| 17 | + |
| 18 | + |
| 19 | +def add_to_treeview(): |
| 20 | + data = database.fetch_data() |
| 21 | + print("Fetched Data for TreeView:", data) # Debugging print to check fetched data |
| 22 | + tree.delete(*tree.get_children()) |
| 23 | + for item in data: |
| 24 | + tree.insert('', END, values=item) |
| 25 | + print("TreeView updated.") |
| 26 | + |
| 27 | + |
| 28 | +def clear(*clicked): |
| 29 | + if clicked: |
| 30 | + tree.selection_remove(tree.focus()) |
| 31 | + tree.focus('') |
| 32 | + id_entry.delete(0, END) |
| 33 | + name_entry.delete(0, END) |
| 34 | + desc_entry.delete(0, END) |
| 35 | + variable1.set('Male') |
| 36 | + variable2.set('Select') |
| 37 | + status_entry.delete(0, END) |
| 38 | + email_entry.delete(0, END) |
| 39 | + title_entry.delete(0, END) |
| 40 | + number_entry.delete(0, END) |
| 41 | + |
| 42 | + |
| 43 | +def display_data(event): |
| 44 | + selected_item = tree.focus() |
| 45 | + if selected_item: |
| 46 | + row = tree.item(selected_item)['values'] |
| 47 | + clear() |
| 48 | + id_entry.insert(0, row[0]) |
| 49 | + name_entry.insert(0, row[1]) |
| 50 | + desc_entry.insert(0, row[2]) |
| 51 | + variable2.set(row[3]) |
| 52 | + email_entry.insert(0, row[4]) |
| 53 | + variable1.set(row[5]) |
| 54 | + title_entry.insert(0, row[6]) |
| 55 | + number_entry.insert(0, row[7]) |
| 56 | + else: |
| 57 | + pass |
| 58 | + |
| 59 | + |
| 60 | +def delete(): |
| 61 | + selected_item = tree.focus() |
| 62 | + if not selected_item: |
| 63 | + messagebox.showerror('Error', 'Choose a data to delete.') |
| 64 | + else: |
| 65 | + id = id_entry.get() |
| 66 | + database.delete_data(id) |
| 67 | + add_to_treeview() |
| 68 | + clear() |
| 69 | + messagebox.showinfo('Success', 'Data has been deleted.') |
| 70 | + |
| 71 | + |
| 72 | +def update(): |
| 73 | + selected_item = tree.focus() |
| 74 | + if not selected_item: |
| 75 | + messagebox.showerror('Error', 'Choose a Data to update.') |
| 76 | + else: |
| 77 | + id = id_entry.get() |
| 78 | + name = name_entry.get() |
| 79 | + desc = desc_entry.get() |
| 80 | + status = variable2.get() |
| 81 | + email = email_entry.get() |
| 82 | + gender = variable1.get() |
| 83 | + title = title_entry.get() |
| 84 | + number = number_entry.get() |
| 85 | + |
| 86 | + # Ensure that all fields are not empty |
| 87 | + if not (id and name and desc and status and email and gender and title and number): |
| 88 | + messagebox.showerror('Error', 'Enter all fields.') |
| 89 | + return |
| 90 | + |
| 91 | + # Debug prints to check values |
| 92 | + print(f"Updating data with ID: {id}") |
| 93 | + print(f"Name: {name}") |
| 94 | + print(f"Description: {desc}") |
| 95 | + print(f"Status: {status}") |
| 96 | + print(f"Email: {email}") |
| 97 | + print(f"Gender: {gender}") |
| 98 | + print(f"Title: {title}") |
| 99 | + print(f"Number: {number}") |
| 100 | + |
| 101 | + # Ensure that the update function is called |
| 102 | + database.update_data(name, desc, status, email, gender, title, number, id) |
| 103 | + |
| 104 | + # Fetch and print data directly from the database after update |
| 105 | + updated_data = database.fetch_data() |
| 106 | + print("Data after update:", updated_data) |
| 107 | + |
| 108 | + add_to_treeview() |
| 109 | + clear() |
| 110 | + messagebox.showinfo('Success', 'Data has been updated.') |
| 111 | + |
| 112 | + |
| 113 | +def insert(): |
| 114 | + id = id_entry.get() |
| 115 | + name = name_entry.get() |
| 116 | + desc = desc_entry.get() |
| 117 | + status = variable2.get() |
| 118 | + email = email_entry.get() |
| 119 | + gender = variable1.get() |
| 120 | + title = title_entry.get() |
| 121 | + number = number_entry.get() |
| 122 | + if not (id and name and desc and status and email and gender and title and number): |
| 123 | + messagebox.showerror('Error', 'Enter all fields.') |
| 124 | + elif database.id_exists(id): |
| 125 | + messagebox.showerror('Error', 'ID already exists.') |
| 126 | + else: |
| 127 | + database.insert_data(id, name, desc, status, email, gender, title, number) |
| 128 | + add_to_treeview() |
| 129 | + clear() |
| 130 | + messagebox.showinfo('Success', 'Data has been inserted.') |
| 131 | + |
| 132 | + |
| 133 | +def export_to_csv(): |
| 134 | + data = database.fetch_data() |
| 135 | + if not data: |
| 136 | + messagebox.showinfo('No Data', 'There is no data to export.') |
| 137 | + return |
| 138 | + |
| 139 | + file_path = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")]) |
| 140 | + if not file_path: |
| 141 | + return |
| 142 | + |
| 143 | + with open(file_path, 'w', newline='') as file: |
| 144 | + writer = csv.writer(file) |
| 145 | + writer.writerow(['ID', 'Name', 'Description', 'Type', 'Email', 'Gender', 'Title', 'Number']) |
| 146 | + writer.writerows(data) |
| 147 | + |
| 148 | + messagebox.showinfo('Success', 'Data has been exported to CSV file successfully.') |
| 149 | + |
| 150 | + |
| 151 | +def import_from_csv(): |
| 152 | + file_path = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")]) |
| 153 | + if not file_path: |
| 154 | + return |
| 155 | + |
| 156 | + with open(file_path, 'r') as file: |
| 157 | + reader = csv.reader(file) |
| 158 | + header = next(reader) # Skip header row |
| 159 | + for row in reader: |
| 160 | + if not database.id_exists(row[0]): |
| 161 | + database.insert_data(*row) |
| 162 | + |
| 163 | + add_to_treeview() |
| 164 | + messagebox.showinfo('Success', 'Data has been imported from CSV file successfully.') |
| 165 | + |
| 166 | + |
| 167 | +id_label = customtkinter.CTkLabel(app, font=font1, text='ID:', text_color='#fff', bg_color='#161C25') |
| 168 | +id_label.place(x=20, y=20) |
| 169 | + |
| 170 | +id_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 171 | + border_width=2, width=180) |
| 172 | +id_entry.place(x=100, y=20) |
| 173 | + |
| 174 | +name_label = customtkinter.CTkLabel(app, font=font1, text='Name:', text_color='#fff', bg_color='#161C25') |
| 175 | +name_label.place(x=20, y=80) |
| 176 | + |
| 177 | +name_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 178 | + border_width=2, width=180) |
| 179 | +name_entry.place(x=100, y=80) |
| 180 | + |
| 181 | +desc_label = customtkinter.CTkLabel(app, font=font1, text='Desc:', text_color='#fff', bg_color='#161C25') |
| 182 | +desc_label.place(x=20, y=140) |
| 183 | + |
| 184 | +desc_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 185 | + border_width=2, width=180) |
| 186 | +desc_entry.place(x=100, y=140) |
| 187 | + |
| 188 | +status_label = customtkinter.CTkLabel(app, font=font1, text='Status:', text_color='#fff', bg_color='#161C25') |
| 189 | +status_label.place(x=20, y=200) |
| 190 | + |
| 191 | +status_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 192 | + border_width=2, width=180) |
| 193 | +status_entry.place(x=100, y=200) |
| 194 | + |
| 195 | +email_label = customtkinter.CTkLabel(app, font=font1, text='Email:', text_color='#fff', bg_color='#161C25') |
| 196 | +email_label.place(x=20, y=260) |
| 197 | + |
| 198 | +email_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 199 | + border_width=2, width=180) |
| 200 | +email_entry.place(x=100, y=260) |
| 201 | + |
| 202 | +gender_label = customtkinter.CTkLabel(app, font=font1, text='Gender:', text_color='#fff', bg_color='#161C25') |
| 203 | +gender_label.place(x=20, y=320) |
| 204 | + |
| 205 | +gender_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 206 | + border_width=2, width=180) |
| 207 | +gender_entry.place(x=100, y=320) |
| 208 | + |
| 209 | +title_label = customtkinter.CTkLabel(app, font=font1, text='Title:', text_color='#fff', bg_color='#161C25') |
| 210 | +title_label.place(x=20, y=380) |
| 211 | + |
| 212 | +title_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 213 | + border_width=2, width=180) |
| 214 | +title_entry.place(x=100, y=380) |
| 215 | + |
| 216 | +number_label = customtkinter.CTkLabel(app, font=font1, text='Number:', text_color='#fff', bg_color='#161C25') |
| 217 | +number_label.place(x=20, y=440) |
| 218 | + |
| 219 | +number_entry = customtkinter.CTkEntry(app, font=font1, text_color='#000', fg_color='#fff', border_color='#0C9295', |
| 220 | + border_width=2, width=180) |
| 221 | +number_entry.place(x=100, y=440) |
| 222 | + |
| 223 | +options = ['Male', 'Female', 'Other'] |
| 224 | +optionss = ['Select', 'Option1', 'Option2'] |
| 225 | + |
| 226 | +variable1 = StringVar(app) |
| 227 | +variable2 = StringVar(app) |
| 228 | + |
| 229 | +gender_options = customtkinter.CTkComboBox(app, font=font1, text_color='#000', fg_color='#fff', |
| 230 | + dropdown_hover_color='#0C9295', button_color='#0C9295', |
| 231 | + button_hover_color='#0C9295', border_color='#0C9295', width=180, |
| 232 | + variable=variable1, values=options, state='readonly') |
| 233 | +gender_options.set('Male') |
| 234 | +gender_options.place(x=100, y=320) |
| 235 | + |
| 236 | +status_options = customtkinter.CTkComboBox(app, font=font1, text_color='#000', fg_color='#fff', |
| 237 | + dropdown_hover_color='#0C9295', button_color='#0C9295', |
| 238 | + button_hover_color='#0C9295', border_color='#0C9295', width=180, |
| 239 | + variable=variable2, values=optionss, state='readonly') |
| 240 | +status_options.set('Select') |
| 241 | +status_options.place(x=100, y=200) |
| 242 | + |
| 243 | +add_button = customtkinter.CTkButton(app, command=insert, font=font1, text_color='#fff', text='Add Data', |
| 244 | + fg_color='#05A312', hover_color='#00850B', bg_color='#161C25', cursor='hand2', |
| 245 | + corner_radius=15, width=260) |
| 246 | +add_button.place(x=20, y=500) |
| 247 | + |
| 248 | +clear_button = customtkinter.CTkButton(app, command=lambda: clear(True), font=font1, text_color='#fff', text='New Data', |
| 249 | + fg_color='#161C25', hover_color='#FF5002', bg_color='#161C25', |
| 250 | + border_color='#F15704', border_width=2, cursor='hand2', corner_radius=15, |
| 251 | + width=260) |
| 252 | +clear_button.place(x=20, y=540) |
| 253 | + |
| 254 | +update_button = customtkinter.CTkButton(app, command=update, font=font1, text_color='#fff', text='Update Data', |
| 255 | + fg_color='#161C25', hover_color='#FF5002', bg_color='#161C25', |
| 256 | + border_color='#F15704', border_width=2, cursor='hand2', corner_radius=15, |
| 257 | + width=260) |
| 258 | +update_button.place(x=20, y=580) |
| 259 | + |
| 260 | +delete_button = customtkinter.CTkButton(app, command=delete, font=font1, text_color='#fff', text='Delete Data', |
| 261 | + fg_color='#E40404', hover_color='#AE0000', bg_color='#161C25', |
| 262 | + border_color='#E40404', border_width=2, cursor='hand2', corner_radius=15, |
| 263 | + width=260) |
| 264 | +delete_button.place(x=20, y=620) |
| 265 | + |
| 266 | +export_button = customtkinter.CTkButton(app, command=export_to_csv, font=font1, text_color='#fff', text='Export to CSV', |
| 267 | + fg_color='#0C9295', hover_color='#087A6B', bg_color='#161C25', cursor='hand2', |
| 268 | + corner_radius=15, width=260) |
| 269 | +export_button.place(x=20, y=660) |
| 270 | + |
| 271 | +import_button = customtkinter.CTkButton(app, command=import_from_csv, font=font1, text_color='#fff', |
| 272 | + text='Import from CSV', fg_color='#0C9295', hover_color='#087A6B', |
| 273 | + bg_color='#161C25', cursor='hand2', corner_radius=15, width=260) |
| 274 | +import_button.place(x=20, y=700) |
| 275 | + |
| 276 | +style = ttk.Style(app) |
| 277 | + |
| 278 | +style.theme_use('clam') |
| 279 | +style.configure('Treeview', font=font2, foreground='#fff', background='#000', fieldbackground='#313837') |
| 280 | +style.map('Treeview', background=[('selected', '#1A8F2D')]) |
| 281 | + |
| 282 | +tree = ttk.Treeview(app, height=30) |
| 283 | + |
| 284 | +tree['columns'] = ('ID', 'Name', 'Description', 'Type', 'Email', 'Gender', 'Title', 'Number') |
| 285 | + |
| 286 | +tree.column('#0', width=0, stretch=tk.NO) # hide first default column |
| 287 | +tree.column('ID', anchor=tk.CENTER, width=120) |
| 288 | +tree.column('Name', anchor=tk.CENTER, width=120) |
| 289 | +tree.column('Description', anchor=tk.CENTER, width=120) |
| 290 | +tree.column('Type', anchor=tk.CENTER, width=120) |
| 291 | +tree.column('Email', anchor=tk.CENTER, width=120) |
| 292 | +tree.column('Gender', anchor=tk.CENTER, width=120) |
| 293 | +tree.column('Title', anchor=tk.CENTER, width=120) |
| 294 | +tree.column('Number', anchor=tk.CENTER, width=120) |
| 295 | + |
| 296 | +tree.heading('ID', text='ID') |
| 297 | +tree.heading('Name', text='Name') |
| 298 | +tree.heading('Description', text='Description') |
| 299 | +tree.heading('Type', text='Type') |
| 300 | +tree.heading('Email', text='Email') |
| 301 | +tree.heading('Gender', text='Gender') |
| 302 | +tree.heading('Title', text='Title') |
| 303 | +tree.heading('Number', text='Number') |
| 304 | + |
| 305 | +tree.place(x=300, y=20) |
| 306 | + |
| 307 | +tree.bind('<ButtonRelease-1>', display_data) |
| 308 | + |
| 309 | +add_to_treeview() |
| 310 | + |
| 311 | +app.mainloop() |
0 commit comments