import customtkinter as ctk
import sqlite3
from tkinter import messagebox, filedialog
from [Link].backend_tkagg import FigureCanvasTkAgg
import [Link] as plt
import pandas as pd
from tkcalendar import Calendar
from PIL import Image, ImageTk
from datetime import datetime
import hashlib
import csv
import os
# Set the appearance mode and color theme
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("dark-blue")
# Create the main application window
app = [Link]()
[Link]("1000x700")
[Link]("Login to Digital Diary")
# Variables
mood_var = [Link](value="Select Mood")
sleep_hours_var = [Link](value="7")
screen_time_var = [Link](value="5")
exercise_var = [Link](value="30")
daily_quote = "Stay positive, work hard, make it happen!"
def set_background(app, image_path):
if not [Link](image_path):
[Link]("Error", f"Image not found: {image_path}")
return
background_image = [Link](image_path)
background_image = background_image.resize((1000, 700), [Link]) #
Replace ANTIALIAS with [Link]
background_photo = [Link](background_image)
background_label = [Link](app, image=background_photo, text="")
background_label.image = background_photo # Keep a reference to avoid garbage collection
background_label.place(x=0, y=0, relwidth=1, relheight=1)
# Database connection
def connect_db():
conn = [Link]('new_diary.db', timeout=10)
[Link]('PRAGMA journal_mode=WAL;') # Enable WAL mode for concurrency
cursor = [Link]()
[Link]('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL
)''')
[Link]('''
CREATE TABLE IF NOT EXISTS entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
mood TEXT,
content TEXT,
photo_path TEXT
)''')
[Link]('''
CREATE TABLE IF NOT EXISTS wellbeing (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
sleep_hours TEXT,
screen_time TEXT,
exercise TEXT
)''')
[Link]('''
CREATE TABLE IF NOT EXISTS settings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
theme TEXT,
font TEXT
)''')
[Link]()
return conn
conn = connect_db() # Global connection to be reused
# Function to close the database connection
def close_db(conn):
if conn:
[Link]()
# Function to encrypt password
def encrypt_password(password):
return hashlib.sha256([Link]()).hexdigest()
# Function to handle login
def login():
try:
username = entry_username.get()
password = encrypt_password(entry_password.get())
cursor = [Link]()
[Link]("SELECT * FROM users WHERE username=? AND password=?", (username,
password))
user = [Link]()
if user:
load_settings()
[Link]("Login Successful", "Welcome!")
open_dashboard()
else:
[Link]("Login Failed", "Invalid username or password")
except Exception as e:
[Link]("Error", f"An error occurred: {e}")
finally:
[Link]()
# Function to register a new user
def register():
username = entry_username.get()
password = encrypt_password(entry_password.get())
cursor = [Link]()
try:
[Link]("INSERT INTO users (username, password) VALUES (?, ?)", (username, password))
[Link]()
[Link]("Registration Successful", "User Registered Successfully!")
finally:
[Link]()
# Function to open the dashboard
def open_dashboard():
dashboard = [Link]()
[Link]("1200x800")
[Link]("Enhanced Digital Diary Dashboard")
# Create a menu frame
menu_frame = [Link](dashboard, width=220, height=800)
menu_frame.pack(side="left", fill="y", padx=10, pady=10)
# Add menu buttons
btn_home = [Link](menu_frame, text="🏠 Home", corner_radius=8, command=lambda:
show_frame(home_frame))
btn_home.pack(pady=20)
btn_new_entry = [Link](menu_frame, text="📝 New Entry", corner_radius=8,
command=lambda: show_frame(new_entry_frame))
btn_new_entry.pack(pady=20)
btn_wellbeing = [Link](menu_frame, text="💪 Wellbeing", corner_radius=8,
command=lambda: show_frame(wellbeing_frame))
btn_wellbeing.pack(pady=20)
btn_stats = [Link](menu_frame, text="📊 View Stats", corner_radius=8,
command=view_stats)
btn_stats.pack(pady=20)
btn_settings = [Link](menu_frame, text="⚙️Settings", corner_radius=8,
command=lambda: show_frame(settings_frame))
btn_settings.pack(pady=20)
btn_logout = [Link](menu_frame, text="🚪 Logout", corner_radius=8, command=lambda:
logout(dashboard))
btn_logout.pack(pady=20)
# Add calendar to the menu for quick access
lbl_calendar = [Link](menu_frame, text="📅 Calendar", font=("Arial", 18))
lbl_calendar.pack(pady=20)
calendar = Calendar(menu_frame, selectmode='day', year=2024, month=9, day=1)
[Link](pady=10)
btn_view_entry = [Link](menu_frame, text="Show Entry", command=lambda:
show_entry_for_selected_date(calendar))
btn_view_entry.pack(pady=10)
# Frames for each section
home_frame = [Link](dashboard, width=980, height=800)
new_entry_frame = [Link](dashboard, width=980, height=800)
wellbeing_frame = [Link](dashboard, width=980, height=800)
settings_frame = [Link](dashboard, width=980, height=800)
for frame in (home_frame, new_entry_frame, wellbeing_frame, settings_frame):
[Link](x=220, y=0, relwidth=0.8, relheight=1)
# Home frame content
lbl_home = [Link](home_frame, text="Welcome to your Enhanced Digital Diary!",
font=("Arial", 24))
lbl_home.pack(pady=20)
lbl_quote = [Link](home_frame, text=daily_quote, font=("Arial", 16))
lbl_quote.pack(pady=20)
lbl_recent_entry = [Link](home_frame, text="Recent Entry:", font=("Arial", 18))
lbl_recent_entry.pack(pady=10)
txt_recent_entry = [Link](home_frame, width=700, height=300)
txt_recent_entry.pack(pady=10)
txt_recent_entry.insert("1.0", get_recent_entry())
txt_recent_entry.configure(state="disabled")
# New Entry frame content
lbl_new_entry = [Link](new_entry_frame, text="New Diary Entry", font=("Arial", 24))
lbl_new_entry.pack(pady=20)
search_text = [Link](new_entry_frame, width=500, corner_radius=10,
placeholder_text="Search for keywords...")
search_text.pack(pady=10)
entry_text = [Link](new_entry_frame, width=700, height=300, corner_radius=10)
entry_text.pack(pady=10)
# Replace mood emoji buttons with a mood dropdown (Combobox)
mood_label = [Link](new_entry_frame, text="Select Mood", font=("Arial", 16))
mood_label.pack(pady=10)
mood_dropdown = [Link](new_entry_frame, values=["😊 Happy", "😢 Sad", "😠
Angry", "😌 Relaxed", "😴 Tired"], variable=mood_var)
mood_dropdown.pack(pady=10)
btn_attach_photo = [Link](new_entry_frame, text="🖼 Attach Photo", command=lambda:
attach_photo(new_entry_frame))
btn_attach_photo.pack(pady=10)
btn_save_entry = [Link](new_entry_frame, text="💾 Save Entry", command=lambda:
save_entry(entry_text, mood_var.get()))
btn_save_entry.pack(pady=10)
# Wellbeing frame content
lbl_wellbeing = [Link](wellbeing_frame, text="Wellbeing Tracker", font=("Arial", 24))
lbl_wellbeing.pack(pady=20)
lbl_screen_time = [Link](wellbeing_frame, text="Track Your Screen Time (in hours)",
font=("Arial", 18))
lbl_screen_time.pack(pady=10)
screen_time_entry = [Link](wellbeing_frame, textvariable=screen_time_var)
screen_time_entry.pack(pady=10)
lbl_sleep_hours = [Link](wellbeing_frame, text="Track Your Sleep Hours (in hours)",
font=("Arial", 18))
lbl_sleep_hours.pack(pady=10)
sleep_hours_entry = [Link](wellbeing_frame, textvariable=sleep_hours_var)
sleep_hours_entry.pack(pady=10)
lbl_exercise = [Link](wellbeing_frame, text="Track Your Exercise Time (in minutes)",
font=("Arial", 18))
lbl_exercise.pack(pady=10)
exercise_entry = [Link](wellbeing_frame, textvariable=exercise_var)
exercise_entry.pack(pady=10)
btn_save_wellbeing = [Link](wellbeing_frame, text="💾 Save Wellbeing",
command=save_wellbeing)
btn_save_wellbeing.pack(pady=20)
# Settings frame content
lbl_settings = [Link](settings_frame, text="Customize Your Dashboard", font=("Arial", 24))
lbl_settings.pack(pady=20)
lbl_theme = [Link](settings_frame, text="Select Theme", font=("Arial", 18))
lbl_theme.pack(pady=10)
# Add theme buttons with a change of button format
theme_light_btn = [Link](settings_frame, text="🌞 Light Theme", command=lambda:
change_theme("light"))
theme_light_btn.pack(pady=10)
theme_dark_btn = [Link](settings_frame, text="🌚 Dark Theme", command=lambda:
change_theme("dark"))
theme_dark_btn.pack(pady=10)
lbl_font = [Link](settings_frame, text="Select Font", font=("Arial", 18))
lbl_font.pack(pady=10)
# Add font selection buttons with a change of button format
font_arial_btn = [Link](settings_frame, text="Arial", command=lambda:
change_font("Arial", dashboard))
font_arial_btn.pack(pady=10)
font_roboto_btn = [Link](settings_frame, text="Roboto", command=lambda:
change_font("Roboto", dashboard))
font_roboto_btn.pack(pady=10)
font_courier_btn = [Link](settings_frame, text="Courier", command=lambda:
change_font("Courier", dashboard))
font_courier_btn.pack(pady=10)
show_frame(home_frame)
[Link]()
# Function to display wellbeing stats
def view_stats():
stats_window = [Link]()
stats_window.geometry("800x600")
stats_window.title("Wellbeing Stats")
lbl_stats = [Link](stats_window, text="Wellbeing Stats", font=("Arial", 18))
lbl_stats.pack(pady=20)
# Fetch the latest diary entry for the pie chart
cursor = [Link]()
[Link]("SELECT screen_time, exercise, sleep_hours FROM wellbeing ORDER BY date DESC
LIMIT 1")
data = [Link]()
if not data:
[Link]("Error", "No data to display!")
return
screen_time, exercise_time, sleep_hours = data
# Pie chart data for time invested in each activity
labels = ['Screen Time', 'Exercise Time', 'Sleep Hours']
times = [float(screen_time), float(exercise_time), float(sleep_hours)]
fig, axs = [Link](1, 3, figsize=(15, 5))
# Bar chart and Line graph for last 7 days
[Link]("SELECT screen_time, exercise, sleep_hours FROM wellbeing ORDER BY date DESC
LIMIT 7")
all_data = [Link]()[::-1] # Reverse to get chronological order
screen_times = [float(row[0]) for row in all_data]
exercise_times = [float(row[1]) for row in all_data]
sleep_hours_list = [float(row[2]) for row in all_data]
days = range(1, len(all_data) + 1)
# Stacked bar chart
axs[0].bar(days, screen_times, color='blue', label="Screen Time")
axs[0].bar(days, exercise_times, color='green', label="Exercise Time", bottom=screen_times)
axs[0].bar(days, sleep_hours_list, color='orange', label="Sleep Hours",
bottom=[i + j for i, j in zip(screen_times, exercise_times)])
axs[0].set_title("Last 7 Days Time Spent on Activities")
axs[0].set_xlabel("Days")
axs[0].set_ylabel("Hours")
axs[0].legend()
# Pie chart for today's time investment
axs[1].pie(times, labels=labels, autopct='%1.1f%%', startangle=90)
axs[1].set_title("Today's Time Investment")
# Line graph for time trends over last 7 days
axs[2].plot(days, screen_times, marker='o', color='blue', label="Screen Time")
axs[2].plot(days, exercise_times, marker='o', color='green', label="Exercise Time")
axs[2].plot(days, sleep_hours_list, marker='o', color='orange', label="Sleep Hours")
axs[2].set_title("Trend of Time Spent Over Last 7 Days")
axs[2].set_xlabel("Days")
axs[2].set_ylabel("Hours")
axs[2].legend()
# Show the graphs
canvas = FigureCanvasTkAgg(fig, master=stats_window)
[Link]()
canvas.get_tk_widget().pack(pady=20)
stats_window.mainloop()
# Function to show the selected frame
def show_frame(frame):
[Link]()
# Function to show entry for the selected date
def show_entry_for_selected_date(calendar):
selected_date = calendar.get_date()
cursor = [Link]()
try:
[Link]("SELECT content FROM entries WHERE date=?", (selected_date,))
entry = [Link]()
if entry:
[Link]("Entry", entry[0])
else:
[Link]("Entry", "No entry found for the selected date.")
finally:
[Link]()
# Function to attach a photo to the entry
def attach_photo(frame):
photo_path = [Link](filetypes=[("Image files", "*.jpg;*.jpeg;*.png")])
if photo_path:
photo = [Link](photo_path)
[Link]((200, 200))
photo_display = [Link](photo)
lbl_photo = [Link](frame, image=photo_display)
lbl_photo.photo = photo_display # Keep a reference
lbl_photo.pack(pady=10)
# Function to save the diary entry
def save_entry(entry_text, mood):
date = [Link]().strftime('%Y-%m-%d')
content = entry_text.get("1.0", "end").strip()
cursor = [Link]()
try:
[Link]("INSERT INTO entries (date, mood, content) VALUES (?, ?, ?)", (date, mood,
content))
[Link]()
[Link]("Success", "Entry saved successfully!")
finally:
[Link]()
# Function to get the most recent entry with date, time, and mood
def get_recent_entry():
cursor = [Link]()
try:
[Link]("SELECT date, mood, content FROM entries ORDER BY id DESC LIMIT 1")
entry = [Link]()
if entry:
date, mood, content = entry
return f"Date: {date}\nMood: {mood}\n\n{content}"
else:
return "No entries yet."
finally:
[Link]()
# Create login frame and widgets
login_frame = [Link](app)
login_frame.pack(pady=50)
# Set login background image
set_background(app, "C:/Users/Anjali/Downloads/download (6).jpeg") # Replace with your image
path
lbl_title = [Link](login_frame, text="Digital Diary", font=("Arial", 24))
lbl_title.pack(pady=20)
entry_username = [Link](login_frame, width=300, corner_radius=10,
placeholder_text="Username")
entry_username.pack(pady=10)
entry_password = [Link](login_frame, width=300, corner_radius=10,
placeholder_text="Password", show="*")
entry_password.pack(pady=10)
btn_login = [Link](login_frame, text="Login", corner_radius=10, command=login)
btn_login.pack(pady=10)
lbl_register = [Link](login_frame, text="New user? Register below.", font=("Arial", 14))
lbl_register.pack(pady=10)
btn_register = [Link](login_frame, text="Register", corner_radius=10, command=register)
btn_register.pack(pady=10)
# Function to save wellbeing data
def save_wellbeing():
date = [Link]().strftime('%Y-%m-%d')
sleep_hours = sleep_hours_var.get()
screen_time = screen_time_var.get()
exercise = exercise_var.get()
cursor = [Link]()
try:
[Link]("INSERT INTO wellbeing (date, sleep_hours, screen_time, exercise) VALUES
(?, ?, ?, ?)", (date, sleep_hours, screen_time, exercise))
[Link]()
[Link]("Success", "Wellbeing data saved successfully!")
plot_wellbeing_data() # Call to plot data after saving
finally:
[Link]()
def plot_wellbeing_data():
# Code for plotting the wellbeing data
pass
# Function to apply and save theme changes
def change_theme(theme):
ctk.set_appearance_mode(theme)
save_settings(theme=theme)
# Function to apply and save font changes
def change_font(font):
app.option_add("*Font", font)
save_settings(font=font)
# Function to save the theme and font settings in the database
def save_settings(theme=None, font=None):
cursor = [Link]()
try:
if theme:
[Link]("UPDATE settings SET theme=?", (theme,))
if font:
[Link]("UPDATE settings SET font=?", (font,))
[Link]()
finally:
[Link]()
# Function to change font for the dashboard window
def change_font(font, window):
print("Attempting to change font...")
if window.winfo_exists():
print(f"Window exists, changing font to {font}")
window.option_add("*Font", font) # Apply font change to the window
save_settings(font=font) # Save settings to the database
else:
print("Window doesn't exist. Cannot change font.")
[Link]("Error", "Cannot change font, the window is closed.")
# Function to load saved settings from the database
def load_settings():
cursor = [Link]()
try:
[Link]("SELECT theme, font FROM settings")
settings = [Link]()
if settings:
theme, font = settings
if theme:
ctk.set_appearance_mode(theme)
if font:
app.option_add("*Font", font)
finally:
[Link]()
# Function to log out and close the dashboard
def logout(dashboard):
[Link]()
# Create login frame and widgets
login_frame = [Link](app, width=400, height=300) # Set a fixed size for the frame
login_frame.pack_propagate(False) # Prevent the frame from resizing to fit content
login_frame.place(relx=0.5, rely=0.4, anchor="center") # Center the frame, adjusting `rely` for
vertical alignment
lbl_title = [Link](login_frame, text="Digital Diary", font=("Arial", 24))
lbl_title.pack(pady=20)
entry_username = [Link](login_frame, width=300, corner_radius=10,
placeholder_text="Username")
entry_username.pack(pady=10)
entry_password = [Link](login_frame, width=300, corner_radius=10,
placeholder_text="Password", show="*")
entry_password.pack(pady=10)
btn_login = [Link](login_frame, text="Login", corner_radius=10, command=login)
btn_login.pack(pady=10)
lbl_register = [Link](login_frame, text="New user? Register below.", font=("Arial", 14))
lbl_register.pack(pady=10)
btn_register = [Link](login_frame, text="Register", corner_radius=10, command=register)
btn_register.pack(pady=10)
# Start the application
[Link]()