Files
caltool/xcal.py
2017-08-26 08:54:02 -04:00

1079 lines
39 KiB
Python
Executable File

#!usr/bin/python3
'''
' xcal.py
' Author: Bronson Graansma 0872249
' Contact: bgraansm@mail.uoguelph.ca
' Date: April 7, 2016
' Description: Tkinter GUI to interact with caltool + mySQL
'''
import sys, os, getpass
import mysql.connector as sql
import tkinter as tk
from tkinter import *
from tkinter import filedialog as fd
import random
from random import randint
import Cal
def holdfocus():
global focus
focus = window.focus_get()
def dbstatus():
cursor.execute("SELECT COUNT(*) FROM EVENT")
logtext.set(logtext.get()+"\nDatabase has "+str(cursor.fetchone()[0])+" events, ")
cursor.execute("SELECT COUNT(*) FROM TODO")
logtext.set(logtext.get()+str(cursor.fetchone()[0])+" todo-items, ")
cursor.execute("SELECT COUNT(*) FROM ORGANIZER")
logtext.set(logtext.get()+str(cursor.fetchone()[0])+" organizers.\n")
def storeall():
global result
for r in result[1]:
if r[0] == "VEVENT" or r[0] == "VTODO":
org_id = -1
cursor.execute("SELECT COUNT(*) FROM ORGANIZER WHERE name=\"{}\"".format(r[4]))
if cursor.fetchone()[0] == 0:
cursor.execute("INSERT INTO ORGANIZER (name, contact) \
VALUES (\"{}\", \"{}\")".format(r[4], r[5]))
database.commit()
cursor.execute("SELECT org_id FROM ORGANIZER WHERE name=\"{}\"".format(r[4]))
ftch = cursor.fetchone()
if ftch != None:
org_id = ftch[0]
if r[0] == "VEVENT":
cursor.execute("SELECT COUNT(*) FROM EVENT WHERE summary=\"{}\" \
AND start_time=\"{}\"".format(r[3], r[6]))
if cursor.fetchone()[0] == 0 and org_id >= 0:
cursor.execute("INSERT INTO EVENT (summary, start_time, location, organizer) \
VALUES (\"{}\", \"{}\", \"{}\", {})".format(r[3], r[6], r[7], org_id))
elif r[0] == "VTODO":
cursor.execute("SELECT COUNT(*) FROM TODO WHERE summary=\"{}\"".format(r[3]))
if cursor.fetchone()[0] == 0 and org_id >= 0:
cursor.execute("INSERT INTO TODO (summary, priority, organizer) \
VALUES (\"{}\", \"{}\", {})".format(r[3], r[8], org_id))
database.commit()
dbstatus()
def storesel():
global result
global entry
global focus
flag = False
compNum = -1
for i in range(len(entry)):
for e in entry[i]:
if e == focus:
flag = True
compNum = i
break
if flag:
break
if compNum >= 0:
if result[1][compNum][0] == "VEVENT" or result[1][compNum][0] == "VTODO":
org_id = -1
cursor.execute("SELECT COUNT(*) FROM ORGANIZER WHERE name=\"{}\"".format(result[1][compNum][4]))
if cursor.fetchone()[0] == 0:
cursor.execute("INSERT INTO ORGANIZER (name, contact) \
VALUES (\"{}\", \"{}\")".format(result[1][compNum][4], result[1][compNum][5]))
database.commit()
cursor.execute("SELECT org_id FROM ORGANIZER WHERE name=\"{}\"".format(result[1][compNum][4]))
ftch = cursor.fetchone()
if ftch != None:
org_id = ftch[0]
if result[1][compNum][0] == "VEVENT":
cursor.execute("SELECT COUNT(*) FROM EVENT WHERE summary=\"{}\" \
AND start_time=\"{}\"".format(result[1][compNum][3], result[1][compNum][6]))
if cursor.fetchone()[0] == 0 and org_id >= 0:
cursor.execute("INSERT INTO EVENT (summary, start_time, location, organizer) \
VALUES (\"{}\", \"{}\", \"{}\", {})"\
.format(result[1][compNum][3], result[1][compNum][6], result[1][compNum][7], org_id))
elif result[1][compNum][0] == "VTODO":
cursor.execute("SELECT COUNT(*) FROM TODO WHERE summary=\"{}\"".format(result[1][compNum][3]))
if cursor.fetchone()[0] == 0 and org_id >= 0:
cursor.execute("INSERT INTO TODO (summary, priority, organizer) \
VALUES (\"{}\", \"{}\", {})".format(result[1][compNum][3], result[1][compNum][8], org_id))
database.commit()
dbstatus()
def clearsql():
cursor.execute("TRUNCATE TABLE TODO")
cursor.execute("TRUNCATE TABLE EVENT")
cursor.execute("DELETE FROM ORGANIZER")
database.commit()
dbstatus()
def querysql():
dialog = queryDialog(window)
def save():
if filename.get() == "":
return
os.system("cat .save.ics > \""+filename.get()+"\"")
logtext.set(logtext.get()+"\n\n"+os.popen("wc -l .save.ics").read()+" lines written.\n")
saved.set(True)
string = list(filename.get())
for i in range(len(filename.get())):
if string[i] == '/':
place = i+1
window.title('xcal - ' + filename.get()[place:])
def saveas():
if filename.get() == "":
return
saveto = fd.asksaveasfilename(filetypes=[('calendar files', '.ics'), ('text files', '.txt')])
if saveto != "" and saveto != None:
os.system("cat .save.ics > \""+saveto+"\"")
saved.set(True)
filename.set(saveto)
string = list(filename.get())
for i in range(len(filename.get())):
if string[i] == '/':
place = i+1
window.title('xcal - ' + filename.get()[place:])
def combine():
if filename.get() == "":
logtext.set(logtext.get()+"\n\nYou must open a file before combining.")
return
file2 = fd.askopenfilename(filetypes=[('calendar files', '.ics'), ('text files', '.txt')])
if file2 == "" or file2 == None:
return
os.system("./caltool -combine \""+file2+"\" < .save.ics > .xcal.log 2> .xcal.tmp")
logtext.set(logtext.get()+"\n\n"+open(".xcal.log").read()+open(".xcal.tmp").read())
os.system("cat .xcal.log > .save.ics")
os.system("rm -f .xcal.*")
saved.set(False)
string = list(filename.get())
for i in range(len(filename.get())):
if string[i] == '/':
place = i+1
window.title('xcal - ' + filename.get()[place:]+"*")
Cal.freeFile(result[0])
tup = Cal.readFile(".save.ics")
result[0] = tup[0]
result[1] = tup[1]
if result[0] == "error":
logtext.set(logtext.get()+"\n\n"+result[1])
return
tup = Cal.readFile(".save.ics")
result[0] = tup[0]
result[1] = tup[1]
if result[0] == "error":
logtext.set(logtext.get()+"\n\n"+result[1])
return
for i in range(len(result[1])):
s = StringVar()
s.set("")
entry.append([s, s, s, s, s])
entry[i][0] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][0].insert(0, str(i+1))
entry[i][0].configure(state='readonly')
entry[i][0].grid(row=i+1, column=0)
entry[i][1] = Entry(frame, width=25, validate="focusin", vcmd=holdfocus)
entry[i][1].insert(0, result[1][i][0])
entry[i][1].configure(state='readonly')
entry[i][1].grid(row=i+1, column=1)
entry[i][2] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][2].insert(0, str(result[1][i][1]))
entry[i][2].configure(state='readonly')
entry[i][2].grid(row=i+1, column=2)
entry[i][3] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][3].insert(0, str(result[1][i][2]))
entry[i][3].configure(state='readonly')
entry[i][3].grid(row=i+1, column=3)
entry[i][4] = Entry(frame, width=30, validate="focusin", vcmd=holdfocus)
entry[i][4].insert(0, result[1][i][3])
entry[i][4].configure(state='readonly')
entry[i][4].grid(row=i+1, column=4)
def filter():
if filename.get() == "":
logtext.set(logtext.get()+"\n\nYou must open a file before filtering.")
return
dialog = fDialog(window)
window.wait_window(dialog.top)
saved.set(False)
string = list(filename.get())
for i in range(len(filename.get())):
if string[i] == '/':
place = i+1
window.title('xcal - ' + filename.get()[place:]+"*")
Cal.freeFile(result[0])
tup = Cal.readFile(".save.ics")
result[0] = tup[0]
result[1] = tup[1]
if result[0] == "error":
logtext.set(logtext.get()+"\n\n"+result[1])
return
for i in range(len(result[1])):
s = StringVar()
s.set("")
entry.append([s, s, s, s, s])
entry[i][0] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][0].insert(0, str(i+1))
entry[i][0].configure(state='readonly')
entry[i][0].grid(row=i+1, column=0)
entry[i][1] = Entry(frame, width=25, validate="focusin", vcmd=holdfocus)
entry[i][1].insert(0, result[1][i][0])
entry[i][1].configure(state='readonly')
entry[i][1].grid(row=i+1, column=1)
entry[i][2] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][2].insert(0, str(result[1][i][1]))
entry[i][2].configure(state='readonly')
entry[i][2].grid(row=i+1, column=2)
entry[i][3] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][3].insert(0, str(result[1][i][2]))
entry[i][3].configure(state='readonly')
entry[i][3].grid(row=i+1, column=3)
entry[i][4] = Entry(frame, width=30, validate="focusin", vcmd=holdfocus)
entry[i][4].insert(0, result[1][i][3])
entry[i][4].configure(state='readonly')
entry[i][4].grid(row=i+1, column=4)
def exte():
os.system("./caltool -extract e < .save.ics > .xcal.log 2> .xcal.tmp")
logtext.set(logtext.get()+"\n\n"+open(".xcal.log").read()+open(".xcal.tmp").read())
os.system("rm -f .xcal.*")
def extx():
os.system("./caltool -extract x < .save.ics > .xcal.log 2> .xcal.tmp")
logtext.set(logtext.get()+"\n\n"+open(".xcal.log").read()+open(".xcal.tmp").read())
os.system("rm -f .xcal.*")
def show():
focus = window.focus_get()
flag = False
compNum = -1
for i in range(len(entry)):
for e in entry[i]:
if e == focus:
flag = True
compNum = i
break
if flag:
break
if compNum >= 0:
os.system("touch .selected.ics")
write = Cal.writeFile(".selected.ics", result[0], compNum)
if write == "OK":
logtext.set(logtext.get()+"\n\n"+open(".selected.ics").read())
else:
logtext.set(logtext.get()+"\n\n"+write)
os.system("rm -f .selected.ics")
def openfile():
if not saved.get():
saveprompt = openDialog(window)
window.wait_window(saveprompt.top)
if saveprompt.cancel.get():
return
Cal.freeFile(result[0])
newfile = fd.askopenfilename(filetypes=[('calendar files', '.ics'), ('text files', '.txt')])
if newfile == "" or newfile == None:
return
os.system("cat \""+newfile+"\" > .save.ics")
os.system("./caltool -info < .save.ics > .xcal.log 2> .xcal.tmp")
if open(".xcal.tmp").read() != "":
logtext.set(open(".xcal.tmp").read())
os.system("rm -f .xcal.*")
return
tup = Cal.readFile(".save.ics")
result[0] = tup[0]
result[1] = tup[1]
if result[0] == "error":
logtext.set(logtext.get()+"\n\n"+result[1])
return
string = list(newfile)
for i in range(len(newfile)):
if string[i] == '/':
place = i+1
window.title('xcal - ' + newfile[place:])
filename.set(newfile)
saved.set(True)
logtext.set(open(".xcal.log").read())
os.system("rm -f .xcal.*")
global entry
for e in entry:
for f in e:
f.destroy()
entry = []
for i in range(len(result[1])):
s = StringVar()
s.set("")
entry.append([s, s, s, s, s])
entry[i][0] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][0].insert(0, str(i+1))
entry[i][0].configure(state='readonly')
entry[i][0].grid(row=i+1, column=0)
entry[i][1] = Entry(frame, width=25, validate="focusin", vcmd=holdfocus)
entry[i][1].insert(0, result[1][i][0])
entry[i][1].configure(state='readonly')
entry[i][1].grid(row=i+1, column=1)
entry[i][2] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][2].insert(0, str(result[1][i][1]))
entry[i][2].configure(state='readonly')
entry[i][2].grid(row=i+1, column=2)
entry[i][3] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][3].insert(0, str(result[1][i][2]))
entry[i][3].configure(state='readonly')
entry[i][3].grid(row=i+1, column=3)
entry[i][4] = Entry(frame, width=30, validate="focusin", vcmd=holdfocus)
entry[i][4].insert(0, result[1][i][3])
entry[i][4].configure(state='readonly')
entry[i][4].grid(row=i+1, column=4)
if not openfile.called:
Button(buttonpane, text="Show Selected", width=10, command=show).pack()
Button(buttonpane, text="Extract Events", width=10, command=exte).pack()
Button(buttonpane, text="Extract X-Props", width=10, command=extx).pack()
menubar = tk.Menu(window)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open...", command=openfile, accelerator="Ctrl+O")
filemenu.add_command(label="Save", command=save, accelerator="Ctrl+S")
filemenu.add_command(label="Save As...", command=saveas)
filemenu.add_command(label="Combine...", command=combine)
filemenu.add_command(label="Filter...", command=filter)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=exit, accelerator="Ctrl+X")
menubar.add_cascade (label="File", menu=filemenu)
todomenu = tk.Menu(menubar, tearoff=0)
todomenu.add_command(label="To-do List...", command=todo, accelerator="Ctrl+T")
todomenu.add_command(label="Undo", command=undo, accelerator="Ctrl+Z")
menubar.add_cascade (label="Todo", menu=todomenu)
datemenu = tk.Menu(menubar, tearoff=0)
datemenu.add_command(label="Date Mask...", command=datemsk)
datemenu.add_command(label="About xcal...", command=aboutme)
menubar.add_cascade (label="Help", menu=datemenu)
basemenu = tk.Menu(menubar, tearoff=0)
basemenu.add_command(label="Store All", command=storeall)
basemenu.add_command(label="Store Selected", command=storesel)
basemenu.add_command(label="Clear", command=clearsql)
basemenu.add_command(label="Status", command=dbstatus)
basemenu.add_command(label="Query", command=querysql)
menubar.add_cascade (label="Database", menu=basemenu)
window.bind_all("<Control-o>", openk)
window.bind_all("<Control-s>", savek)
window.bind_all("<Control-x>", exitk)
window.bind_all("<Control-t>", todok)
window.bind_all("<Control-z>", undok)
window.config(menu=menubar)
openfile.called = True
openfile.called = False
def exit():
if not saved.get():
saveprompt = saveDialog(window)
window.wait_window(saveprompt.top)
if saveprompt.cancel.get():
return
else:
close()
def close():
if result[0] != 1:
Cal.freeFile(result[0])
os.system("rm -f .xcal.* .*.ics")
database.close()
sys.exit();
def todo():
todoprompt = todoDialog(window)
def undo():
global completed
for c in completed:
c[0].grid(row=int(c[0].get()), column=0)
c[1].grid(row=int(c[0].get()), column=1)
c[2].grid(row=int(c[0].get()), column=2)
c[3].grid(row=int(c[0].get()), column=3)
c[4].grid(row=int(c[0].get()), column=4)
entry.insert(int(c[0].get())-1, c)
completed = []
def datemsk():
datemaskvar = fd.askopenfilename()
if datemaskvar != "" and datemaskvar != None:
os.environ['DATEMSK'] = datemaskvar
def aboutme():
top = Toplevel(window)
top.wm_title("About xcal")
title = "xcal"
author = "Bronson Graansma"
version = "iCalendar v2.0"
Label(top, text=title, font=("Times", 22, "bold"), fg="navy").pack()
Label(top, text="by "+author, font=("Helvetica", 14), fg="blue").pack()
Label(top, text="compatible with "+version, font=("Helvetica", 10), fg="blue").pack()
center(top)
top.resizable(0, 0)
def openk(self):
openfile()
def savek(self):
save()
def exitk(self):
exit()
def todok(self):
todo()
def undok(self):
undo()
def clear():
logtext.set("")
def center(toplevel):
toplevel.update_idletasks()
w = toplevel.winfo_screenwidth()
h = toplevel.winfo_screenheight()
size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
x = w/2 - size[0]/2
y = h/2 - size[1]/2
toplevel.geometry("%dx%d+%d+%d" % (size + (x, y)))
def initpane():
e = Entry(frame, width=5)
e.insert(0,'No.')
e.configure(state='readonly', justify='center')
e.grid(row=0, column=0)
e = Entry(frame, width=25)
e.insert(0,'Name')
e.configure(state='readonly', justify='center')
e.grid(row=0, column=1)
e = Entry(frame, width=5)
e.insert(0,'Props')
e.configure(state='readonly', justify='center')
e.grid(row=0, column=2)
e = Entry(frame, width=5)
e.insert(0,'Subs')
e.configure(state='readonly', justify='center')
e.grid(row=0, column=3)
e = Entry(frame, width=30)
e.insert(0,'Summary')
e.configure(state='readonly', justify='center')
e.grid(row=0, column=4)
for i in range(8):
Entry(frame, width=5, state="readonly").grid(row=i+1, column=0)
Entry(frame, width=25, state="readonly").grid(row=i+1, column=1)
Entry(frame, width=5, state="readonly").grid(row=i+1, column=2)
Entry(frame, width=5, state="readonly").grid(row=i+1, column=3)
Entry(frame, width=30, state="readonly").grid(row=i+1, column=4)
def scrollto(event):
canvas.configure(scrollregion=canvas.bbox("all"), width=590,height=190)
def scrolltolog(event):
logcanvas.configure(scrollregion=logcanvas.bbox("all"), width=590,height=190)
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
class Dialog:
def __init__(self, parent):
top = self.top = Toplevel(parent)
top.title("Date Mask")
Label(top, text="Date Mask is not currently set.\nWould you like to set it now?").pack(padx=10, pady=10)
Button(top, text=" Yes ", command=combine_funcs(datemsk, top.destroy))\
.pack(in_=top, side=LEFT, expand=YES)
Button(top, text="Not now", command=top.destroy).pack(in_=top, side=LEFT, expand=YES)
top.resizable(0,0)
center(top)
class queryDialog:
def scrollyto(self, event):
self.rightcanvas.configure(scrollregion=self.rightcanvas.bbox("all"))
def help(self):
helpscrn = Toplevel(self.top)
describe = StringVar()
rows=0
helpscrn.title("Help")
winder = Frame(helpscrn)
cursor.execute("DESCRIBE ORGANIZER")
Label(winder, text="ORGANIZER").pack()
frame = Frame(winder)
for f in cursor.fetchall():
rows += 1
Label(frame, text=str(f[0])).grid(row=rows, column=0)
Label(frame, text="|" ).grid(row=rows, column=1)
Label(frame, text=str(f[1])).grid(row=rows, column=2)
frame.pack()
Frame(winder, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
cursor.execute("DESCRIBE EVENT")
Label(winder, text="EVENT").pack()
frame = Frame(winder)
for f in cursor.fetchall():
rows += 1
Label(frame, text=str(f[0])).grid(row=rows, column=0)
Label(frame, text="|" ).grid(row=rows, column=1)
Label(frame, text=str(f[1])).grid(row=rows, column=2)
frame.pack()
Frame(winder, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
cursor.execute("DESCRIBE TODO")
Label(winder, text="TODO").pack()
frame = Frame(winder)
for f in cursor.fetchall():
rows += 1
Label(frame, text=str(f[0])).grid(row=rows, column=0)
Label(frame, text="|" ).grid(row=rows, column=1)
Label(frame, text=str(f[1])).grid(row=rows, column=2)
frame.pack()
winder.pack()
helpscrn.resizable(0,0)
center(helpscrn)
def submit(self):
if self.v.get() == 1:
cursor.execute("SELECT summary FROM EVENT INNER JOIN ORGANIZER \
ON ORGANIZER.org_id=EVENT.organizer AND ORGANIZER.name=\"{}\"\
".format(self.orgEntry.get()))
self.text.set(self.text.get()+\
"------------------------------------------------------------\n")
for f in cursor.fetchall():
self.text.set(self.text.get()+str(f[0])+"\n")
cursor.execute("SELECT summary FROM TODO INNER JOIN ORGANIZER \
ON ORGANIZER.org_id=TODO.organizer AND ORGANIZER.name=\"{}\""\
.format(self.orgEntry.get()))
elif self.v.get() == 2:
cursor.execute("SELECT summary FROM EVENT WHERE location=\"{}\"".format(self.locEntry.get()))
self.text.set(self.text.get()+\
"------------------------------------------------------------\n")
elif self.v.get() == 3:
if self.startEntry.get() != "" and self.endEntry.get() != "":
cursor.execute("SELECT summary FROM EVENT WHERE start_time >=\"{}\" AND start_time <=\"{}\""\
.format(self.startEntry.get(), self.endEntry.get()))
elif self.startEntry.get() != "":
cursor.execute("SELECT summary FROM EVENT WHERE start_time >=\"{}\"".format(self.startEntry.get()))
elif self.endEntry.get() != "":
cursor.execute("SELECT summary FROM EVENT WHERE start_time <=\"{}\"".format(self.endEntry.get()))
else:
return
self.text.set(self.text.get()+\
"------------------------------------------------------------\n")
elif self.v.get() == 4:
cursor.execute("SELECT summary FROM TODO WHERE priority <={}".format(self.priorEntry.get()))
self.text.set(self.text.get()+\
"------------------------------------------------------------\n")
elif self.v.get() == 5:
string = ""
try:
cursor.execute(self.selEntry.get(1.0, "end"))
except sql.Error:
string = "Syntax Error\n"
self.text.set(self.text.get()+\
"------------------------------------------------------------\n")
if string != "":
self.text.set(self.text.get()+string)
return
for f in cursor.fetchall():
self.text.set(self.text.get()+str(f)+"\n")
return
elif self.v.get() == 6:
tables = ("EVENT", "ORGANIZER", "TODO")
keys = ("event_id", "org_id", "todo_id")
rand = randint(0,2)
cursor.execute("SELECT MIN({}), MAX({}) FROM {}"\
.format(keys[rand], keys[rand], tables[rand]))
fetched = cursor.fetchall()
if fetched != None:
cursor.execute("SELECT * FROM {} WHERE {}={}"\
.format(tables[rand], keys[rand], randint(fetched[0][0], fetched[0][1])))
for f in cursor.fetchall():
self.text.set(self.text.get()+str(f[1])+"\n")
return
for f in cursor.fetchall():
self.text.set(self.text.get()+str(f[0])+"\n")
def clearResults(self):
self.text.set("")
def __init__(self, parent):
top = self.top = Toplevel(parent)
top.title("Query")
v = self.v = IntVar()
leftpane = Frame(top)
rightpane = Frame(top, relief="sunken", bd=1)
frame = Frame(leftpane)
subframe = Frame(frame)
Radiobutton(subframe, text="Display the items of:", variable=v, value=1).pack(side="left")
self.orgEntry = Entry(subframe)
self.orgEntry.pack(side="right")
subframe.pack(side="top")
Label(frame, text="(organizer)").pack(side="bottom")
frame.pack(anchor="w")
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
frame = Frame(leftpane)
Radiobutton(frame, text="Display the events that take place in:", variable=v, value=2).pack(side="top")
self.locEntry = Entry(frame)
Label(frame, text="(location)").pack(side="right")
self.locEntry.pack(side="right")
frame.pack(anchor="w")
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
frame = Frame(leftpane)
Radiobutton(frame, text="Display the events that take place between:", variable=v, value=3).pack(side="top", anchor="w")
self.endEntry = Entry(frame, width=15)
self.endEntry.pack(side="right")
Label(frame, text="and").pack(side="right")
self.startEntry = Entry(frame, width=15)
self.startEntry.pack(side="right")
frame.pack(anchor="w")
Label(leftpane, text="YYYY-MM-DD HH:MM:SS").pack()
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
frame = Frame(leftpane)
Radiobutton(frame, text="Display to-do items prioritized:", variable=v, value=4).pack(side="left")
self.priorEntry = Entry(frame, width=5)
self.priorEntry.pack(side="left")
Label(frame, text="or higher").pack(side="left")
frame.pack(anchor="w")
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
Radiobutton(leftpane, text="Randomize", variable=v, value=6).pack(anchor="w")
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
frame = Frame(leftpane)
Radiobutton(frame, variable=v, value=5).pack(side="left")
self.selEntry = Text(frame, height=6, width=40)
self.selEntry.insert("end", "SELECT ")
self.selEntry.pack(side="left")
frame.pack(anchor="w")
Frame(leftpane, height=2, bd=1, relief="sunken").pack(fill="x", padx=5, pady=5)
frame = Frame(leftpane)
Button(frame, text=" Help ", command=self.help).pack(side="left" )
Button(frame, text="Submit", command=self.submit).pack(side="right")
frame.pack()
leftpane.pack(side="left")
self.text = StringVar()
self.rightcanvas = Canvas(rightpane, bg="white")
scrolly = Scrollbar(rightpane, orient="vertical", command=self.rightcanvas.yview)
self.rightcanvas.configure(yscrollcommand=scrolly.set)
scrolly.pack(side="left", fill="y")
frame = Frame(self.rightcanvas, bg="white")
Label(frame, textvariable=self.text, justify="left", bg="white")\
.pack(fill="both", expand="yes")
self.rightcanvas.pack(side="left", fill="both", expand="yes")
self.rightcanvas.create_window((0, 0), window=frame, anchor='nw')
frame.bind("<Configure>", self.scrollyto)
Button(rightpane, text="Clear", command=self.clearResults).pack()
rightpane.pack(side="right", padx=5, pady=5, fill="both")
top.resizable(0,0)
center(top)
class saveDialog:
def cancelwin(self):
self.cancel.set(True)
self.top.destroy()
def cancelk(self, parent):
self.cancelwin()
def __init__(self, parent):
self.cancel = BooleanVar()
self.cancel.set(False)
top = self.top = Toplevel(parent)
top.title("Quit")
Label(top, text="Discard changes before quitting?").pack(padx=10, pady=10)
Button(top, text="Cancel", command=self.cancelwin)\
.pack(in_=top, side=LEFT, expand=YES)
Button(top, text="Discard", command=combine_funcs(top.destroy, close))\
.pack(in_=top, side=LEFT, expand=YES)
Button(top, text="Save", command=combine_funcs(save, top.destroy, close))\
.pack(in_=top, side=LEFT, expand=YES)
top.protocol('WM_DELETE_WINDOW', self.cancelwin)
top.bind_all("<Escape>", self.cancelk)
top.resizable(0,0)
center(top)
class todoDialog:
def cancelwin(self):
self.cancel.set(True)
self.top.destroy()
def done(self):
j = 0
removed = 0
for i in range(len(result[1])):
if result[1][i][0] == "VTODO":
if j < len(self.vars) and self.vars[j].get():
entry[i-removed][0].grid_remove()
entry[i-removed][1].grid_remove()
entry[i-removed][2].grid_remove()
entry[i-removed][3].grid_remove()
entry[i-removed][4].grid_remove()
completed.append(entry[i-removed])
entry.remove(entry[i-removed])
removed+=1
j+=1
self.top.destroy()
def cancelk(self, parent):
self.cancelwin()
def scrollto(self, event):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def stateof(self):
for var in self.vars:
if var:
self.b.config(state="normal")
return
self.b.config(state="disabled")
def __init__(self, parent):
self.cancel = BooleanVar()
self.cancel.set(False)
top = self.top = Toplevel(parent)
top.title("To-do List")
self.vars = []
self.check = []
todos = Frame(top, relief="sunken", bd=1)
todos.pack(ipadx=5, ipady=5)
self.canvas = Canvas(todos)
scrollBar = Scrollbar(todos, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=scrollBar.set)
scrollBar.pack(side="left", fill="y")
frame = Frame(self.canvas)
for i in range(len(entry)):
if entry[i][1].get() == "VTODO":
self.vars.append(BooleanVar())
self.vars[-1].set(False)
c = Checkbutton(frame, command=self.stateof, text=entry[i][4].get(),\
variable=self.vars[-1], onvalue=True, offvalue=False, justify="left")
c.grid(row=i, sticky="w")
self.check.append(c)
self.canvas.pack(side="left", fill="x", expand="yes")
self.canvas.create_window((0, 0), window=frame, anchor='nw')
frame.bind("<Configure>", self.scrollto)
self.b = Button(top, text="Done", command=self.done, state="disabled")
self.b.pack()
top.protocol('WM_DELETE_WINDOW', self.cancelwin)
top.bind_all("<Escape>", self.cancelk)
top.resizable(0,0)
center(top)
class openDialog:
def cancelwin(self):
self.cancel.set(True)
self.top.destroy()
def cancelk(self, parent):
self.cancelwin()
def __init__(self, parent):
self.cancel = BooleanVar()
self.cancel.set(False)
top = self.top = Toplevel(parent)
top.title("Open")
Label(top, text="Discard changes before opening a new file?").pack(padx=10, pady=10)
Button(top, text="Cancel", command=self.cancelwin)\
.pack(in_=top, side=LEFT, expand=YES)
Button(top, text="Discard", command=top.destroy)\
.pack(in_=top, side=LEFT, expand=YES)
Button(top, text="Save", command=combine_funcs(save, top.destroy))\
.pack(in_=top, side=LEFT, expand=YES)
top.protocol('WM_DELETE_WINDOW', self.cancelwin)
top.bind_all("<Escape>", self.cancelk)
top.resizable(0,0)
center(top)
class fDialog:
def okbutton(self):
Button(self.top, text=" OK ", command=combine_funcs(self.callFilter, self.top.destroy))\
.grid(row=2, column=2)
def callFilter(self):
fromvar = ""
tovar = ""
if self.val.get() != "e" and self.val.get() != "t":
return
if self.fromdate.get() != "":
fromvar = " from "
self.fromdate.set("\""+self.fromdate.get()+"\"")
if self.todate.get() != "":
tovar = " to "
self.todate.set("\""+self.todate.get()+"\"")
os.system("./caltool -filter "+self.val.get()+fromvar+self.fromdate.get()+tovar+\
self.todate.get()+" < .save.ics > .xcal.log 2> .xcal.tmp")
logtext.set(logtext.get()+"\n\n"+open(".xcal.log").read()+open(".xcal.tmp").read())
os.system("cat .xcal.log > .save.ics")
os.system("rm -f .xcal.*")
tup = Cal.readFile(".save.ics")
result[0] = tup[0]
result[1] = tup[1]
if result[0] == "error":
logtext.set(logtext.get()+"\n\n"+result[1])
return
global entry
for e in entry:
for r in e:
r.destroy()
entry = []
for i in range(len(result[1])):
s = StringVar()
s.set("")
entry.append([s, s, s, s, s])
entry[i][0] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][0].insert(0, str(i+1))
entry[i][0].configure(state='readonly')
entry[i][0].grid(row=i+1, column=0)
entry[i][1] = Entry(frame, width=25, validate="focusin", vcmd=holdfocus)
entry[i][1].insert(0, result[1][i][0])
entry[i][1].configure(state='readonly')
entry[i][1].grid(row=i+1, column=1)
entry[i][2] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][2].insert(0, str(result[1][i][1]))
entry[i][2].configure(state='readonly')
entry[i][2].grid(row=i+1, column=2)
entry[i][3] = Entry(frame, width=5, validate="focusin", vcmd=holdfocus)
entry[i][3].insert(0, str(result[1][i][2]))
entry[i][3].configure(state='readonly')
entry[i][3].grid(row=i+1, column=3)
entry[i][4] = Entry(frame, width=30, validate="focusin", vcmd=holdfocus)
entry[i][4].insert(0, result[1][i][3])
entry[i][4].configure(state='readonly')
entry[i][4].grid(row=i+1, column=4)
def __init__(self, parent):
self.val = StringVar()
self.fromdate = StringVar()
self.todate = StringVar()
top = self.top = Toplevel(parent)
top.title("Filter")
Label(top, text="Content:").grid(row=0, column=0)
Radiobutton(top, text="Todo" , variable=self.val, value="t", command=self.okbutton)\
.grid(row=0, column=1)
Radiobutton(top, text="Event", variable=self.val, value="e", command=self.okbutton)\
.grid(row=0, column=2)
Label(top, text="From:").grid(row=1, column=0)
Label(top, text="To:" ).grid(row=1, column=2)
Entry(top, textvariable=self.fromdate).grid(row=1, column=1)
Entry(top, textvariable=self.todate).grid(row=1, column=3)
Button(top, text="Cancel", command=top.destroy).grid(row=2, column=1)
top.resizable(0,0)
center(top)
############################GUI building begins here######################################
username = ""
hostname = "dursley.socs.uoguelph.ca"
password = ""
database = None
if len(sys.argv) > 1:
username = sys.argv[1]
if len(sys.argv) > 2:
hostname = sys.argv[2]
else:
print("Usage: "+sys.argv[0]+" <username> <optional hostname>")
sys.exit()
for i in range(3):
try:
password = getpass.getpass("password for "+username+": ")
database = sql.connect(database=username, user=username, password=password, host=hostname)
except sql.Error:
print("Failed to connect to "+hostname+"\n"+str(sql.Error))
if i == 2:
sys.exit()
else:
break
cursor = database.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS ORGANIZER (\
org_id INT AUTO_INCREMENT PRIMARY KEY,\
name VARCHAR(60) NOT NULL, \
contact VARCHAR(60) NOT NULL)")
cursor.execute("CREATE TABLE IF NOT EXISTS TODO (\
todo_id INT AUTO_INCREMENT PRIMARY KEY,\
summary VARCHAR(60) NOT NULL,\
priority SMALLINT,\
organizer INT,\
FOREIGN KEY(organizer) REFERENCES ORGANIZER(org_id) ON DELETE CASCADE)")
cursor.execute("CREATE TABLE IF NOT EXISTS EVENT (\
event_id INT AUTO_INCREMENT PRIMARY KEY,\
summary VARCHAR(60) NOT NULL,\
start_time DATETIME NOT NULL,\
location VARCHAR(60) NOT NULL,\
organizer INT,\
FOREIGN KEY(organizer) REFERENCES ORGANIZER(org_id) ON DELETE CASCADE)")
window = tk.Tk()
filename = StringVar()
saved = BooleanVar()
saved.set(True)
focus = None
entry = []
result = [1, 2]
completed = []
window.title('xcal')
window.minsize(width=605+110, height=415)
window.tk.call('wm', 'iconphoto', window._w, PhotoImage(file='ical.png'))
center(window)
window.protocol('WM_DELETE_WINDOW', exit)
menubar = tk.Menu(window)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Open...", command=openfile, accelerator="Ctrl+O")
filemenu.add_separator()
filemenu.add_command(label="Exit", command=exit, accelerator="Ctrl+X")
menubar.add_cascade (label="File", menu=filemenu)
datemenu = tk.Menu(menubar, tearoff=0)
datemenu.add_command(label="Date Mask...", command=datemsk)
datemenu.add_command(label="About xcal...", command=aboutme)
menubar.add_cascade (label="Help", menu=datemenu)
window.bind_all("<Control-o>", openk)
window.bind_all("<Control-x>", exitk)
window.config(menu=menubar)
mainframe = Frame(window)
myframe = Frame(mainframe, relief="sunken", bd=1)
canvas = Canvas(myframe)
frame = Frame(canvas)
myscrollbar = Scrollbar(myframe, orient="vertical", command=canvas.yview)
canvas.configure(yscrollcommand=myscrollbar.set)
myscrollbar.pack(side="right", fill="y")
canvas.pack(side="left", fill="x", expand=YES)
canvas.create_window((0, 0), window=frame, anchor='nw')
frame.bind("<Configure>", scrollto)
initpane()
mylog = Frame(mainframe, relief="sunken", bd=1, bg="white")
logcanvas = Canvas(mylog, bg="white")
logframe = Frame(logcanvas)
logscrollbar = Scrollbar(mylog, orient="vertical", command=logcanvas.yview)
logcanvas.configure(yscrollcommand=logscrollbar.set)
logscrollbar.pack(side="right", fill="y")
logcanvas.pack(side="left", fill="x", expand=YES)
logcanvas.create_window((0, 0), window=logframe, anchor='w')
logframe.bind("<Configure>", scrolltolog)
logcanvas.configure(scrollregion=logcanvas.bbox("all"), width=590,height=190)
logtext = StringVar()
Label(logframe, justify=LEFT, textvariable=logtext, bg="white").grid(row=0, ipadx=5, ipady=5)
buttonpane = Frame(mainframe)
clearpane = Frame(mainframe)
Button(clearpane, text="Clear", width=10, command=clear).pack()
myframe.grid(row=0, column=0)
buttonpane.grid(row=0, column=1)
mylog.grid(row=1, column=0)
clearpane.grid(row=1, column=1)
mainframe.grid(row=0)
window.update()
if os.environ.get('DATEMSK') == None:
dialog = Dialog(window)
window.wait_window(dialog.top)
window.mainloop()