Friday, December 30, 2022

TkCal

 I have been asked to produce a windows .exe file from the - now running -

tkcalendar project. Unfortunately, I cannot do this at the moment. Pyinstaller is

not (yet) compatible with python 3.10. Those still running an earlier version

of python should be able to quite easily.


Below, my running tkcal code. Note that there are many styling options I am not

using, and that many color schemes are possible. That's half the achievement of the

tkcal module, producing all that styling code for the calendar options. 


from tkinter import *
import tkinter.messagebox as mb
from tkinter import ttk
from tkcalendar import Calendar
import sqlite3
import datetime

#Create database
connector = sqlite3.connect('Calevents.db')
cursor = connector.cursor()
connector.execute(
"CREATE TABLE IF NOT EXISTS CALEVENTS (EVENT_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
"DAY TEXT, DESC TEXT, TAG TEXT )"
)

#show form with empty fields
def reset_fields():
global day_strvar, desc_strvar, tag_strvar
for i in ['day_strvar', 'desc_strvar', 'tag_strvar']:
exec(f"{i}.set('')")

#erase all current database entries
def reset_form():
import sqlite3

conn = sqlite3.connect('Calevents.db')
c = conn.cursor()

# delete all rows from table
c.execute('DELETE FROM CALEVENTS;', );

print('We have deleted', c.rowcount, 'records from the table.')

# commit the changes to db
conn.commit()
# close the connection
conn.close()

#display records and activate cal
def display_records():
tree.delete(*tree.get_children())
curr = connector.execute('SELECT * FROM CALEVENTS')
data = curr.fetchall()
for records in data:
tree.insert('', END, values=records)

date = datetime.datetime.strptime(records[1], "%Y-%m-%d").date()
my_cal.calevent_create(date, records[2], records[3])
my_cal.tag_config('out', background='turquoise')
my_cal.tag_config('home', background='plum')

# do_stuff_with_row
def add_record():
global day_strvar, desc_strvar, tag_strvar
day = day_strvar.get()
desc = desc_strvar.get()
tag = tag_strvar.get()

if not day or not desc or not tag:
mb.showerror('Error!', "Please fill all the missing fields!!")
else:
try:
connector.execute(
'INSERT INTO CALEVENTS (DAY, DESC, TAG) VALUES (?,?,?)',
(day, desc, tag)
)
connector.commit()
mb.showinfo('Record added', f"Record of {day} was successfully added")
reset_fields()
display_records()
except:
mb.showerror('Wrong type',
'The type of the values entered is not accurate.')

def remove_record():
if not tree.selection():
mb.showerror('Error!', 'Please select an item from the database')
else:
current_item = tree.focus()
values = tree.item(current_item)
selection = values["values"]
tree.delete(current_item)
connector.execute('DELETE FROM CALEVENTS' %selection[0])
connector.commit()
mb.showinfo('Done', 'The record you wanted deleted was successfully deleted.')
display_records()

def view_record():
global day_strvar, desc_strvar, tag_strvar

if not tree.selection():
mb.showerror('Error!', 'Please select a record to view')
else:

current_item = tree.focus()
values = tree.item(current_item)
selection = values["values"]

day_strvar.set(selection[1]); desc_strvar.set(selection[2])
tag_strvar.set(selection[3]);


date = datetime.datetime.strptime(selection[1], "%Y-%m-%d").date()
my_cal.tag_config('out', background='turquoise')
my_cal.tag_config('home', background='plum')
my_cal.calevent_create(date, selection[2], selection[3])

#initiating root
root=Tk()
root.title('My_Calevents')
root.geometry('800x400+400+200')
root.resizable(False, False)
root.update_idletasks()
lf_bg = 'seashell2' # bg color for the left_frame
cf_bg = 'grey77' # bg color for the center_frame

# Creating the StringVar or IntVar variables, and the calevents label
day_strvar = StringVar()
desc_strvar = StringVar()
tag_strvar = StringVar()
Label(root, text="CALEVENTS", bg='ivory').pack(side=TOP, fill=X)

#creating the frames
left_frame = Frame(root, bg=lf_bg)
left_frame.place(x=0, y=30, relheight=1, relwidth=0.2)

center_frame = Frame(root, bg=cf_bg)
center_frame.place(relx=0.2, y=30, relheight=1, relwidth=0.2)
right_frame = Frame(root, bg="Gray65")
right_frame.place(relx=0.4, y=30, relheight=1, relwidth=0.6)

# Placing components in the left frame
Label(left_frame, text="Day").place(relx=0.333, rely=0.05)
Label(left_frame, text="Description").place(relx=0.233, rely=0.18)
Label(left_frame, text="Tag").place(relx=0.333, rely=0.31)
Entry(left_frame, width=15, textvariable=day_strvar).place(x=20, rely=0.1)
Entry(left_frame, width=15, textvariable=desc_strvar).place(x=20, rely=0.23)
Entry(left_frame, width=15, textvariable=tag_strvar).place(x=20, rely=0.36)
Button(left_frame, text='Add Record', command=add_record, width=18).place(relx=0.025, rely=0.85)

# Placing components in the center frame
Button(center_frame, text='Delete Record', command=remove_record, width=14).place(relx=0.1, rely=0.25)
Button(center_frame, text='View Record', command=view_record, width=14).place(relx=0.1, rely=0.35)
Button(center_frame, text='Reset Fields', command=reset_fields, width=14).place(relx=0.1, rely=0.45)
Button(center_frame, text='Delete database', command=reset_form, width=14).place(relx=0.1, rely=0.55)

#Showing header in the right frame
Label(right_frame, text='Events Listing', bg='light steel blue', fg='purple').pack(side=TOP, fill=X)

#cal features
global my_cal
top=Toplevel(root)
top.resizable(False, False)
top.update_idletasks()
my_cal = Calendar(top, selectmode='day', showweeknumbers=False, locale='en_US',
date_pattern='y-mm-dd', selectbackground ='khaki3',
background='light yellow', foreground='purple', font='Ink_Free 12',
tooltipbackground='teal', tooltipalpha=.5, tooltipdelay=0)
my_cal.pack(side='right')

#the two buttons for showing or not the database features
def withdraw():
root.withdraw()
def show_win():
root.deiconify()
buttonW = Button(top, text='Close_Win', command=withdraw)
buttonW.pack()
buttonWD = Button(top, text="Show_Win", command=show_win)
buttonWD.pack()

#atyling the database entries
style = ttk.Style()
style.theme_use('vista')

#style.configure("Heading", font="Arial, 14, bold")
tree = ttk.Treeview(right_frame, height=100, selectmode=BROWSE,
columns=('ID', "Day", "Description", "Tag"))

X_scroller = Scrollbar(tree, orient=HORIZONTAL, command=tree.xview)
Y_scroller = Scrollbar(tree, orient=VERTICAL, command=tree.yview)
X_scroller.pack(side=BOTTOM, fill=X)
Y_scroller.pack(side=RIGHT, fill=Y)
tree.config(yscrollcommand=Y_scroller.set, xscrollcommand=X_scroller.set)
tree.heading('ID', text='ID', anchor=W)
tree.heading('Day', text='Day', anchor=W)
tree.heading('Description', text='Description', anchor=W)
tree.heading('Tag', text='Tag', anchor=W)
tree.column('#0', width=0, stretch=NO)
tree.column('#1', width=80, stretch=NO)
tree.column('#2', width=150, stretch=NO)
tree.column('#3', width=180, stretch=NO)
tree.place(y=30, relwidth=1, relheight=0.9, relx=0)

#calling display and update
display_records()
root.update()

#keeping the root window open
root.mainloop()

No comments: