#!/usr/bin/env python
#----------------------------------------------------------------------------
# Name:         pagenda.py
#
# Purpose:	Multi-user capable calendar/schedule.
#		Written in Python, using wxWidgets and the sqlite database.
#		Prints daily schedules of appointments..
#		
# Author:       Paul Sherman <psherma1@rochester.rr.com>
#		http://www.pcbypaul.com
#
# Created:      11/14/2005
# CVS-ID:       not in CVS :(
# Copyright:    (c) 2005-2007 by Paul Sherman
# License:      GPL2
#----------------------------------------------------------------------------
### IMPORTS ############################################################################
import os, sys, shutil, tempfile, time, datetime, string, commands, math, re, _strptime, csv
import wx
import wx.lib.calendar
import wx.lib.dialogs
try:
	import images
except:
	print >>sys.stderr, "The file \"images.py\" was not found, it is needed to run pAgenda"
	sys.exit()
	
import wx.html as html
from pysqlite2 import dbapi2 as sqlite

if wx.Platform == "__WXMSW__":
	from win32com.shell import shell, shellcon
	import pythoncom
	import _winreg

### Globals ###########################################################################

test_days = []
# check and set flag for write access to program directory	   
datadir = os.path.dirname(os.path.realpath(sys.argv[0]))
data_acc = False
if os.access(datadir, os.W_OK):
	data_acc = True
# get user home directory
if wx.Platform == "__WXMSW__":
	df = shell.SHGetDesktopFolder()
	pidl = df.ParseDisplayName(0, None, "::{450d8fba-ad25-11d0-98a8-0800361b1103}")[1]
	basedir = shell.SHGetPathFromIDList(pidl)
else:
	basedir = wx.GetHomeDir()
	
infoText = '''
<html>
<body>
<center>
<font color="#23632e">
<h2>pAgenda - v3.2</h2>
</font>
<BR>
<font size=-1>(c)2005-2006 by Paul Sherman
<BR>
<a href="mailto:psherma1@rochester.rr.com">psherma1@rochester.rr.com</a>
<BR>
http://www.pcbypaul.com
<BR>
Licence: GPL2
</font>
</center>
<BR>
<p><b>Help:</b></p><BR><BR>
<UL><LI>By <b>selecting a date</b> on the calendar, any appointment you have 
entered for that date will show up on this page, with the day/date 
at the top and each appointment time and description listed below.
</LI></UL><BR><BR>
<UL><LI>
Appointments for any day may be added or removed via the <b>right-click menu</b> on this page.
</LI></UL><BR><BR>
<UL><LI>
Appointments may NOT be made for dates previous to the current date. 
</LI></UL><BR><BR>

<UL><LI>
<b>Alerts</b> (reminders) will pop up every hour while the application is running. 
 They display appointments for the current day and tomorrow. They can be turned off permanently 
 from the appointment page right-click menu. They can also be turned off for the day from a button 
 on the reminder pop-up page.
</LI></UL><BR><BR>

<UL><LI>
<b>To-Do items</b> can be added in one of two ways. First, there is the ability to add TO-DOs 
for any day, without specifying a time. Any such TO-DO is added to the top of the daily schedule. The 
second type of To-Do is in separate list used to reference quickly at any time, without tying it 
to any specific date.
</LI></UL><BR><BR>
<UL><LI>
The <b>Contacts</b> page allows you to keep a list of names with information including 
email addresses. If you enter an email, pAgenda will make a clickable link out of it for you to show 
up on the contacts page.
</LI></UL><BR><BR>
<UL><LI>
Both appointments and contacts can be imported from other pAgenda databases.
</LI></UL><BR><BR>
<UL><LI>
The Contacts list has several additional import/export options. The list of contacts can be exported 
as a CSV (comma separated value) list. Also, such a list can be imported.
<br><br>There is the added ability to import a CSV file originally exported from a 
Windows <b>Outlook Express Address Book.</b> 
<br>
While running the Address Book for Windows choose <br>
<b>File->Export->Other Addrress Book</b><br>
Then pick <b>Text File (Comma Separated Values)</b><br>
After you pick whichever values you'd like to export, name the file with a <b>.csv</b> suffix. 
</LI></UL><BR><BR>
<UL><LI>
The <b>Remove Old</b> menu item is a way to clean up the database. Using it will remove all appointments 
prior to the current date. They are not automatically deleted because many people like a record 
of appointments, and they do not take up much space. Hundreds of old appointments, however, can slow down 
the application -- so backing up the DB once in a while would be best for those who 
like to keep track all those old events.
</LI></UL><BR><BR>
<UL><LI>
Selecting <b>Print</b> from the popup menu (or the print button) will print out the current contents 
of this page.
</LI></UL><BR><BR>
<UL><LI>Select <b>Add a Schedule</b> to include other people's calendars, or schedules for separate activities.
(Many folks keep a separate work schedule, or a sport schedule, etc.) It is worthwhile to mention 
that pAgenda looks for and stores all information in the current user's home (My Documents on Windows) 
folder. So folks logged in as different users do not see each others schedules. If more than one 
person uses the PC as the same user, however, different schedules for the separate users become 
a necessity.
</LI></UL><BR><BR>
<UL><LI>
A <b>separate database</b> is generated for each user/schedule. It is located in the user's home 
or My Documents folder and is the same as the name you gave the schedule -- prepended by an 
underscore \"<b>_</b>\" and followed by the extension \"<b>.db</b>\". 
<br><br>
This is the file you could copy to make a &quot;backup&quot; of your schedule/contacts. It is a small 
database file and can easily be copied to disk or sent to a friend/associate. If the other person uses pAgenda 
they can simply drop that file into their home (or My Documents) directory, and the next time they start 
pAgenda that schedule/contact list will appear. Handy, and without any need to import/export anything.
</LI></UL><BR><BR>
<UL><LI>
<b>Clicking the email link:</b> In Windows the default mailer will open with the \"To\" field filled in; 
under Linux pAgenda will attempt to find your email client and do the same... but under Linux you also can 
choose your email client or enter a custom string to start one using the <b>Set Mail Client</b> menu. 
This menu does not appear in Windows.
</LI></UL><BR><BR>
</body>
</html>
'''	

dHeader1 = '''<html><body><center><table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td align="center"><h2>							'''	
dHeadAppt = '''<!-- Appt -->'''
dHeadCont = '''<!-- Cont -->'''
dHeadTodo = '''<!-- Todo -->'''
dHeader2 = '''</h2></td></tr></table></center>'''	

dFooter = '</body></html>'


# self.clockStyle:
SHOW_QUARTERS_TICKS = 1
SHOW_HOURS_TICKS    = 2
SHOW_MINUTES_TICKS  = 4
ROTATE_TICKS        = 8
SHOW_HOURS_HAND     = 16
SHOW_MINUTES_HAND   = 32
SHOW_SECONDS_HAND   = 64
SHOW_SHADOWS        = 128
OVERLAP_TICKS       = 256

# self.tickMarkHoursStyle and self.tickMarkMinutesStyle:
TICKS_NONE          = 1
TICKS_SQUARE        = 2
TICKS_CIRCLE        = 4
TICKS_POLY          = 8
TICKS_DECIMAL       = 16
TICKS_ROMAN         = 32
	   
########################################################################## TOP FRAME ######################
########################################################################## TOP FRAME ######################
		
class MyTaskBarIcon(wx.TaskBarIcon):
		def __init__(self, frame):
			wx.TaskBarIcon.__init__(self)
	
			self.frame = frame
			icon1=wx.EmptyIcon()
		
			icon1.CopyFromBitmap(images.getTaskBitmap())
			self.SetIcon(icon1, "pyAgenda")
		
			self.Bind(wx.EVT_MENU, self.OnTaskBarActivate, id=1)
			self.Bind(wx.EVT_MENU, self.OnTaskBarDeactivate, id=2)
			self.Bind(wx.EVT_MENU, self.OnTaskBarClose, id=3)
	
		def CreatePopupMenu(self):
			menu = wx.Menu()
			menu.Append(1, 'Show pAgenda')
			menu.Append(2, 'Hide pAgenda')
			menu.Append(3, 'Close Calendar')
			return menu
	
		def OnTaskBarClose(self, event):
			self.frame.Close()
	
		def OnTaskBarActivate(self, event):
			if not self.frame.IsShown():
				self.frame.Show()
	
		def OnTaskBarDeactivate(self, event):
			if self.frame.IsShown():
				self.frame.Hide()

  
		
class CalendFrame(wx.Frame):
	
	def __init__(self, parent, id, title):
		
		### set up the sizes and some initial variables
		tmax = wx.GetDisplaySize()
		if tmax[0] > 1020: tmax[0] = 1020
		if tmax[0] > 790:
			xDefault = 780
		else:
			xDefault = 620
	
		wx.Frame.__init__(self, parent, id, title,size=(xDefault, 370))
		
		self.aptTimes = []
		self.tmp = tempfile.mktemp(".html")
		self.curDateTable = "a" + time.strftime("%Y%m%d",time.localtime(time.time()))
		self.dbName = None
		self.ulist = self.GetUsers()
		col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
		self.SetBackgroundColour(col1)
	
		# make sure we have a user ######################
		if not self.ulist: self.addUser(1)
					
		# now set the user database ###########################################################
		####if len(self.GetUsers()) == 0: print "No Users"
		# exit if nothing found or created
		if self.dbName == None:
			if os.path.exists(os.path.join(basedir, '_' + self.GetUsers()[0] + '.db')):
				self.dbName = os.path.join(basedir, '_' + self.GetUsers()[0] + '.db')
			else:
				if os.path.exists(os.path.join(datadir, '__' + self.GetUsers()[0] + '.db')):
					self.dbName = os.path.join(datadir, '__' + self.GetUsers()[0] + '.db')					

		# and with that we make sure we have all needed support tables in place ###############
		self.checkDB()
		
		# And get the mailer string if we are on Linux and it is set
		if wx.Platform == "__WXGTK__":
			self.mailStr = self.getMailtoStr(self.dbName)
		else:
			self.mailStr = "mailto:"

		# make app icon for Linux ############################################################
		try:
			icon1=wx.EmptyIcon()
			icon1.CopyFromBitmap(images.getIconBitmap())
			self.SetIcon(icon1)
		except:
			print >>sys.stderr, "Unable to import the applications images"
			sys.exit()

		if wx.Platform == "__WXMSW__":
			self.tskic = MyTaskBarIcon(self)
		 
		 
		### Set up the GUI ###################################################################
		
		self.psize = 307
		self.SetSizeHints(620, 370, -1, -1)
		#self.SetSizeHints(620, 370, tmax[0], ymax)
		self.panel1 = wx.Panel(self,-1, size=(self.psize, self.psize))
		
		#  clock ##################################
		clock = AnalogClockWindow(self)
		clock.SetTickStyles(h=SHOW_HOURS_HAND | SHOW_MINUTES_HAND)

		clock.SetHandColours(wx.Colour(66,66,128))
		clock.SetTickColours(wx.Colour(66,66,128))
		clock.SetClockStyle(SHOW_HOURS_TICKS | SHOW_SHADOWS)
		clock.SetTickSizes(h=16)

		# Page Display ############################
		self.panel2 = AppointmentPage(self)
		
		# Toolbar  ################################
		self.MakeToolMenu()
		
		box = wx.BoxSizer(wx.HORIZONTAL)
		leftbox = wx.BoxSizer(wx.VERTICAL)
		leftbox.Add(self.panel1, 0, wx.TOP | wx.BOTTOM | wx.RIGHT, 2)
		leftbox.Add(clock, 1, wx.ALL | wx.EXPAND, 0)
		
		box.Add(leftbox, 0, wx.TOP | wx.BOTTOM | wx.LEFT, 2)
		box.Add(self.panel2, 1, wx.EXPAND, 0)

		self.SetAutoLayout(True)
		self.SetSizer(box)
		self.panel2.Layout()
		self.Layout()
		
		self.h = box.GetSize().GetHeight() + 2
		self.makeCalendar(self.h)
		clock.SetSizeHints(300,300, -1, -1)
		
		self.ResetDisplay()	
		self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
		self.curDateTable = "a" + string.zfill(str(self.calend.GetYear()), 4) + string.zfill(str(self.calend.GetMonth()),2) + string.zfill(str(self.calend.GetDay()),2)
		self.printer = html.HtmlEasyPrinting()

		refreshPage(self.dbName, self.curDateTable, self)

		
		
	def hourly_callback(self):
		if self.checkAlerts(self.dbName) == 'n':
			return
		today = datetime.date.today()
		cdate = "a" + string.zfill(today.year, 4) + string.zfill(today.month, 2) + string.zfill(today.day, 2)
		if self.checkSkip(self.dbName) == cdate:
			return
		
		try:
			self.win.Close(True)
		except:
			pass	
		
		d = "a" + time.strftime("%Y%m%d",time.localtime(time.time()))
		d1 = "a" + time.strftime("%Y%m%d",time.localtime(time.time() + 86400))
		have_appts_today = 0
		have_appts_tom = 0
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		
		try:
			query = 'pragma table_info(%s)' % d
			cur.execute(query)
			ret = cur.fetchall()
			if ret:
				query = 'SELECT * FROM (%s)' % d
				cur.execute(query)
				ret = cur.fetchone()
				if ret:
					have_appts_today = 1
		except:
			pass
				
		try:			
			query = 'pragma table_info(%s)' % d1
			cur.execute(query)
			ret = cur.fetchall()
			if ret:
				query = 'SELECT * FROM (%s)' % d1
				cur.execute(query)
				ret = cur.fetchone()
				if ret:
					have_appts_tom = 1
		except:
			pass
					
		cur.close()
		con.close()	
		if have_appts_today == 1 or have_appts_tom == 1:			
			self.win = alert_frame(self, self.dbName)
			self.win.Show() 
		
		
	def getDB_Name(self):
		lStr = os.path.join(basedir, '_' + self.tb.FindControl(1000).GetValue() + '.db')
		gStr = os.path.join(datadir, '__' + self.tb.FindControl(1000).GetValue() + '.db')
		if os.path.exists(lStr):
			return lStr
		elif os.path.exists(gStr):
			return gStr
		else:
			return
		
		
	def checkDB(self):
		# check contacts table
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("pragma table_info(contacts)")
		ret = cur.fetchone()
		cur.close()
		con.close()
		if not ret:
			self.makeContactsTable(self.dbName)


		# check options table
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("pragma table_info(options)")
		ret = cur.fetchone()
		cur.close()
		con.close()
		if not ret:
			self.makeOptionsTable(self.dbName)
		# below is for backward compatability prior to version 3.0
		# if only one options value, we rebuild the table with new options,
		# saving the previous caltype value. "oldCalTypeVal"
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("pragma table_info(options)")
		t = cur.fetchone()
		ret = cur.fetchone()
		ret = cur.fetchone()
		cur.close()
		con.close()
		if not ret:
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute("SELECT caltype FROM options")
			oldCalTypeVal = cur.fetchone()[0]
			cur.close()
			con.close()
			self.makeOptionsTable(self.dbName, oldCalTypeVal) 
		
		
		# check ToDo table
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("pragma table_info(todo)")
		ret = cur.fetchone()
		cur.close()
		con.close()
		if not ret:
			self.makeTodoTable(self.dbName)
			
			
		# check mailer table (for Linux users)
		if wx.Platform == "__WXGTK__":
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute("pragma table_info(mailer)")
			ret = cur.fetchone()	
			cur.close()
			con.close()
			if not ret:
				self.makeMailerTable(self.dbName)
		

		
	def getMailtoStr(self, db):
		# check for a setting first
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("SELECT mailstr FROM mailer")
		mailer = cur.fetchone()
		cur.close()
		con.close()
		if mailer: return mailer[0]
		# then common mailers if no set
		if len(commands.getoutput('type -path sylpheed')):
			return 'sylpheed --compose'
		if len(commands.getoutput('type -path kmail')):
			return 'kmail --composer'
		if len(commands.getoutput('type -path evolution')):
			return 'evolution'
		if len(commands.getoutput('type -path mozilla-thunderbird')):
			return 'mozilla-thunderbird -compose'
		if len(commands.getoutput('type -path balsa')):
			return 'balsa -m'
		
		
		
	def makeCalendar(self,h):
		self.calend = wx.lib.calendar.Calendar(self.panel1, -1, size=(self.h, self.h - 4))
		self.calend.SetCurrentDay()
		self.calend.SetMargin(2,2)
		ps = self.h - 2
		self.panel1.SetSizeHints(ps,ps,ps,ps)
		self.Bind(wx.lib.calendar.EVT_CALENDAR, self.MouseClick, self.calend)
		self.calend.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown, self.calend)
		
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("pragma table_info(options)")
		ret = cur.fetchone()
		cur.close()
		con.close()
		if not ret:
			self.makeOptionsTable(self.dbName)
			return
			
		if self.checkOptions(self.dbName) == "BUS":
			self.calend.SetBusType()
	
	
	def OnKeyDown(self, event):
		if event.GetKeyCode() == wx.WXK_SPACE:
			return self.MouseClick(self.calend)
			#event.Skip()
			#return

		event.Skip()	
	
	
	def makeOptionsTable(self, db, oldVal= None):
		if oldVal:
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("drop table options")
			con.commit()
			cur.close()
			con.close()
		
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("CREATE TABLE options(caltype str, alerts str, skipalert str)")
		con.commit()
		if oldVal:
			v1 = oldVal
		else:
			v1 = 'NORMAL'
		v2 = 'y'
		v3 = 'zzz'
		vals = v1, v2, v3
		query = "insert into options (caltype, alerts, skipalert) values (?, ?, ?)"
		cur.execute(query, vals)
		con.commit()	
		cur.close()
		con.close()

		
		
	def makeContactsTable(self, db):
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("CREATE TABLE contacts(lname str, fname str, address1 str, address2 str, telephone str, email str, comment str)")
		con.commit()	
		cur.close()
		con.close()

	def makeMailerTable(self, db):
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("CREATE TABLE mailer(mailstr str)")
		con.commit()	
		cur.close()
		con.close()

	def makeTodoTable(self, db):
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("CREATE TABLE todo(subject str, details str)")
		con.commit()	
		cur.close()
		con.close()
			
	def checkOptions(self, db):
		try:
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("pragma table_info(options)")
			ret = cur.fetchall()
			if ret:
				cur.execute("SELECT caltype FROM options")
				val = cur.fetchone()[0]

			cur.close()
			con.close()
			return val
		except:
			return "doh!"
			
			
			
	def checkAlerts(self, db):
		try:
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("pragma table_info(options)")
			ret = cur.fetchall()
			if ret:
				cur.execute("SELECT alerts FROM options")
				val = cur.fetchone()[0]
			cur.close()
			con.close()
			return val
		except:
			return "doh!"
			
			
			
	def checkSkip(self, db):
		try:
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("pragma table_info(options)")
			ret = cur.fetchall()
			if ret:
				cur.execute("SELECT skipalert FROM options")
				val = cur.fetchone()[0]
			cur.close()
			con.close()
			return val
		except:
			return "doh!"			

			
			
	def MouseClick(self, evt):
		self.aptTimes = []
		when = datetime.date(evt.year, evt.month, evt.day)
		displayName = when.strftime("%A, %m/%d/%Y")
		# convert to a sring -- additionally, prefix a letter or will error
		
		self.curDateTable = "a" + string.zfill(evt.year, 4) + string.zfill(evt.month, 2) + string.zfill(evt.day, 2)
		self.dbName = self.getDB_Name()
		if self.dbName == None:
			dlg = wx.MessageDialog(self, 'Sorry, \n\nThere has been an error accessing the database\n', "Access Error", wx.OK | wx.ICON_EXCLAMATION )
        		dlg.ShowModal()
			dlg.Destroy()
			return	
		####################################################################
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		query = 'pragma table_info(%s)' % self.curDateTable
		cur.execute(query)
		ret = cur.fetchall()
		if not ret:
			query = 'CREATE TABLE %s(apttime str, appt str, abstime str)' % self.curDateTable
			cur.execute(query)
			con.commit()
			cur.close()
			con.close()
		refreshPage(self.dbName, self.curDateTable, self)
		


	def addUser(self, evt=None):
		bdir = basedir
		db_prefix = "_"
		if evt == 1:
			mTxt = "pAgenda needs to create a schedule database.\n\nDo you wish to make the schedule available to all users?"
		else:
			mTxt = "Do you wish to make the new calendar schedule available to all users?"
		if data_acc:
			dlg = wx.MessageDialog(self, mTxt, "Schedule Creation", wx.YES_NO | wx.NO_DEFAULT  | wx.ICON_QUESTION)
        		if dlg.ShowModal() == wx.ID_YES:
				dlg.Destroy()
				bdir = datadir
				db_prefix = "__"
			else:
				dlg.Destroy()

		
		dlg = wx.TextEntryDialog( self, 'To create a new calendar,\nenter a new schedule name below.\n','Add a Schedule')
        	dlg.SetValue("")
        	if dlg.ShowModal() == wx.ID_OK:
			ret = dlg.GetValue()
			dlg.Destroy()
            		if not ret:
				self.Destroy
			else:
				if ret[0] == "_":
					dlg = wx.MessageDialog(self, 'Sorry, \n\nA schedule name cannot begin with the \"_\" character...\n', "Invalid Name", wx.OK | wx.ICON_EXCLAMATION )
        				dlg.ShowModal()
					dlg.Destroy()
					return
				self.ulist.append(ret)
				dbname = os.path.join(bdir, db_prefix + ret + '.db')
				# make sure db is not there already
				if os.path.exists(dbname):
					dlg = wx.MessageDialog(self, 'Sorry, \n\nThat schedule name is already being used...\n', "Duplicate Schedule", wx.OK | wx.ICON_EXCLAMATION )
        				dlg.ShowModal()
					dlg.Destroy()
					return
				self.dbName = dbname
				con = sqlite.connect(dbname)
				con.commit()
				cur = con.cursor()
				cur.execute("PRAGMA auto_vacuum = 1")
				con.commit()
				cur.close()	
				con.close()
				if evt != 1: self.tb.FindControl(1000).Append(ret)
				self.makeOptionsTable(dbname)
				self.makeContactsTable(dbname)
				if wx.Platform == "__WXGTK__": self.makeMailerTable(dbname)
		else:
			dlg.Destroy()
			if evt == 1:
				print >>sys.stderr, "pAgenda needs to create database schedule to run"
				sys.exit()
			
			
	def OnCloseWindow(self, event):
		if os.path.exists(self.tmp):
			try:
				os.remove(self.tmp)
			except:
				pass
		if data_acc: self.flushDB()
		if wx.Platform == "__WXMSW__":
			self.tskic.Destroy()
		self.Destroy()

	def ResetDisplay(self):
        	month = self.calend.GetMonth()
		d = self.calend.GetDate()
		ns = "a" + str(d[2]) + string.zfill(d[1], 2)
		ns_list = []
		for i in range(31):
			j = string.zfill(i, 2)
			ns_list.append(ns + j)
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		tb_list = []
		for n in ns_list:
			query = 'pragma table_info(%s)' % n
			cur.execute(query)
			ret = cur.fetchone()
			if ret:
				tb_list.append(n)		
		hasAppt_list = []
		for tb in tb_list:
			query = 'SELECT * FROM %s order by abstime' % tb 
			cur.execute(query)
			data = cur.fetchone()
			if data: hasAppt_list.append(int(tb[-2:]))	
		cur.close()
		con.close()
        	self.calend.SetSelDay(hasAppt_list)
		self.calend.SetColor('highlight_background', wx.Colour(200,200,226))   
		self.calend.SetColor('selection_background', wx.Colour(255,255,200)) 
		self.calend.SetColor('header_font', wx.Colour(0, 66, 0))                  
        	self.calend.Refresh()


	def OnIncYear(self, event):
        	self.calend.IncYear()
        	self.ResetDisplay()

	def OnDecYear(self, event):
        	self.calend.DecYear()
        	self.ResetDisplay()

	def OnIncMonth(self, event):
        	self.calend.IncMonth()
        	self.ResetDisplay()

	def OnDecMonth(self, event):
        	self.calend.DecMonth()
        	self.ResetDisplay()

	def OnCurrent(self, event):
        	self.calend.SetCurrentDay()
		today = datetime.date.today()
		self.curDateTable = "a" + string.zfill(today.year, 4) + string.zfill(today.month, 2) + string.zfill(today.day, 2)
        	self.ResetDisplay()
		refreshPage(self.dbName, self.curDateTable, self) 

	def OnPrint(self, event=None):
		self.printer.PrintFile(self.panel2.GetOpenedPage())
	
	def ShowHelp(self, evt=None):
		AppointmentPage.reLoad(self.panel2,infoText)
		self.Refresh()
		
	def ShowContacts(self, evt=None):
		refreshContacts(self.dbName, self)
		self.Refresh()

	def ShowTodo(self, evt=None):
		refreshTodo(self.dbName, self)
		self.Refresh()
				
	def OnClose(self, event):	
		d = wx.MessageDialog( self, '\nAre you sure?', 'Exit pAgenda', wx.YES_NO )
		r = d.ShowModal()
		if r==wx.ID_YES:
			if wx.Platform == "__WXGTK__": print "pAgenda -- \"Over and Out!\""
			self.Close()

	def MakeToolMenu(self):
		self.tb = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)
		self.tb.SetToolBitmapSize((32,32))
		
        	mID = 101
		self.tb.AddTool(mID, images.getYearDnBitmap(), shortHelpString="Previous Year")
        	self.Bind(wx.EVT_TOOL, self.OnDecYear, id=mID)
		
        	mID = 012
        	self.tb.AddTool(mID, images.getMonthDnBitmap(), shortHelpString='Previous Month')
        	self.Bind(wx.EVT_TOOL, self.OnDecMonth, id=mID)

        	mID = 103
        	self.tb.AddTool(mID, images.getHomeBitmap(), shortHelpString='Current Date')
        	self.Bind(wx.EVT_TOOL, self.OnCurrent, id=mID)

        	mID = 104
        	self.tb.AddTool(mID, images.getMonthUpBitmap(), shortHelpString='Next Month')
        	self.Bind(wx.EVT_TOOL, self.OnIncMonth, id=mID)

        	mID = 105
        	self.tb.AddTool(mID, images.getYearUpBitmap(), shortHelpString='Next Year')
        	self.Bind(wx.EVT_TOOL, self.OnIncYear, id=mID)
		
        	mID = 201
        	self.tb.AddTool(mID, images.getPhantomBitmap())
		self.tb.EnableTool(mID, False)
		
        	mID = 202
        	self.tb.AddTool(mID, images.getUsersBitmap(), shortHelpString='Add a Schedule')
        	self.Bind(wx.EVT_TOOL, self.addUser, id=mID)

		mID = 1000
		self.tb.AddControl(wx.ComboBox(self.tb, mID, "", choices=self.ulist,
                	size=(150,-1), style=wx.CB_DROPDOWN | wx.CB_READONLY))
		self.Bind(wx.EVT_COMBOBOX, self.changeDB, id=mID)
			
        	mID = 203
        	self.tb.AddTool(mID, images.getPhantomBitmap())
		self.tb.EnableTool(mID, False)
		
		mID = 204
        	self.tb.AddTool(mID, images.getPrintLgBitmap(), shortHelpString='Print Appointments')
		self.Bind(wx.EVT_TOOL, self.OnPrint, id=mID)
		
        	mID = 300
        	self.tb.AddTool(mID, images.getContactsBitmap(), shortHelpString='Contacts')
        	self.Bind(wx.EVT_TOOL, self.ShowContacts, id=mID)
		
        	mID = 302
        	self.tb.AddTool(mID, images.getTodoBitmap(), shortHelpString='To-Do List')
        	self.Bind(wx.EVT_TOOL, self.ShowTodo, id=mID)		
		
        	mID = 301
        	self.tb.AddTool(mID, images.getCloseBitmap(), shortHelpString='Close')
        	self.Bind(wx.EVT_TOOL, self.OnClose, id=mID)
		
		self.tb.FindControl(1000).SetSelection(0)
		self.dbName = self.getDB_Name()
		self.SetToolBar(self.tb)
		self.tb.Realize()
			
	def GetUsers(self):
		# check "home" directory for db files
		lst = os.listdir(basedir)
		dblist = []
		i = 0
		for f in lst:
			if f[0] == '_' and f[-3:] == '.db':
				dblist.append(f[1:-3])
			i += 1
		# check program directory for db files
		# trap error and go on if not readable
		try:
			lst = os.listdir(datadir)
			for f in lst:
				if f[0:2] == '__' and f[-3:] == '.db':
					dblist.append(f[2:-3])
				i += 1
		except:
			pass

		return dblist
		
	def changeDB(self, evt):
		self.dbName = self.getDB_Name()
		self.checkDB()
		self.ResetDisplay()
		
		# this will determine the type of page without being displayed ###
		t1 = self.panel2.GetParser().GetSource()
		t2 = dHeader1 + "Contacts"
		if t1 == infoText:
			pass
		elif string.count(t1,t2) > 0:
			refreshContacts(self.dbName, self)
		else:
			refreshPage(self.dbName, self.curDateTable, self) 

	def parseConList(self,db):
		con = sqlite.connect(db)
		cur = con.cursor()
		cur.execute("pragma table_info(contacts)")
		ret = cur.fetchall()
		if not ret:
			dlg = wx.MessageDialog(self, '%s \ndoes not appear to contain a contacts list.' % db, "No Contacts List", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			cur.close()
			con.close()
		cur.execute("SELECT * FROM contacts order by lname")
		data = cur.fetchall()
		cur.close()
		con.close()
		self.newList = []
		if data:
			self.newList.append(["lastName", "firstName", "address1", "address2", "telephone", "email", "comment"])
			for row in data:
				tmp = [item for item in row]
				self.newList.append(tmp)
		else:
			dlg = wx.MessageDialog(self, '%s \ndoes not appear to contain any contacts.' % db, "No Contacts To Export", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
		return self.newList	
		
		
	def flushDB(self):
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		tb_list = []
		#cur.execute("select tbl_name from sqlite_master")
		cur.execute("select name from sqlite_master WHERE type='table' ORDER BY name")
		ret = cur.fetchall()

		datelist = []
		for tb in ret:
			tbTmp = str(tb)[3:-3]
			if tbTmp[0] == 'a':
				datelist.append(str(tb)[3:-3])
				

		tb_list = []
		for n in datelist:
			#query = 'pragma table_info(%s)' % n
			query = 'select * from ' + n
			cur.execute(query)
			ret = cur.fetchone()
			#if ret: print ret
			if not ret:
				tb_list.append(n)		
		for n in tb_list:
				query = 'drop table ' + n
				cur.execute(query)
		con.commit()	
		cur.close()
		con.close()
		#self.ResetDisplay()
		
	
###################################################################### DISPLAY PAGE ################################
###################################################################### DISPLAY PAGE ################################

class AppointmentPage(html.HtmlWindow):

	def __init__(self, parent, pageText=None):

        	html.HtmlWindow.__init__(self, parent, -1, style=wx.NO_FULL_REPAINT_ON_RESIZE | wx.SUNKEN_BORDER)
		self.parent = parent
		if not pageText:
			pageText = infoText
		FILE = open(self.parent.tmp,"w")
    		FILE.write(pageText)
		FILE.close()
		self.LoadPage(self.parent.tmp)
		self.Layout()

		if os.path.exists(self.parent.dbName):
			if not os.access(self.parent.dbName, os.W_OK):
				return
		
		self.Bind(wx.EVT_RIGHT_UP, self._popMenu)
		
		
	def OnLinkClicked(self, linkinfo):
		lnk = linkinfo.GetHref()
		if string.count(lnk,'mailto:') > 0:
			ret = string.find(lnk,'mailto')
			lnk = lnk[ret+7:]
			if wx.Platform == "__WXMSW__":
                                cmd = 'start %s%s' % (self.parent.mailStr, lnk)
				print cmd
			else:
				cmd = '%s  \"%s\"' % (self.parent.mailStr, lnk)
			os.system(cmd)
		else:
			MessageDlg(self.parent, "For security reasons pAgenda will only process links for emails at this time.")	
		
		
		
	def reLoad(self, txt=None):
		if not txt:
			txt = infoText
		FILE = open(self.parent.tmp,"w")
    		FILE.write(txt)
		FILE.close()
		self.LoadPage(self.parent.tmp)
		self.Layout()	
		# below is to disable the right-click menu if the DB we are using is read-only
		if os.path.exists(self.parent.dbName):
			if not os.access(self.parent.dbName, os.W_OK):
				try:
					self.Unbind(wx.EVT_RIGHT_UP)
					self.menu.Destroy()
					
				except:
					return
				return
		
		self.Bind(wx.EVT_RIGHT_UP, self._popMenu)	
	
	
	def _popMenu(self, evt):
		if os.path.exists(self.parent.dbName):
			if not os.access(self.parent.dbName, os.W_OK):
				return
			
		# unbind first 2 items to switch bindings ####################
		self.Unbind(wx.EVT_MENU, id=1)
		self.Unbind(wx.EVT_MENU, id=2)
		self.Unbind(wx.EVT_MENU, id=301)
		self.Unbind(wx.EVT_MENU, id=400)
		
		self.Bind(wx.EVT_MENU, self.OnPrint, id=3)
		self.Bind(wx.EVT_MENU, self.OnDelete, id=4)
		self.Bind(wx.EVT_MENU, self.OnSunday, id=5)
		self.Bind(wx.EVT_MENU, self.OnAlerts, id=411)
		if wx.Platform == "__WXMSW__":self.Bind(wx.EVT_MENU, self.OnStartup, id=412)
		self.Bind(wx.EVT_MENU, self.OnHelp, id=6)
		self.Bind(wx.EVT_MENU, self.OnImportApt, id=101)
		self.Bind(wx.EVT_MENU, self.OnImportApt, id=102)
		self.Bind(wx.EVT_MENU, self.OnImportCSV, id=103)
		self.Bind(wx.EVT_MENU, self.OnImportOE, id=104)
		self.Bind(wx.EVT_MENU, self.OnExportContacts, id=201)
		##################################################################################
        	self.menu = wx.Menu()
		self.dbName = self.parent.getDB_Name()
		##################################################################################
		# this will determine the type of page being displayed ###
		# header comments are embedded in each type of page to impliment this more easily 
		t1 = self.GetParser().GetSource()[:70]
		if not t1.find("<!-- Todo -->") == -1:
			self.pType = "todo"
		elif not t1.find("<!-- Appt -->") == -1:
			self.pType = "appointment"
		elif not t1.find("<!-- Cont -->") == -1:
			self.pType = "contact"
		else:
			self.pType = "info"
        	# add #########################################################
		if self.pType == "appointment":
			self.Bind(wx.EVT_MENU, self.AddAppointment, id=1)
        		item = wx.MenuItem(self.menu, 1,"Add an Appointment")
        		bmp = images.getAddBitmap()
        		item.SetBitmap(bmp)
        		self.menu.AppendItem(item)

			self.Bind(wx.EVT_MENU, self.AddTodo, id=301)
        		item301 = wx.MenuItem(self.menu, 301,"Add a To-Do item")
        		bmp301 = images.getAddBitmap()
        		item301.SetBitmap(bmp301)
        		self.menu.AppendItem(item301)			
			
			# below is to disable adding appointments in the past
			calDate = self.parent.calend.GetDate()
			calTime = [calDate[2], calDate[1], calDate[0] + 1, 0, 0, 0, 0, 0 ,0]
			realDate = datetime.datetime.now()
			ct = time.mktime(calTime)
			rt = time.mktime(realDate.timetuple())	
			if ct - rt < 0:
				item.Enable(False)
				item301.Enable(False)
				
		elif self.pType == "contact":
			self.Bind(wx.EVT_MENU, self.AddContact, id=1)
        		item = wx.MenuItem(self.menu, 1,"Add a Contact")
        		bmp = images.getAddBitmap()
        		item.SetBitmap(bmp)
        		self.menu.AppendItem(item)
			
		elif self.pType == "todo":
			self.Bind(wx.EVT_MENU, self.AddListTodo, id=400)
        		item400 = wx.MenuItem(self.menu, 400,"Add to ToDo List")
        		bmp400 = images.getAddBitmap()
        		item400.SetBitmap(bmp400)
        		self.menu.AppendItem(item400)
		else:
			pass

        	# remove #####################################################
		item2 = wx.MenuItem(self.menu, 2,"Remove one")
		bmp2 = images.getRemoveBitmap()
		item2.SetBitmap(bmp2)
		self.menu.AppendItem(item2)
		if self.pType == "appointment":
			self.Bind(wx.EVT_MENU, self.OnRemApt, id=2)
			if not self.parent.aptTimes:
				item2.Enable(False)
		elif self.pType == "contact":
			self.Bind(wx.EVT_MENU, self.OnRemCon, id=2)
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute("SELECT lname FROM contacts")
			ret = cur.fetchone()
			cur.close()
			con.close()
			if not ret:	
				item2.Enable(False)
		elif self.pType == "todo":
			self.Bind(wx.EVT_MENU, self.OnRemTodo, id=2)
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute("SELECT subject FROM todo")
			ret = cur.fetchone()
			cur.close()
			con.close()
			if not ret:	
				item2.Enable(False)
		else:
			item2.Enable(False)
				
		# print ######################################################
		item3 = wx.MenuItem(self.menu, 3,"Print this page")
		bmp3 = images.getPrintSmBitmap()
		item3.SetBitmap(bmp3)
		self.menu.AppendItem(item3)
		if self.pType == "appointment":
			if not self.parent.aptTimes:
				item3.Enable(False)
		elif self.pType == "contact":
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute("SELECT lname FROM contacts")
			ret = cur.fetchone()
			cur.close()
			con.close()
			if not ret:	
				item3.Enable(False)
		else:
			item3.Enable(False)

		self.menu.AppendSeparator() 

		# import appointments or contacts #############################
		imp = wx.Menu()
		item101 = wx.MenuItem(self.menu, 101)
		imp.Append(101, "Import Appointments")

		item102 = wx.MenuItem(self.menu, 102)
		imp.Append(102, "Import Contacts")
		
		imp.AppendSeparator() 
		
		item103 = wx.MenuItem(self.menu, 103)
		imp.Append(103, "pAgenda CSV")
		
		item104 = wx.MenuItem(self.menu, 104)
		imp.Append(104, "Outlook CSV")
		
		item100 = wx.MenuItem(self.menu, 100,"Import", subMenu=imp)
        	bmp100 = images.getImportBitmap()
        	item100.SetBitmap(bmp100)
		self.menu.AppendItem(item100)

		# Export Contacts #####################################
		item20 = wx.MenuItem(self.menu, 201,"Export Contacts")
		bmp20 = images.getExportBitmap()
		item20.SetBitmap(bmp20)
		item20.SetHelp("Export Contacts")
		self.menu.AppendItem(item20)


		# Delete old appointments #####################################
		item4 = wx.MenuItem(self.menu, 4,"Delete Old Stuff")
		bmp4 = images.getDelTableBitmap()
		item4.SetBitmap(bmp4)
		item4.SetHelp("Clear away old appointments")
		self.menu.AppendItem(item4)
		
		# Option ######################################################
		item5 = wx.MenuItem(self.menu, 5, "Sunday First", kind=wx.ITEM_CHECK)
		self.menu.AppendItem(item5)
		if self.parent.checkOptions(self.dbName) == "NORMAL":
			self.menu.Check(5, True)
			
		item411 = wx.MenuItem(self.menu, 411, "Alerts", kind=wx.ITEM_CHECK)
		self.menu.AppendItem(item411)
		if self.parent.checkAlerts(self.dbName) == "y":
			self.menu.Check(411, True)
			
			
		if wx.Platform == "__WXMSW__":
                        item412 = wx.MenuItem(self.menu, 412, "Run on Startup", kind=wx.ITEM_CHECK)
			self.menu.AppendItem(item412)
			if self.checkStartup():
				self.menu.Check(412, True)
		
			
		self.menu.AppendSeparator() 
		
		# Help ########################################################
		item6 = wx.MenuItem(self.menu, 6,"Help")
		bmp6 = images.getHelpBitmap()
		item6.SetBitmap(bmp6)
		self.menu.AppendItem(item6)
		
		if wx.Platform == "__WXGTK__":
		
			sm = wx.Menu()
			item8 = wx.MenuItem(self.menu, 8)
			sm.Append(8, "Sylpheed")
			self.Bind(wx.EVT_MENU, self.setSylpheed, id=8)
			
			item9 = wx.MenuItem(self.menu, 9)
			sm.Append(9, "Kmail")
			self.Bind(wx.EVT_MENU, self.setKmail, id=9)
			
			item10 = wx.MenuItem(self.menu, 10)
			sm.Append(10, "Evolution")
			self.Bind(wx.EVT_MENU, self.setEvolution, id=10)
			
			item11 = wx.MenuItem(self.menu, 11)
			sm.Append(11, "Thunderbird")
			self.Bind(wx.EVT_MENU, self.setThunderbird, id=11)
			
			item12 = wx.MenuItem(self.menu, 12)
			sm.Append(12, "Balsa")
			self.Bind(wx.EVT_MENU, self.setBalsa, id=12)

			sm.AppendSeparator() 

			item13 = wx.MenuItem(self.menu, 13)
			sm.Append(13, "Enter Custom")
			self.Bind(wx.EVT_MENU, self.setCustom, id=13)
			
			item7 = wx.MenuItem(self.menu, 7,"Set Mail Client", subMenu=sm)
        		bmp7 = images.getMailBitmap()
        		item7.SetBitmap(bmp7)
			self.menu.AppendItem(item7)
			
			
		
        	# show the menu
        	self.PopupMenu(self.menu, evt.GetPosition())
        	self.menu.Destroy()



	def checkStartup(self):
		regpath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
		try:
			reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, regpath)
			val = _winreg.QueryValueEx(reg, "pAgenda")
                        if val:
                            _winreg.CloseKey(reg)
                            return True
                        else:
                            return False
		except EnvironmentError:
			return False
			
			
						
	def OnExportContacts(self, evt):
		db = self.dbName
		if db == None:return
		cList = self.parent.parseConList(db)
		if not cList: return
		efile = self.getExportPath()
		if not efile: return
		try:
			writer = csv.writer(open(efile, "wb"))
			writer.writerows(cList)
		except:
			dlg = wx.MessageDialog(self.parent, '%s \nCould not save as a CSV file.' % efile, "Problem Writing File", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			return			

	def getImportPath(self, typeof):
		if typeof == "db":
			wc = "Sqlite Database  (*.db)|*.db"
		elif typeof == "csv":
			wc = "Sqlite Database  (*csv)|*.csv"
		else:
			wc = "Sqlite Database  (*.db)|*.db"
			
		if wx.Platform == "__WXMSW__":
			df = shell.SHGetDesktopFolder()
			pidl = df.ParseDisplayName(0, None, "::{450d8fba-ad25-11d0-98a8-0800361b1103}")[1]
			mydocs = shell.SHGetPathFromIDList(pidl)
		else:
			mydocs = wx.GetHomeDir()	
        	dlg = wx.FileDialog(self.parent, message="Choose a database to import...", defaultDir=mydocs, 
			defaultFile="", style=wx.OPEN | wx.FILE_MUST_EXIST)
		dlg.SetWildcard(wc)
        	if dlg.ShowModal() == wx.ID_OK:
			path = dlg.GetPath()
			dlg.Destroy()
			return path
        	dlg.Destroy()

	def getExportPath(self):
		if wx.Platform == "__WXMSW__":
			df = shell.SHGetDesktopFolder()
			pidl = df.ParseDisplayName(0, None, "::{450d8fba-ad25-11d0-98a8-0800361b1103}")[1]
			mydocs = shell.SHGetPathFromIDList(pidl)
		else:
			mydocs = wx.GetHomeDir()	

		defName = "contacts.csv"	
        	dlg = wx.FileDialog(self.parent, message="Save contact to a csv file...", defaultDir=mydocs, 
			defaultFile=defName, style=wx.SAVE)
		dlg.SetWildcard("CSV file  (*.csv)|*.csv")
		
        	if dlg.ShowModal() == wx.ID_OK:
			path = dlg.GetPath()
			dlg.Destroy()
			ext = ".csv"
			if os.path.splitext(path)[1] != ext: path += ext
			if os.path.exists(path):
				dlg = wx.MessageDialog(self.parent, 'That file already exists --  \nDo you wish to replace the existing file?',
                				       'Overwrite Confirmation', wx.YES_NO | wx.ICON_INFORMATION)

				if dlg.ShowModal() == wx.ID_YES:
					dlg.Destroy()
					return path
				else:
					dlg.Destroy()
					return
			return path
        	dlg.Destroy()


	def OnImportCSV(self, event):
		fn = self.getImportPath("csv")
		if fn == None:return
		# read in first line, then the rest of the file
		try:
			reader = csv.reader(open(fn, "rb"))
		except:
			dlg = wx.MessageDialog(self.parent, '%s \nCould not read the requested file.' % fn, "Problem Reading File", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			return		
		lines = []
		for row in reader:
			lines.append(row)
		if not lines[0] == ['lastName', 'firstName', 'address1', 'address2', 'telephone', 'email', 'comment']:
			dlg = wx.MessageDialog(self.parent, '%s \nis not a pAgenda CSV file or has been corrupted.' % fn, "Problem Reading File", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			return
		if len(lines) < 2:
			dlg = wx.MessageDialog(self.parent, "There does not appear to be any readable contact information in the selected file..", "No Data Available", wx.OK | wx.ICON_INFORMATION )
        		dlg.ShowModal()
			dlg.Destroy
			return
			
		mFields = lines[0]
		
		whole = lines[1:]		
		tmpArray = []
		for line in whole:
			tmpArray.append(line)
		self.csvImport(tmpArray)


	def OnImportOE(self, event):
		fn = self.getImportPath("csv")
		if fn == None:return
		# read in first line, then the rest of the file
		try:
		 reader = csv.reader(open(fn, "rb"))
		except:
			dlg = wx.MessageDialog(self.parent, '\n%s \n\nCould not read the requested file.' % fn, "Problem Reading File", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			return		
		lines = []
		for row in reader:
			lines.append(row)
		if len(lines) < 2:
			dlg = wx.MessageDialog(self.parent, "There does not appear to be any readable contact information in the selected file..", "No Data Available", wx.OK | wx.ICON_INFORMATION )
        		dlg.ShowModal()
			dlg.Destroy
			return
			
		mFields = lines[0]
		whole = lines[1:]
		i = 0
		p0 = p1 = p2 = p3 = p4 = p5 = p6 = p7 = p8 = p10 = p11 = p12 = p13 = p14 = ""
		for itm in mFields:
			itm = itm.strip()
			if itm == "Last Name":
				p0 = i
			elif itm == "First Name":
				p1 = i
			elif itm == "Home Phone":
				p2 = i
			elif itm == "E-mail Address":
				p3 = i
			elif itm == "Notes":
				p4 = i
			elif itm == "Home Street":
				p5 == i
			elif itm == "Home City":
				p6 = i
			elif itm == "Home State":
				p7 = i
			elif itm == "Home Postal Code":
				p8 = i
			##############################
			elif itm == "Business Phone":
				p10 == i
			elif itm == "Business Street":
				p11 == i
			elif itm == "Business City":
				p12 = i
			elif itm == "Business State":
				p13 = i
			elif itm == "Business Postal Code":
				p14 = i
				
			else:
				pass				
			i += 1
			
			
		if p0 == "" or p1 == "":			
			dlg = wx.MessageDialog(self.parent, '\n%s \n\nThis file does not appear to be a proper OE Address Book CSV file.' % fn, "Address Book Import Error", wx.OK | wx.ICON_ERROR )
        		dlg.ShowModal()
			dlg.Destroy()
			return	
		
		tmpArray = []
		for lines in whole:
			items = []
			for l in lines:
				items.append(l)
		
			# this avoids line-breaking BS, esp. at end of file
			if len(items) < 2: continue
			if p0 == "" or p1 == "":
				pass
			else:
				lname = items[p0]
				fname = items[p1]
				email = items[p3]
				#
				comment = ""
				phone = ""
				add1 = ""
				add2 = ""
				#
				# home phone not present, but business phone is
				if p2 == "" and not p10 == "":
					phone = items[p10]
				#	p10 = ""
				# both home phone and business phone
				elif not p2 == "" and not p10 == "":
					comment = 'Business Phone ' + items[p10]
				elif p2 == "" and p10 == "":
					phone = ""
				else:
					phone = items[p2]

				# home address not present, but business address is
				# put
				if p5 == "" and not p11 == "":
					add1 = 'Business Address: ' + items[p11]
					if p12: add2 = items[p12] + ', '
					if p13: add2 = add2 + items[p13] + '  '
					if p14: add2 = add2 + items[p14] 
				# both home address and business address
				elif not p5 == "" and not p11 == "":
					add1 = comment + 'Business Address: ' + items[p11] 
					if p12: comment = comment + items[p12] + ', '
					if p13: comment = comment + items[p13] + '  '
					if p14: comment = comment + items[p14]
				# neither home or business adddress 1 present
				elif p5 == "" and p11 == "":
					add1 = ""
				# home address there, but no business address
				else:
					add1 = items[p5]
					
					add2 = items[p6] + ', ' + items[p7] + '  ' + items[p8]

				##### 7 fields to be passed to pagends ######
				##  last, first, add1, add2, phone, email, coment ##
				##  p0, p1, p5, p6, p2, p3, p4   ## 
				#
				comment = comment + items[p4]
				tmpArray.append([lname,fname,add1,add2,phone,email,comment])
		self.csvImport(tmpArray)



	def OnImportApt(self, event):
		db = self.getImportPath("db")
		if db == None:return
		m_id = event.GetId()
		if m_id == 101:
			win = self.ImportAptFrame(self, "Import", db, self.dbName, style=wx.DEFAULT_FRAME_STYLE)
		else:
			win = self.ImportConFrame(self, "Import", db, self.dbName, style=wx.DEFAULT_FRAME_STYLE)
		
		#win.SetSize((440, 400))
		win.CenterOnParent(wx.BOTH)
		win.Show(True)	
	
	
	
	def OnImportCon(self, event):
		db = self.getImportPath("db")
		if db == None:return
		
		

	def setSylpheed(self, event):
		mstr = 'sylpheed --compose'
		self.parent.mailStr = mstr
		self.saveMailStr(mstr)
		
		
		
	def setKmail(self, event):
		mstr = 'kmail --composer'
		self.parent.mailStr = mstr
		self.saveMailStr(mstr)
		
		
		
	def setEvolution(self, event):
		mstr = 'evolution'
		self.parent.mailStr = mstr
		self.saveMailStr(mstr)
		
		
		
	def setThunderbird(self, event):
		mstr = 'mozilla-thunderbird -compose'
		self.parent.mailStr = mstr
		self.saveMailStr(mstr)
		
		
		
	def setBalsa(self, event):
		mstr = 'balsa -m'
		self.parent.mailStr = mstr
		self.saveMailStr(mstr)		
		
		
		
	def setCustom(self, event):
        	dlg = wx.TextEntryDialog(
                	self, 'What is your favorite programming language?',
                	'Enter a custom email string')
        	if dlg.ShowModal() == wx.ID_OK:
			mstr = dlg.GetValue()
        		self.parent.mailStr = mstr
			self.saveMailStr(mstr)
        	dlg.Destroy()
		
		
		
	def saveMailStr(self, mailer):
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("SELECT * FROM mailer")
		data = cur.fetchone()
		if data:	
			cur.execute("delete from mailer")
			con.commit()
		query = 'insert into mailer (mailstr) values ("%s")' % mailer	
		cur.execute(query)
		con.commit()
		cur.close()
		con.close()
	
	
	
	def AddAppointment(self, evt):
		win = self.AptFrame(self, "Add an Appointment", style=wx.DEFAULT_FRAME_STYLE)
		win.SetSize((460, 300))
		win.CenterOnParent(wx.BOTH)
		win.Show(True)	



	def AddTodo(self, evt):
		win = self.todoFrame(self, "Add a ToDo Item", style=wx.DEFAULT_FRAME_STYLE)
		win.SetSize((460, 300))
		win.CenterOnParent(wx.BOTH)
		win.Show(True)	
	
	
	
	def AddContact(self, evt):
		win = self.ContactFrame(self, "Add a Contact", style=wx.DEFAULT_FRAME_STYLE)
		win.SetSize((420, 420))
		win.CenterOnParent(wx.BOTH)
		win.Show(True)	



	def AddListTodo(self, evt):
		win = self.todoListFrame(self, "Add To ToDo List", style=wx.DEFAULT_FRAME_STYLE)
		win.SetSize((460, 400))
		win.CenterOnParent(wx.BOTH)
		win.Show(True)	
		
		
		
	def OnRemApt(self, event):
		ftop = self.parent
	        dlg = wx.SingleChoiceDialog(self, 'Choose the Appointment you wish to delete.', 'Remove an Appointment', ftop.aptTimes, wx.CHOICEDLG_STYLE)
        	if dlg.ShowModal() == wx.ID_OK:
            		apt_time = dlg.GetStringSelection()
		else:
			dlg.Destroy()
			return
        	dlg.Destroy()
		# get all them variables ###################
		dt = string.split(apt_time, ' ')[0]
		
		if dt[:2] == "**":
			secTime = dt[-2:]
		else:
			td = ftop.calend.GetDate()
			tt = string.zfill(td[2], 4) + '/' + string.zfill(td[1], 2) + '/' + string.zfill(td[0], 2) + ',' + dt
			t = time.strptime(tt,"%Y/%m/%d,%I:%M%p")
			secTime = str(int(time.mktime(t)))	

		# now delete that sucker ####################
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		query = 'delete from ' +  str(ftop.curDateTable) + ' where abstime = ' + secTime
		cur.execute(query)
		con.commit()
		cur.close()
		con.close()
		ftop.ResetDisplay()
		refreshPage(self.dbName, ftop.curDateTable, ftop)
		
		
	
	def OnRemCon(self, event):
		ftop = self.parent
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("SELECT lname, fname FROM contacts order by lname")
		data = cur.fetchall()
		cur.close()
		con.close()
		if data:
			displaylist = []
			for row in data:
				tmp = [item for item in row]
				displaylist.append(str(tmp[0]) + ', ' + str(tmp[1]))

	        dlg = wx.SingleChoiceDialog(self, 'Choose the Contact you wish to delete.', 'Remove an Contact', displaylist, wx.CHOICEDLG_STYLE)
        	if dlg.ShowModal() == wx.ID_OK:
            		con_name = dlg.GetStringSelection()
		else:
			dlg.Destroy()
			return
        	dlg.Destroy()
			
		# now delete that sucker ####################
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		tmp_str = string.split(con_name, ',')
		query = 'delete from contacts where lname = "%s" and fname = "%s"' % (tmp_str[0].strip(), tmp_str[1].strip())
		cur.execute(query)
		con.commit()
		cur.close()
		con.close()
		ftop.ResetDisplay()
		refreshContacts(self.dbName, ftop)



	def OnRemTodo(self, event):
		ftop = self.parent
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("SELECT subject FROM todo")
		data = cur.fetchall()
		cur.close()
		con.close()
		if data:
			displaylist = []
			todoList = []
			for row in data:
				tmp = [item for item in row]
				max = 40
				if len(str(tmp[0])) < max:
					max = len(str(tmp[0]))
				l = str(tmp[0])
				displaylist.append(l[:max])
				todoList.append(str(tmp[0]))

	        dlg = wx.SingleChoiceDialog(self, 'Choose the To-Do you wish to delete.', 'Remove an To-Do', displaylist, wx.CHOICEDLG_STYLE)
        	if dlg.ShowModal() == wx.ID_OK:
            		todo_index = dlg.GetSelection()
		else:
			dlg.Destroy()
			return
        	dlg.Destroy()
			
		# now delete that sucker ####################
		todo_subject = todoList[todo_index]
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		query = 'delete from todo where subject = "%s"' % todo_subject
		cur.execute(query)
		con.commit()
		cur.close()
		con.close()
		ftop.ResetDisplay()
		refreshTodo(self.dbName, ftop)
		
		
		
	def OnPrint(self, event):
		self.parent.OnPrint()



	def OnDelete(self, event):
		dlg = wx.MessageDialog(self, "This action will delete all old appointments\n that were scheduled prior to today.", "Are you sure?", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
        	if dlg.ShowModal() == wx.ID_OK:
			dlg.Destroy()
        		dbName = self.parent.getDB_Name()
			con = sqlite.connect(dbName)
			cur = con.cursor()
			cur.execute("select name from sqlite_master where type='table' order by name")
			data = cur.fetchall()
			cur.close()
			con.close()
			
			if data:
				tablelist = []
				
				cd = int(time.strftime("%Y%m%d",time.localtime(time.time())))
				
				con = sqlite.connect(dbName)
				cur = con.cursor()
				for row in data:
					tmp = [item for item in row]
					if tmp[0][0] != "a": continue
					ad = int(tmp[0][1:])
					if ad < cd:
						query = "drop table " + tmp[0]
						cur.execute(query)
						con.commit()
				cur.close()
				con.close()
				self.parent.ResetDisplay()
				return
        	dlg.Destroy()



	def OnSunday(self, evt):
		m_id = evt.GetId()
		ct = self.parent.checkOptions(self.dbName)
		tog = self.menu.IsChecked(m_id)
		self.setOptSundayFirst(tog)
		
		
		
	def OnAlerts(self, evt):
		m_id = evt.GetId()
		ct = self.parent.checkAlerts(self.dbName)
		tog = self.menu.IsChecked(m_id)
		self.setAlerts(tog)
		
		
		
	def OnStartup(self, evt):
		regpath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
		valname = "pAgenda"
		#appPath = os.getcwdu() + "\\pAgenda.exe"

		try:
                        reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, regpath, _winreg.KEY_ALL_ACCESS)
                        valName = _winreg.QueryValueEx(reg, valname)
                        if valName:
                            _winreg.DeleteValue(reg, valname)
			_winreg.CloseKey(reg)
		except EnvironmentError:
			try:
                                reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, regpath, 0, _winreg.KEY_WRITE)
				_winreg.SetValueEx(reg, "pAgenda", 0, _winreg.REG_SZ, os.getcwdu() + "\\pAgenda.exe")
				_winreg.CloseKey(reg)
			except:
				print "Unable to set on startup"
				return


		
	def OnHelp(self, evt):
		self.parent.ShowHelp()		
	
	
	
	def setOptSundayFirst(self, mBool):
		ftop = self.parent
		v2 = self.parent.checkAlerts(self.dbName)
		if v2==None:v2='y'
		v3 = self.parent.checkSkip(self.dbName)
		if v3==None:v3='zzz'
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("delete from options where caltype = 'NORMAL' or caltype = 'BUS'")
		con.commit()
		if wx.Platform == "__WXMSW__": mBool = not mBool
		if mBool:
			v1 = 'NORMAL'
		else:
			v1 = 'BUS'
		vals = v1, v2, v3
		query = "insert into options (caltype, alerts, skipalert) values (?, ?, ?)"
		cur.execute(query, vals)
		con.commit()
		cur.execute("select name from sqlite_master where type='table'")
		data = cur.fetchall()
		cur.close()
		con.close()
		ftop.calend.Destroy()
		ftop.makeCalendar(ftop.h)
		ftop.ResetDisplay()
		refreshPage(self.dbName, ftop.curDateTable, ftop)
		
		
		
		
	def setAlerts(self, mBool):
		ftop = self.parent
		v1 = self.parent.checkOptions(self.dbName)
		if v1==None:v1='NORMAL'
		v3 = self.parent.checkSkip(self.dbName)
		if v3==None:v3='zzz'
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("delete from options")
		con.commit()
		if wx.Platform == "__WXMSW__": mBool = not mBool
		if mBool:
			v2 = 'y'
		else:
			v2 = 'n'
		vals = v1, v2, v3
		query = "insert into options (caltype, alerts, skipalert) values (?, ?, ?)"
		cur.execute(query, vals)	
		con.commit()
		cur.execute("select name from sqlite_master where type='table'")
		data = cur.fetchall()
		cur.close()
		con.close()		
		
	
	
	def csvImport(self, newList):
		# used to import entire lists
		########  needs to be passed the import list array as "newList" ############
		########  build contacts list from the current db as "cList"    ############		

		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("SELECT * FROM contacts order by lname")
		data = cur.fetchall()
		cur.close()
		con.close()
		self.cList = []
		if data:
			for row in data:
				tmp = [item for item in row]
				self.cList.append(tmp)	
		i = 0	
		for its in newList:
			if len(its) > 6:
				l = its[0]
				f = its[1]
				self.addItem(l,f,i, newList, self.cList)
				
			i += 1
		refreshContacts(self.dbName, self.parent)

	def addItem(self, l,f, num, newList, oldList):
		if len(oldList):
			ismatch = False
			for i in range(len(oldList)):
				if oldList[i][0] == l and oldList[i][1] == f:
					ismatch = True
					break
			if ismatch:
				dlg = wx.MessageDialog(self, '%s %s\nIs already listed among your contacts.\nDo you want to overwrite your current entry with the imported values?' % (f,l), "Duplicate Entry", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
        			if dlg.ShowModal() == wx.ID_OK:
					dlg.Destroy()
					# delete old entry, then insert new
					con = sqlite.connect(self.dbName)
					cur = con.cursor()
					cur.execute("delete from contacts where lname = ? and fname = ?", (l,f))
					con.commit()
					cur.close()
					con.close()
					self.insert(newList[num])
				else:
					dlg.Destroy()
					return
			else:
				# does not match any current contacts, so go ahead and import
				self.insert(newList[num])

		else:
			# nothing to match against, so just insert value
			self.insert(newList[num])
			

	def insert(self, item):
		con = sqlite.connect(self.dbName)
		cur = con.cursor()
		cur.execute("insert into contacts values (?,?,?,?,?,?,?)", item)
		con.commit()
		cur.close()
		con.close()

#######################################################  ADD APPOINTMENTS  ###################################
#######################################################  ADD APPOINTMENTS  ###################################
		
	class AptFrame(wx.MiniFrame):
		def __init__(self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			self.MakeModal(True)
			self.topframe = parent.parent
			hourList = ["0:","1:","2:","3:","4:","5:","6:","7:","8:","9:","10:","11:","12:"]
			minList = ["00","05","10","15","20","25","30","35","40","45","50","55"]
			lblFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			cbFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			txtFont = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			self.SetBackgroundColour(col1)
			
			topbox = wx.BoxSizer(wx.VERTICAL)
			upperbox = wx.BoxSizer(wx.HORIZONTAL)
			lowerbox = wx.BoxSizer(wx.HORIZONTAL)
			
			self.lTop = wx.StaticText(self, -1, "Enter the appointment time and description.")
			self.lTop.SetFont(lblFont)
			
			l1 = wx.StaticText(self, -1, "Hour  ")
			l1.SetFont(lblFont)
			self.cbHour = wx.ComboBox(self, -1, "9:", choices=hourList, size=(50,-1), style=wx.CB_DROPDOWN | wx.CB_READONLY)
			self.cbHour.SetFont(cbFont)
			l2 = wx.StaticText(self, -1, "Minute  ")
			l2.SetFont(lblFont)
			self.cbMin = wx.ComboBox(self, -1, "00", choices=minList, size=(50,-1), style=wx.CB_DROPDOWN | wx.CB_READONLY)
        		self.cbMin.SetFont(cbFont)
			self.isPM = wx.CheckBox(self, -1, "PM")
			self.isPM.SetFont(lblFont)
			
			self.desc = wx.TextCtrl(self, -1, "", (-1, -1), (420, 100), style=wx.TE_MULTILINE)
			self.desc.SetFont(txtFont)
			
			makeButton = wx.BitmapButton(self, -1, images.getCreateBtnBitmap())
			makeButton.SetToolTip( wx.ToolTip( 'Save the Appointment' ) )
			closeButton = wx.BitmapButton(self, -1, images.getCancelBtnBitmap())
			closeButton.SetToolTip( wx.ToolTip( 'Cancel' ) )
			
        		closeButton.Bind(wx.EVT_BUTTON, self.OnClose, closeButton)
        		makeButton.Bind(wx.EVT_BUTTON, self.OnMake, makeButton)
			
			upperbox.Add(l1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			upperbox.Add(self.cbHour, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			upperbox.Add(l2, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 32)
			upperbox.Add(self.cbMin, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			upperbox.Add(self.isPM, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 32)
			
			lowerbox.Add(closeButton, 0, wx.RIGHT, 20)
			lowerbox.Add(makeButton, 0, wx.LEFT, 20)
			
			topbox.Add(self.lTop, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 24)
			topbox.Add(upperbox, 1, wx.ALIGN_CENTER, 12)
			topbox.Add(self.desc, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 12)
			topbox.Add(lowerbox, 0, wx.ALL | wx.ALIGN_CENTER, 6)
			self.SetSizer(topbox)
			self.Layout()
			self.desc.SetFocus()
			
		def OnClose(self, event):
			self.MakeModal(False)
        		self.Destroy()

		def OnMake(self, event):
			self.MakeModal(False)
			if self.desc.GetValue() == "":
				self.lTop.SetLabel("You must enter appointment information.")
				self.lTop.SetForegroundColour("RED")
				self.Refresh()
				self.desc.SetFocus()
				self.MakeModal(True)
				return
			self.MakeModal(False)
			######################################## get needed variables ##########
        		dbName = self.topframe.getDB_Name()
			tbName = self.topframe.curDateTable
			if self.isPM.IsChecked():
				tp = "pm"
			else:
				tp = "am"
			timeStr = str(self.cbHour.GetValue() + str(self.cbMin.GetValue()) + tp)
			
			
			#### check if time is already taken ##############
			inUse = False
			con = sqlite.connect(dbName)
			cur = con.cursor()
			query = 'pragma table_info(%s)' % tbName
			cur.execute(query)
			ret = cur.fetchall()
			if ret:
				query = 'SELECT * FROM %s' % tbName
				cur.execute(query)
				data = cur.fetchall()
				if data:
					for row in data:
						tempX = [ item for item in row]
						if tempX[0] == timeStr:
							inUse = True
			
			cur.close()
			con.close()
			if inUse:
				MessageDlg(self.topframe, '\n%s  is already scheduled.' % 	timeStr)
				return		
			
			#####################################
			
			td = self.topframe.calend.GetDate()
			tt = string.zfill(td[2], 4) + '/' + string.zfill(td[1], 2) + '/' + string.zfill(td[0], 2) + ',' + timeStr
			t = time.strptime(tt,"%Y/%m/%d,%I:%M%p")
			secTime = str(time.mktime(t))

			txt = self.desc.GetValue()
			
			########################################  Do the DB vodoo ##############			
			con = sqlite.connect(dbName)
			cur = con.cursor()
			query = 'pragma table_info(%s)' % tbName
			cur.execute(query)
			ret = cur.fetchall()
			if not ret:
				query = 'CREATE TABLE %s(apttime str, appt str, abstime str)' % tbName
				cur.execute(query)
				con.commit()
			vals = timeStr, txt, secTime
			query = "insert into " + tbName + " (apttime, appt, abstime) values (?, ?, ?)"
			cur.execute(query, vals)
			con.commit()
			cur.close()
			con.close()
			self.topframe.ResetDisplay()
			refreshPage(dbName, tbName, self.topframe)						
			##########################################  get lost  #######
			self.Destroy()


#######################################################  ADD LIST TODO  ###################################
#######################################################  ADD LIST TODO  ###################################
		
	class todoListFrame(wx.MiniFrame):
		def __init__(self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			self.MakeModal(True)
			self.topframe = parent.parent
			lblFont = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			cbFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			todoFont = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			txtFont = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			self.SetBackgroundColour(col1)
			
			topbox = wx.BoxSizer(wx.VERTICAL)
			lowerbox = wx.BoxSizer(wx.HORIZONTAL)
			
			self.lTop = wx.StaticText(self, -1, "Enter your ToDo.")
			self.lTop.SetFont(lblFont)
			
			self.todo = wx.TextCtrl(self, -1, "", (-1, -1), (420, 26))
			self.todo.SetFont(todoFont)
			
			lbot = wx.StaticText(self, -1, "Enter a description (optional)")
			lbot.SetFont(lblFont)
			
			self.desc = wx.TextCtrl(self, -1, "", (-1, -1), (420, 100), style=wx.TE_MULTILINE)
			self.desc.SetFont(txtFont)
			
			
			makeButton = wx.BitmapButton(self, -1, images.getCreateBtnBitmap())
			makeButton.SetToolTip( wx.ToolTip( 'Save the To-Do' ) )
			closeButton = wx.BitmapButton(self, -1, images.getCancelBtnBitmap())
			closeButton.SetToolTip( wx.ToolTip( 'Cancel' ) )
			
        		closeButton.Bind(wx.EVT_BUTTON, self.OnClose, closeButton)
        		makeButton.Bind(wx.EVT_BUTTON, self.OnMake, makeButton)
			
			lowerbox.Add(closeButton, 0, wx.RIGHT, 20)
			lowerbox.Add(makeButton, 0, wx.LEFT, 20)
			
			topbox.Add(self.lTop, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 24)
			topbox.Add(self.todo, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 12)
			topbox.Add(lbot, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 12)
			topbox.Add(self.desc, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 12)
			topbox.Add(lowerbox, 0, wx.ALL | wx.ALIGN_CENTER, 6)
			self.SetSizer(topbox)
			self.Layout()
			self.todo.SetFocus()
			
		def OnClose(self, event):
			self.MakeModal(False)
        		self.Destroy()

		def OnMake(self, event):
			self.MakeModal(False)
			if self.todo.GetValue() == "":
				self.lTop.SetLabel("You must enter a ToDo")
				self.lTop.SetForegroundColour("RED")
				self.Refresh()
				self.todo.SetFocus()
				self.MakeModal(True)
				return
			self.MakeModal(False)
			######################################## get needed variables ##########
        		dbName = self.topframe.getDB_Name()
			tbName = 'todo'
			#####################################
			subj = self.todo.GetValue()
			txt = self.desc.GetValue()
			########################################  Do the DB vodoo ##############			
			con = sqlite.connect(dbName)
			cur = con.cursor()
			query = 'pragma table_info(%s)' % tbName
			cur.execute(query)
			ret = cur.fetchone()
			if not ret:
				query = 'CREATE TABLE %s(subject str, details str)' % tbName
				cur.execute(query)
				con.commit()
			vals = subj, txt
			query = "insert into " + tbName + " (subject, details) values (?, ?)"
			cur.execute(query, vals)
			con.commit()
			cur.close()
			con.close()
			self.topframe.ResetDisplay()
			refreshTodo(dbName, self.topframe)						
			##########################################  get lost  #######
			self.Destroy()
			
			
#######################################################  ADD TODO  ###################################
#######################################################  ADD TODO  ###################################
		
	class todoFrame(wx.MiniFrame):
		def __init__(self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			self.MakeModal(True)
			self.topframe = parent.parent
			lblFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			cbFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			txtFont = wx.Font(14, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			self.SetBackgroundColour(col1)
			
			topbox = wx.BoxSizer(wx.VERTICAL)
			#upperbox = wx.BoxSizer(wx.HORIZONTAL)
			lowerbox = wx.BoxSizer(wx.HORIZONTAL)
			
			self.lTop = wx.StaticText(self, -1, "Enter your ToDo.")
			self.lTop.SetFont(lblFont)
			
			self.desc = wx.TextCtrl(self, -1, "", (-1, -1), (420, 100), style=wx.TE_MULTILINE)
			self.desc.SetFont(txtFont)
			
			makeButton = wx.BitmapButton(self, -1, images.getCreateBtnBitmap())
			makeButton.SetToolTip( wx.ToolTip( 'Save the Todo Item' ) )
			closeButton = wx.BitmapButton(self, -1, images.getCancelBtnBitmap())
			closeButton.SetToolTip( wx.ToolTip( 'Cancel' ) )
			
        		closeButton.Bind(wx.EVT_BUTTON, self.OnClose, closeButton)
        		makeButton.Bind(wx.EVT_BUTTON, self.OnMake, makeButton)

			lowerbox.Add(closeButton, 0, wx.RIGHT, 20)
			lowerbox.Add(makeButton, 0, wx.LEFT, 20)
			
			topbox.Add(self.lTop, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 24)
			topbox.Add(self.desc, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 12)
			topbox.Add(lowerbox, 0, wx.ALL | wx.ALIGN_CENTER, 6)
			self.SetSizer(topbox)
			self.Layout()
			self.desc.SetFocus()
			
		def OnClose(self, event):
			self.MakeModal(False)
        		self.Destroy()

		def OnMake(self, event):
			self.MakeModal(False)
			if self.desc.GetValue() == "":
				self.lTop.SetLabel("You must enter a ToDo")
				self.lTop.SetForegroundColour("RED")
				self.Refresh()
				self.desc.SetFocus()
				self.MakeModal(True)
				return
			self.MakeModal(False)
			######################################## get needed variables ##########
        		dbName = self.topframe.getDB_Name()
			tbName = self.topframe.curDateTable
			
			#### check todo list ##############
			inUse = False
			con = sqlite.connect(dbName)
			cur = con.cursor()
			query = 'pragma table_info(%s)' % tbName
			cur.execute(query)
			ret = cur.fetchall()
			todoNum = 0
			todoStr = "**ToDo_"
			toSuf = "01"
			if ret:
				query = 'SELECT * FROM %s' % tbName
				cur.execute(query)
				data = cur.fetchall()
				if data:
					for row in data:
						tempX = [ item for item in row]
						if tempX[0][:2] == "**":
							tmpNum = int(tempX[0][-2:]) + 1
							if tmpNum > 98:
								MessageDlg(self.topframe, '\n Sorry, too much to do.')
								return	
							toSuf = string.zfill(str(tmpNum), 2)
			todoStr = todoStr + toSuf	
			cur.close()
			con.close()
			#####################################

			txt = self.desc.GetValue()
			
			########################################  Do the DB vodoo ##############			
			con = sqlite.connect(dbName)
			cur = con.cursor()
			query = 'pragma table_info(%s)' % tbName
			cur.execute(query)
			ret = cur.fetchall()
			if not ret:
				query = 'CREATE TABLE %s(apttime str, appt str, abstime str)' % tbName
				cur.execute(query)
				con.commit()
			vals = todoStr, txt, string.zfill(str(toSuf), 2)
			query = "insert into " + tbName + " (apttime, appt, abstime) values (?, ?, ?)"
			cur.execute(query, vals)
			con.commit()
			cur.close()
			con.close()
			self.topframe.ResetDisplay()
			refreshPage(dbName, tbName, self.topframe)						
			##########################################  get lost  #######
			self.Destroy()
			
						
#######################################################  ADD CONTACTS  ###################################
#######################################################  ADD CONTACTS  ###################################

	class ContactFrame(wx.MiniFrame):
		def __init__(self, parent, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			self.MakeModal(True)
			self.topframe = parent.parent
			self.dbName = self.topframe.getDB_Name()
			
			hourList = ["0:","1:","2:","3:","4:","5:","6:","7:","8:","9:","10:","11:","12:"]
			minList = ["00","05","10","15","20","25","30","35","40","45","50","55"]
			lblFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.BOLD, False)
			txtFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			self.SetBackgroundColour(col1)
			
			topbox = wx.BoxSizer(wx.VERTICAL)
			lnamebox = wx.BoxSizer(wx.HORIZONTAL)
			fnamebox = wx.BoxSizer(wx.HORIZONTAL)
			add1box = wx.BoxSizer(wx.HORIZONTAL)
			add2box = wx.BoxSizer(wx.HORIZONTAL)
			telebox = wx.BoxSizer(wx.HORIZONTAL)
			embox = wx.BoxSizer(wx.HORIZONTAL)
			combox = wx.BoxSizer(wx.HORIZONTAL)
			lowerbox = wx.BoxSizer(wx.HORIZONTAL)
			##################################################################
			self.lTop = wx.StaticText(self, -1, "Enter a contact\'s name and relevant data.", style=wx.ALIGN_CENTRE)
			self.lTop.SetFont(lblFont)
			
			l1 = wx.StaticText(self, -1, "*Last Name", (-1, -1), (100, 24))
			l1.SetFont(lblFont)
			self.l_name = wx.TextCtrl(self, -1, "", (-1, -1), (180, 24), style=wx.TE_PROCESS_TAB)
			self.l_name.SetFont(txtFont)
			self.l_name.Bind(wx.EVT_CHAR, self.lname_next, self.l_name)
			
			l2 = wx.StaticText(self, -1, "*First Name", (-1, -1), (100, 24))
			l2.SetFont(lblFont)
			self.f_name = wx.TextCtrl(self, -1, "", (-1, -1), (180, 24), style=wx.TE_PROCESS_TAB)
        		self.f_name.SetFont(txtFont)
			self.f_name.Bind(wx.EVT_TEXT_ENTER, self.lname_next, self.f_name)
			self.f_name.Bind(wx.EVT_CHAR, self.fname_next, self.f_name)
			###################################################################
			l3 = wx.StaticText(self, -1, "Address1", (-1, -1), (100, 24))
			l3.SetFont(lblFont)
			self.add_1 = wx.TextCtrl(self, -1, "", (-1, -1), (240, 24), style=wx.TE_PROCESS_TAB)
			self.add_1.SetFont(txtFont)
			self.add_1.Bind(wx.EVT_TEXT_ENTER, self.add1_next, self.add_1)
			self.add_1.Bind(wx.EVT_CHAR, self.add1_next, self.add_1)
			
			l4 = wx.StaticText(self, -1, "Address2", (-1, -1), (100, 24))
			l4.SetFont(lblFont)
			self.add_2 = wx.TextCtrl(self, -1, "", (-1, -1), (240, 24), style=wx.TE_PROCESS_TAB)
			self.add_2.SetFont(txtFont)
			self.add_2.Bind(wx.EVT_TEXT_ENTER, self.add2_next, self.add_2)
			self.add_2.Bind(wx.EVT_CHAR, self.add2_next, self.add_2)
			
			l5 = wx.StaticText(self, -1, "Telephone", (-1, -1), (100, 24))
			l5.SetFont(lblFont)
			self.d_tele = wx.TextCtrl(self, -1, "", (-1, -1), (140, 24), style=wx.TE_PROCESS_TAB)
			self.d_tele.SetFont(txtFont)
			self.d_tele.Bind(wx.EVT_TEXT_ENTER, self.tele_next, self.d_tele)
			self.d_tele.Bind(wx.EVT_CHAR, self.tele_next, self.d_tele)
			
			l6 = wx.StaticText(self, -1, "Email", (-1, -1), (100, 24))
			l6.SetFont(lblFont)
			self.d_email = wx.TextCtrl(self, -1, "", (-1, -1), (240, 24), style=wx.TE_PROCESS_TAB)
			self.d_email.SetFont(txtFont)
			self.d_email.Bind(wx.EVT_TEXT_ENTER, self.email_next, self.d_email)
			self.d_email.Bind(wx.EVT_CHAR, self.email_next, self.d_email)
			
			l7 = wx.StaticText(self, -1, "Description", (-1, -1), (100, 24))
			l7.SetFont(lblFont)
			self.d_comment = wx.TextCtrl(self, -1, "", (-1, -1), (240, 70), style=wx.TE_PROCESS_TAB | wx.TE_MULTILINE)
			self.d_comment.SetFont(txtFont)
			self.d_comment.Bind(wx.EVT_TEXT_ENTER, self.com_next, self.d_comment)
			self.d_comment.Bind(wx.EVT_CHAR, self.com_next, self.d_comment)
			
			####################################################################
			
			self.makeButton = wx.BitmapButton(self, -1, images.getCreateBtnBitmap())
			self.makeButton.SetToolTip( wx.ToolTip( 'Save' ) )
			closeButton = wx.BitmapButton(self, -1, images.getCancelBtnBitmap())
			closeButton.SetToolTip( wx.ToolTip( 'Cancel' ) )

        		closeButton.Bind(wx.EVT_BUTTON, self.OnClose, closeButton)
        		self.makeButton.Bind(wx.EVT_BUTTON, self.OnMake, self.makeButton)
			
			
			lnamebox.Add(l1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
			lnamebox.Add(self.l_name, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			fnamebox.Add(l2, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 4)
			fnamebox.Add(self.f_name, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			
			
			add1box.Add(l3, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 2)
			add1box.Add(self.add_1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			add2box.Add(l4, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 4)
			add2box.Add(self.add_2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			telebox.Add(l5, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 4)
			telebox.Add(self.d_tele, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			embox.Add(l6, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 4)
			embox.Add(self.d_email, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)
			
			combox.Add(l7, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 4)
			combox.Add(self.d_comment, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 4)			
	
			lowerbox.Add(closeButton, 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 30)
			lowerbox.Add(self.makeButton, 0, wx.LEFT | wx.ALIGN_CENTER_VERTICAL, 30)
			
			topbox.Add(self.lTop, 0, wx.TOP | wx.BOTTOM | wx.ALIGN_CENTER, 16)
			topbox.Add(lnamebox, 0, wx.LEFT, 20)
			topbox.Add(fnamebox, 0, wx.LEFT, 20)
			topbox.Add(add1box, 0, wx.LEFT, 20)
			topbox.Add(add2box, 0, wx.LEFT, 20)
			topbox.Add(telebox, 0, wx.LEFT, 20)
			topbox.Add(embox, 0, wx.LEFT, 20)
			topbox.Add(combox, 0, wx.LEFT, 20)
				
			topbox.Add(lowerbox, 1, wx.ALL | wx.ALIGN_CENTER, 0)
			self.SetSizer(topbox)
			self.Layout()
			self.l_name.SetFocus()
			
		def lname_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.f_name.SetFocus()
			else:
				event.Skip()

		def fname_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.add_1.SetFocus()
			else:
				event.Skip()
			
		def add1_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.add_2.SetFocus()
			else:
				event.Skip()
			
		def add2_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.d_tele.SetFocus()
			else:
				event.Skip()
			
		def tele_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.d_email.SetFocus()
			else:
				event.Skip()
			
		def email_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 13 or wx.KeyEvent.GetKeyCode(event) == 9:
				self.d_comment.SetFocus()
			else:
				event.Skip()
			
		def com_next(self, event):
			if wx.KeyEvent.GetKeyCode(event) == 9:
				self.makeButton.SetFocus()
			else:
				event.Skip()
		
		def OnClose(self, event):
			self.MakeModal(False)
        		self.Destroy()

		def getCurContacts(self, db):
			conlist = []
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("SELECT * FROM contacts order by lname")
			data = cur.fetchall()
			cur.close()
			con.close()
			if data:
				for row in data:
					tmp2 = [item for item in row]
					conlist.append(tmp2)
			return conlist
		    
		
		def OnMake(self, event):
			self.MakeModal(False)
			if self.l_name.GetValue() == "":
				self.lTop.SetLabel("You must enter a last name.")
				self.lTop.SetForegroundColour("RED")
				self.Refresh()
				self.l_name.SetFocus()
				self.MakeModal(True)
				return
			if self.f_name.GetValue() == "":
				self.lTop.SetLabel("You must enter a first name.")
				self.lTop.SetForegroundColour("RED")
				self.Refresh()
				self.f_name.SetFocus()
				self.MakeModal(True)
				return
			self.MakeModal(False)

			cl = self.getCurContacts(self.dbName)
			if len(cl):
				l = self.l_name.GetValue().strip()
				f = self.f_name.GetValue().strip()
				
				for cont in cl:
					if cont[0] == l and cont[1] == f:
                                                #print "old checked: " + cont[0]
						dlg = wx.MessageDialog(self, '%s %s\nis already on your contact list.\nDo you want to overwrite your current entry with the new values?' % (l, f), "Duplicate entry", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
        					if dlg.ShowModal() == wx.ID_OK:
							dlg.Destroy()
							# delete old entry
							con = sqlite.connect(self.dbName)
							cur = con.cursor()
							cur.execute("delete from contacts where lname = ? and fname = ?", (l, f))
							con.commit()
							cur.close()
							con.close()
						else:
							return

			########################################  Do the DB vodoo ##############			
			con = sqlite.connect(self.dbName)
			cur = con.cursor()
			cur.execute('pragma table_info("contacts")')
			ret = cur.fetchall()
			if not ret:
				cur.execute("CREATE TABLE contacts(lname str, fname str, address1 str, address2 str, telephone str, email str, comment str)")
				con.commit()

			vals = self.l_name.GetValue().strip(),self.f_name.GetValue().strip(),self.add_1.GetValue(),self.add_2.GetValue(),self.d_tele.GetValue(),self.d_email.GetValue(),self.d_comment.GetValue()
			query = "insert into contacts values (?, ?, ?, ?, ?, ?, ?)"
			cur.execute(query, vals)
			con.commit()
			cur.close()
			con.close()
			self.topframe.ResetDisplay()
			refreshContacts(self.dbName, self.topframe)						
			##########################################  get lost  #######
			self.Destroy()

#######################################################  IMPORT APPOINTMENTS  #######################
#######################################################  IMPORT APPOINTMENTS  #######################
						
	class ImportAptFrame(wx.MiniFrame):
		def __init__(self, parent, title, db, curDB, pos=wx.DefaultPosition, size=(420, 400), style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			
			self.topframe = parent.parent
			self.db = db
			self.curDB = curDB
			self.newList = []
			self.selectedDate = ""
			self.oldApts = []
			
			########  build appointment table list from the chosen db  ############
			
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("select name from sqlite_master where type='table' order by name")
			data = cur.fetchall()
			cur.close()
			con.close()
			
			self.displaylist = []
			if data:
				for tb in data:
					tmp = str(tb[0])[1:]
					if str(tb[0])[0] == "a":
						tmp = str(tb[0])[1:]
						self.displaylist.append(tmp[:4] + "-" + tmp[4:-2] + "-" + tmp[6:])

			if not len(self.displaylist):
				dlg = wx.MessageDialog(self, '\n%s \n\ndoes not appear to contain any appointments.' % db, "No Appointments Listed", wx.OK | wx.ICON_INFORMATION )
        			dlg.ShowModal()
				dlg.Destroy()
				self.Destroy()
				
			

			# Now create the Panel to put the other controls on.
			self.SetBackgroundColour("#4B6983")
			panel = wx.Panel(self)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			panel.SetBackgroundColour(col1)
			
			self.cbDates = wx.ComboBox(panel, -1, "", (-1, -1), (120, -1), self.displaylist, wx.CB_DROPDOWN|wx.CB_READONLY)
			self.cbDates.SetSelection(0)
			self.cbDates.Bind(wx.EVT_COMBOBOX, self.OnCbDate, self.cbDates)
			

			# Setup GUI
			text = wx.StaticText(panel, -1, "Select\na Date")
			text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
			text.SetSize(text.GetBestSize())
			
			dbStr = "Import from " + os.path.basename(db)[1:-3]
			txtDB = wx.StaticText(panel, -1, dbStr, style=wx.ALIGN_CENTRE)
			txtDB.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
			txtDB.SetForegroundColour("#4B6983")
			
			txt2 = wx.StaticText(panel, -1, "...from the dropdown box. After a date is selected, the appointments will appear.", size=(150, 60))
			self.btnSel = wx.Button(panel, -1, "Select all")
			self.btnSel.Enable(False)
			btnCancel = wx.Button(panel, -1, "Cancel")
			self.btnImp = wx.Button(panel, -1, "Import")
			self.btnImp.Enable(False)

			# bind the button events to handlers
			self.Bind(wx.EVT_BUTTON, self.OnSelBtn, self.btnSel)
			self.Bind(wx.EVT_BUTTON, self.OnCloseBtn, btnCancel)
			self.Bind(wx.EVT_BUTTON, self.OnImpBtn, self.btnImp)

			self.lb1 = wx.ListBox(panel, -1, (-1, -1), (190, 200), [], wx.LB_MULTIPLE)

			sizer = wx.BoxSizer(wx.HORIZONTAL)
			sizerL = wx.BoxSizer(wx.VERTICAL)
			sizerR = wx.BoxSizer(wx.VERTICAL)
			
			sizerL.Add(txtDB, 0, wx.ALL | wx.ALIGN_CENTER, 10)
			sizerL.Add(self.cbDates, 0, wx.ALL | wx.ALIGN_RIGHT, 10)
			sizerL.Add(self.lb1, 0, wx.ALL, 10)
			
			sizerR.Add(text, 0, wx.ALL, 10)
			sizerR.Add(txt2, 0, wx.ALL, 10)
			sizerR.Add(self.btnSel, 0, wx.ALL, 10)
			sizerR.Add((80,30), 0)
			sizerR.Add(btnCancel, 0, wx.ALL, 10)
			sizerR.Add(self.btnImp, 0, wx.ALL, 10)
			
			sizer.Add(sizerL, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 12)
			sizer.Add(sizerR, 0,wx.ALL | wx.ALIGN_CENTER_VERTICAL, 10)
			panel.SetSizer(sizer)
			panel.Layout()
		
		
		def OnCbDate(self, evt):
			self.lb1.Clear()
        		mDate = self.cbDates.GetValue()
			self.selectedDate = "a" + mDate.replace("-", "")
			con = sqlite.connect(self.db)
			cur = con.cursor()

			query = 'SELECT * FROM %s order by abstime' % self.selectedDate
			cur.execute(query)
			data = cur.fetchall()
			cur.close()
			con.close()
			
			self.btnSel.Enable(len(data))
			self.btnImp.Enable(len(data))
			
			if not data:
				dlg = wx.MessageDialog(self, 'The selected date does not appear to contain ant appointments.', "No Appointments Listed", wx.OK | wx.ICON_INFORMATION )
        			dlg.ShowModal()
				dlg.Destroy()
				return
			else:
				txt = []
				for row in data:
					tempX = [ item for item in row]
					if len(tempX[1]) > 24:
						tapt = str(tempX[1])[:24]
					else:
						tapt = str(tempX[1])
					tapt = str(tempX[0]) + "    " + tapt
					txt.append(tapt)
					self.newList.append(tempX)
			
			self.lb1.InsertItems(txt,0)
			
		def OnSelBtn(self, event):
			for i in range(len(self.displaylist)):
				self.lb1.SetSelection(i)

		def OnCloseBtn(self, evt):
        		self.Close()


		def OnImpBtn(self, evt):
        		nums = self.lb1.GetSelections()
			if not nums:
				dlg = wx.MessageDialog(self, "You need to select something to import.", "No Selections", wx.OK | wx.ICON_INFORMATION )
        			dlg.ShowModal()
				dlg.Destroy()
				return
			for i in nums:
				# get current appointment times for specific dates
				self.oldApts = []
				con = sqlite.connect(self.curDB)
				cur = con.cursor()
				query = 'SELECT * FROM %s order by abstime' % self.selectedDate
				cur.execute(query)
				data = cur.fetchall()
				cur.close()
				con.close()
				if data:
					for row in data:
						tempX = [ item for item in row]
						self.oldApts.append(tempX)
				m = self.lb1.GetString(i)
				l = string.split(m, " ")
				self.addItem(l,i)
				
			refreshPage(self.curDB, self.topframe.curDateTable, self.topframe)
			self.Close()
			
			
		def addItem(self, at, num):
			c = self.selectedDate
			newT = str(at[0])
			if len(self.oldApts):
				ismatch = False
				for i in range(len(self.oldApts)):
					if self.oldApts[i][0] == newT:
						ismatch = True
						break
				if ismatch:
					dlg = wx.MessageDialog(self, '\n%s \n\nalready has a scheduled apointment.\nDo you want to overwrite your current entry with the imported values?' % newT, "Duplicate time", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
        				if dlg.ShowModal() == wx.ID_OK:
						tt = string.zfill(c[1:-4],4) + '/' + string.zfill(c[5:-2],2) + '/' + string.zfill(c[7:],2) + ',' + newT
						t = time.strptime(tt,"%Y/%m/%d,%I:%M%p")
						secTime = str(int(time.mktime(t)))
						dlg.Destroy()
						# delete old entry, then send to insert
						con = sqlite.connect(self.curDB)
						cur = con.cursor()
						query = 'delete from ' + c + ' where abstime = ' + secTime
						cur.execute(query)
						con.commit()
						cur.close()
						con.close()
						self.insert(c, self.newList[num])
					else:
						dlg.Destroy()
				else:
					# does not match any current contacts, so go ahead and import
					self.insert(c, self.newList[num])

			else:
				# nothing to match against, so just insert value
				self.insert(c, self.newList[num])	
			
		def insert(self, c, item):
			t1 = str(item[0])
			t2 = str(item[1])
			t3 = str(item[2])
			vals = t1, t2, t3
			con = sqlite.connect(self.curDB)
			cur = con.cursor()
			query = "insert into " + c + " (apttime, appt, abstime) values (?, ?, ?)"
			cur.execute(query, vals)
			con.commit()
			cur.close()
			con.close()
			
#######################################################  IMPORT CONTACTS  #######################
#######################################################  IMPORT CONTACTS  #######################

	class ImportConFrame(wx.MiniFrame):
		def __init__(self, parent, title, db, curDB, pos=wx.DefaultPosition, size=(440, 400), style=wx.DEFAULT_FRAME_STYLE):
		
        		wx.MiniFrame.__init__(self, parent, -1, title, pos, size, style)
			
			self.topframe = parent.parent
			self.db = db
			self.curDB = curDB
			
			########  build contacts list from the chosen db  ############
			
			con = sqlite.connect(db)
			cur = con.cursor()
			cur.execute("pragma table_info(contacts)")
			ret = cur.fetchall()
			if not ret:
				dlg = wx.MessageDialog(self.topframe, '\n%s \n\ndoes not appear to contain a contacts list.' % db, "No Contacts List", wx.OK | wx.ICON_ERROR )
        			dlg.ShowModal()
				dlg.Destroy()
				cur.close()
				con.close()
				self.Close()
			cur.execute("SELECT * FROM contacts order by lname")
			data = cur.fetchall()
			cur.close()
			con.close()
			
			self.displaylist = []
			self.newList = []
			if data:
				for row in data:
					tmp = [item for item in row]
					self.displaylist.append(str(tmp[0]) + ', ' + str(tmp[1]))
					self.newList.append(tmp)
			else:
				dlg = wx.MessageDialog(self.topframe, '\n%s \n\ndoes not appear to contain any contacts.' % db, "No Contacts Listed", wx.OK | wx.ICON_ERROR )
        			dlg.ShowModal()
				dlg.Destroy()
				self.Destroy()
				
			########  build contacts list from the current db  ############		
								
			con = sqlite.connect(curDB)
			cur = con.cursor()
			cur.execute("SELECT * FROM contacts order by lname")
			data = cur.fetchall()
			cur.close()
			con.close()
			self.cList = []
			if data:
				for row in data:
					tmp2 = [item for item in row]
					self.cList.append(tmp2)
			

			# Now create the Panel to put the other controls on.
			self.SetBackgroundColour("#4B6983")
			panel = wx.Panel(self)
			col1 = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)
			panel.SetBackgroundColour(col1)

			# Setup GUI
			text = wx.StaticText(panel, -1, "Select\nContact(s)")
			text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD))
			text.SetSize(text.GetBestSize())
			
			dbStr = "Import from " + os.path.basename(db)[1:-3]
			txtDB = wx.StaticText(panel, -1, dbStr, style=wx.ALIGN_CENTRE)
			txtDB.SetFont(wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD))
			txtDB.SetForegroundColour("#4B6983")
			
			txt2 = wx.StaticText(panel, -1, "Hold down the control key\nto add multiple entries. Or use the \"Select All\" checkbox to import all.", size=(130, 60))
			self.btnSel = wx.Button(panel, -1, "Select all")
			btnCancel = wx.Button(panel, -1, "Cancel")
			btnImp = wx.Button(panel, -1, "Import")

			# bind the button events to handlers
			self.Bind(wx.EVT_BUTTON, self.OnSelBtn, self.btnSel)
			self.Bind(wx.EVT_BUTTON, self.OnCloseBtn, btnCancel)
			self.Bind(wx.EVT_BUTTON, self.OnImpBtn, btnImp)

			self.lb1 = wx.ListBox(panel, -1, (-1, -1), (200, 300), self.displaylist, wx.LB_MULTIPLE)
			if len(self.displaylist): self.lb1.SetSelection(0)
			
			sizer = wx.BoxSizer(wx.HORIZONTAL)
			sizerL = wx.BoxSizer(wx.VERTICAL)
			sizerR = wx.BoxSizer(wx.VERTICAL)
			
			sizerL.Add(txtDB, 0, wx.ALL | wx.ALIGN_CENTER, 10)
			sizerL.Add(self.lb1, 0, wx.ALL, 10)
			
			sizerR.Add(text, 0, wx.ALL, 10)
			sizerR.Add(txt2, 0, wx.ALL, 10)
			sizerR.Add(self.btnSel, 0, wx.ALL, 10)
			sizerR.Add((80,30), 0)
			sizerR.Add(btnCancel, 0, wx.ALL, 10)
			sizerR.Add(btnImp, 0, wx.ALL, 10)
			
			sizer.Add(sizerL, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 12)
			sizer.Add(sizerR, 0,wx.ALL | wx.ALIGN_CENTER_VERTICAL, 10)
			panel.SetSizer(sizer)
			panel.Layout()
		
		def OnSelBtn(self, event):
			for i in range(len(self.displaylist)):
				self.lb1.SetSelection(i)

		def OnCloseBtn(self, evt):
        		self.Close()

		def OnImpBtn(self, evt):
        		nums = self.lb1.GetSelections()
			if not nums:
				dlg = wx.MessageDialog(self, "You need to select something to import.", "No Selections", wx.OK | wx.ICON_INFORMATION )
        			dlg.ShowModal()
				dlg.Destroy()
				return
			for i in nums:
				l = self.newList[i][0]
				f = self.newList[i][1]
				self.addItem(l,f,i)
			refreshContacts(self.curDB, self.topframe)
			self.Close()
				
		def addItem(self, l,f, num):
			if len(self.cList):
				ismatch = False
				for i in range(len(self.cList)):
					if self.cList[i][0] == l and self.cList[i][1] == f:
						ismatch = True
						break
				if ismatch:
					dlg = wx.MessageDialog(self, '%s %s\nIs already listed among your contacts.\nDo you want to overwrite your current entry with the imported values?' % (f,l), "Duplicate Entry", wx.OK | wx.CANCEL | wx.ICON_QUESTION)
        				if dlg.ShowModal() == wx.ID_OK:
						dlg.Destroy()
						# delete old entry, then insert new
						con = sqlite.connect(self.curDB)
						cur = con.cursor()
						cur.execute("delete from contacts where lname = ? and fname = ?", (l,f))
						con.commit()
						cur.close()
						con.close()
						self.insert(self.newList[num])
					else:
						dlg.Destroy()
				else:
					# does not match any current contacts, so go ahead and import
					self.insert(self.newList[num])

			else:
				# nothing to match against, so just insert value
				self.insert(self.newList[num])
				
		def insert(self, item):
			con = sqlite.connect(self.curDB)
			cur = con.cursor()
			cur.execute("insert into contacts values (?,?,?,?,?,?,?)", item)
			con.commit()
			cur.close()
			con.close()
			
################################################################### START CLOCK #####################		
################################################################### START CLOCK #####################

class AnalogClockWindow(wx.PyWindow):
    """An analog clock window"""
    def __init__(self, parent, ID=-1, pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=0, name="clock"):
        
        # Initialize the wxWindow...
        wx.PyWindow.__init__(self, parent, ID, pos, size, style, name)
        # Initialize some variables and defaults...
	self.parent = parent
        self.clockStep = 1
        self.prefs_open = False
        self.tickShapeHours = self.tickShapeMinutes= [[0,0],
                                                      [1,-1],
                                                      [2,0],
                                                      [1,4]]
        self.handHoursThickness = 5
        self.handHoursColour = (0, 0, 0)
        self.handMinutesThickness = 3
        self.handMinutesColour = (0, 0, 0)
        self.handSecondsThickness = 1
        self.handSecondsColour = (0, 0, 0)
        self.tickMarkHoursPen = wx.Pen((0, 0, 0), 1, wx.SOLID)
        self.tickMarkHoursBrush = wx.Brush((0, 0, 0), wx.SOLID)
        self.markSizeHour = 10
        self.tickMarkHoursFont = wx.Font(1, wx.SWISS, wx.NORMAL, wx.BOLD)
        self.tickMarkHoursFont.SetPointSize(self.markSizeHour)
        self.tickMarkMinutesPen = wx.Pen((0, 0, 0), 1, wx.SOLID)
        self.tickMarkMinutesBrush = wx.Brush((0, 0, 0), wx.SOLID)
        self.markSizeMin = 6
        self.tickMarkMinutesFont = wx.Font(self.markSizeMin, wx.SWISS, wx.NORMAL, wx.BOLD)
        self.offM = 0
        self.shadowPenColour = self.shadowBrushColour = (128,128,128)
        self.watchPen = None
        self.watchBrush = None
        self.clockStyle = SHOW_HOURS_TICKS | SHOW_MINUTES_TICKS | SHOW_SHADOWS | ROTATE_TICKS
        self.handsStyle = SHOW_SECONDS_HAND
        self.tickMarkHoursStyle = TICKS_POLY
        self.tickMarkMinutesStyle = TICKS_CIRCLE
        self.currentTime=None
        size = wx.Size(*size)
        bestSize = self.GetBestSize()
        size.x = max(size.x, bestSize.x)
        size.y = max(size.y, bestSize.y)
        self.SetSize(size)
        # Make an initial bitmap for the face, it will be updated and
        # painted at the first EVT_SIZE event.
        W, H = size
        self.faceBitmap = wx.EmptyBitmap(max(W,1), max(H,1))
        # Set event handlers...
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: None)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_TIMER, self.OnTimerExpire)
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnQuit)
        self.timer = wx.Timer(self)
        self.timer.Start(1000)

    def DoGetBestSize(self):
        return wx.Size(25,25)

    def OnPaint(self, event):
        dc = wx.BufferedPaintDC(self)
        if hasattr(self, 'coords'):
            self._doDrawHands(dc, True)

    def OnTimerExpire(self, event):
        size = self.GetClientSize()
        dc = wx.BufferedDC(wx.ClientDC(self), size)
        self._doDrawHands(dc, True)

    def OnQuit(self, event):
        self.timer.Stop()
        del self.timer

    def OnSize(self, event):
        # The faceBitmap init is done here, to make sure the buffer is always
        # the same size as the Window
        size  = self.GetClientSize()
        if size.x < 1 or size.y < 1:
            return
        self.faceBitmap = wx.EmptyBitmap(size.width, size.height)
        # Update drawing coordinates...
        new_dim = size.Get()
        if not hasattr(self,"dim"):
            self.dim = new_dim
        x,y=[0,1]
        self.scale = min([float(new_dim[x]) / self.dim[x],
                          float(new_dim[y]) / self.dim[y]])
        self.centerX = self.faceBitmap.GetWidth() / 2
        self.centerY = self.faceBitmap.GetHeight() / 2
        self.shadowDistance = 2 * self.scale
        self.radius_watch = min(self.centerX, self.centerY)
        self._doDrawFace()
        
    def _doDrawHands(self, drawDC, force=0):
        currentTime = list(time.localtime(time.time())[3:6])

        if not (self.handsStyle & SHOW_SECONDS_HAND):
            currentTime[2]=-1

        if not (force or currentTime != self.currentTime):
            return
        self.currentTime = currentTime
        hour, minutes, seconds = currentTime
        # Start by drawing the face bitmap
        drawDC.DrawBitmap(self.faceBitmap, 0,0)
        # Draw hours hand shadow
        mStep = 6 * self.clockStep
        angle = hour * 30
        if angle > 360:
            angle = angle - 360
        angle = angle + round(minutes/(mStep*2)) * mStep
        x,y,f = self._getCoords("hand_hours", angle)

        if f and self.clockStyle & SHOW_SHADOWS:
            drawDC.SetPen(wx.Pen(self.shadowPenColour,
                                 int(self.handHoursThickness * self.scale),
                                 wx.SOLID))
            drawDC.DrawLine(self.centerX + self.shadowDistance,
                            self.centerY + self.shadowDistance,
                            x + self.shadowDistance,
                            y + self.shadowDistance)
        # Draw minutes hand shadow
        angle = minutes * 6
        x,y,f = self._getCoords("hand_minutes", angle)

        if f and self.clockStyle & SHOW_SHADOWS:
            drawDC.SetPen(wx.Pen(self.shadowPenColour,
                                 int(self.handMinutesThickness * self.scale),
                                 wx.SOLID))
            drawDC.DrawLine(self.centerX + self.shadowDistance,
                            self.centerY + self.shadowDistance,
                            x + self.shadowDistance,
                            y + self.shadowDistance)
        # Draw seconds hand shadow if required
        if seconds >= 0:
            angle = seconds * 6
            x,y,f = self._getCoords("hand_seconds", angle)
            
            if f and self.clockStyle & SHOW_SHADOWS:
                drawDC.SetPen(wx.Pen(self.shadowPenColour,
                                     int(self.handSecondsThickness * self.scale),
                                     wx.SOLID))
                drawDC.DrawLine(self.centerX + self.shadowDistance,
                                self.centerY + self.shadowDistance,
                                x + self.shadowDistance,
                                y + self.shadowDistance)
        # Draw hours hand
        angle = hour * 30
        if angle > 360:
            angle = angle - 360
        angle = angle + round(minutes/(mStep*2)) * mStep
        x,y,f = self._getCoords("hand_hours", angle)

        if f:
            drawDC.SetPen(wx.Pen(self.handHoursColour,
                                 int(self.handHoursThickness * self.scale),
                                 wx.SOLID))
            drawDC.DrawLine(self.centerX, self.centerY, x, y)
        # Draw minutes hand
        angle = minutes * 6
        x,y,f = self._getCoords("hand_minutes", angle)

        if f:
            drawDC.SetPen(wx.Pen(self.handMinutesColour,
                                 int(self.handMinutesThickness * self.scale),
                                 wx.SOLID))
            drawDC.DrawLine(self.centerX, self.centerY, x, y)
        # Draw seconds hand if required
        if seconds >= 0:
            angle = seconds * 6
            x,y,f = self._getCoords("hand_seconds", angle)
            if f:
                drawDC.SetPen(wx.Pen(self.handSecondsColour,
                                     int(self.handSecondsThickness * self.scale),
                                     wx.SOLID))
                drawDC.DrawLine(self.centerX, self.centerY, x, y)
		
		
	if minutes == 0 and seconds == 0:
	# "seconds only" used in testing
	#if seconds == 0:
		self.parent.hourly_callback()

		
		

    def _doDrawFace(self):
        backgroundBrush = wx.Brush(self.GetBackgroundColour(), wx.SOLID)
        drawDC = wx.MemoryDC()
        drawDC.SelectObject(self.faceBitmap)
        drawDC.SetBackground(backgroundBrush)
        drawDC.Clear()
        self.handHoursLength = 0.65 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
        self.handMinutesLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
        self.handSecondsLength = 0.85 * (self.radius_watch - self._getMarkMaxSize("ticks_hours", drawDC))
        self.radius_ticks_hours = self.radius_watch - self.shadowDistance - self._getMarkMaxSize("ticks_hours", drawDC)
        self.radius_ticks_minutes = self.radius_ticks_hours
        self._calcSteps()
        # Draw the watch...
        self._drawWatch(drawDC)
        # Draw the marks for hours and minutes...
        circle = 360
        mStep = 6 * self.clockStep
        if self.clockStyle & SHOW_SHADOWS:
            for i in range(0, circle, mStep):
                for t in self.coords.keys():
                    if t.find("ticks") > -1:
                        x,y,f = self._getCoords(t, i)
                        if f:
                            self._doDrawTickMark(i, drawDC, t,
                                                 x + self.shadowDistance,
                                                 y + self.shadowDistance,
                                                 True)
        for i in range(0, circle, mStep):
            for t in self.coords.keys():
                if t.find("ticks") > -1:
                    x,y,f = self._getCoords(t, i)
                    if f:
                        self._doDrawTickMark(i, drawDC, t, x, y)


    def _doDrawTickMark(self, angle, drawDC, tipo, x, y, is_a_shadow=None):
        opts = {"ticks_hours":    [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle],
                "ticks_quarters": [self.tickMarkHoursPen, self.tickMarkHoursBrush, self.markSizeHour, self.tickMarkHoursStyle],
                "ticks_minutes":  [self.tickMarkMinutesPen, self.tickMarkMinutesBrush, self.markSizeMin, self.tickMarkMinutesStyle]}
        pen, brush, size, style = opts[tipo];
        size = size * self.scale
        if is_a_shadow:
            drawDC.SetPen(wx.Pen(self.shadowPenColour, 1, wx.SOLID))
            drawDC.SetBrush(wx.Brush(self.shadowBrushColour, wx.SOLID))
            drawDC.SetTextForeground(self.shadowBrushColour)
        else:
            drawDC.SetPen(pen)
            drawDC.SetBrush(brush)
            drawDC.SetTextForeground(brush.GetColour())

        if style & TICKS_CIRCLE:
            x, y = self._center2corner(x, y, tipo)
            drawDC.DrawEllipse(x, y, size, size)

        elif style & TICKS_SQUARE:
            x, y = self._center2corner(x, y, tipo)
            drawDC.DrawRectangle(x, y, size, size)

        elif (style & TICKS_DECIMAL) or (style & TICKS_ROMAN):
            self._draw_rotate_text(drawDC, x, y, tipo, angle)

        elif style & TICKS_POLY:
             self._draw_rotate_polygon(drawDC, x, y, tipo, angle)


    def _draw_rotate_text(self, drawDC, x, y, tipo, angle):
        text = self._build_text(angle, tipo)
        lX, lY = self._center2corner(x, y, tipo, drawDC)
        lX = lX * len(text)
        angle = 360 - angle
        if self.clockStyle & ROTATE_TICKS:
            radiansPerDegree = math.pi / 180
            x = int(x - 
                    ((math.cos((angle) * radiansPerDegree)*lX) + 
                     (math.sin((angle) * radiansPerDegree)*lY)))
            y = int(y - 
                    ((math.cos((angle) * radiansPerDegree)*lY) - 
                     (math.sin((angle) * radiansPerDegree)*lX)))
            drawDC.DrawRotatedText(text, x,y, angle)
        else:
            x = x - lX
            y = y - lY
            drawDC.DrawText(text, x, y)


    def _draw_rotate_polygon(self, drawDC, x, y, tipo, angle):
        if tipo=="ticks_quarters":
            tipo="ticks_hours"
            
        # Add to empty list to prevent system-wide hard freezes under XP...
        points = {"ticks_hours":self.tickShapeHours+[], "ticks_minutes":self.tickShapeMinutes+[]}[tipo]
        size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]

        maxX = max(map(lambda x:x[0],points))
        minX = min(map(lambda x:x[0],points))
        maxY = max(map(lambda x:x[0],points))
        minY = min(map(lambda x:x[0],points))

        maxB = abs(max(maxX, maxY));
        f = size / maxB

        orgX = (maxX - minX) / 2.
        orgY = (maxY - minY) / 2.

        radiansPerDegree = math.pi / 180
        scaledX = x
        scaledY = y

        for z in range(0, len(points)):
            x,y = points[z]
            x = x * f - orgX * f
            y = y * f - orgY * f
            if self.clockStyle & ROTATE_TICKS:
                m,t = self._rect2pol(x,y)
                t = t + angle
                x,y = self._pol2rect(m,t)
            x = x + scaledX
            y = y + scaledY
            points[z] = [int(x), int(y)]

        drawDC.DrawPolygon(points)


    def _pol2rect(self, r, w, deg=1):           # radian if deg=0; degree if deg=1
        if deg:
             w = math.pi * w / 180.0
        return r * math.cos(w), r * math.sin(w)

    def _rect2pol(self, x, y, deg=1):           # radian if deg=0; degree if deg=1
        if deg:
            return math.hypot(x, y), 180.0 * math.atan2(y, x) / math.pi
        else:
            return math.hypot(x, y), math.atan2(y, x)

    def _center2corner(self, x, y, tipo, drawDC=None):
        if tipo == "ticks_quarters":
            tipo = "ticks_hours"

        style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo]
        size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]

        if style & TICKS_DECIMAL or style & TICKS_ROMAN:
            font = {"ticks_hours":self.tickMarkHoursFont, "ticks_minutes":self.tickMarkMinutesFont}[tipo]
            font.SetPointSize(int(size));
            drawDC.SetFont(font)
            lX = drawDC.GetCharWidth() / 2.
            lY = drawDC.GetCharHeight() / 2.
            x = lX
            y = lY
        else:
            size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]
            x=x-size/2.;y=y-size/2.
        return x, y


    def _build_text(self, angle, tipo):
        if tipo == "ticks_quarters":
            tipo = "ticks_hours"
        a = angle
        if a <= 0:
            a = a + 360
        divider = {"ticks_hours":30,"ticks_minutes":6}[tipo]
        a = int(a / divider)

        style = {"ticks_hours":self.tickMarkHoursStyle," ticks_minutes":self.tickMarkMinutesStyle}[tipo]
        text = "%s" % a
        return text


    def _getMarkMaxSize(self, tipo, drawDC=None):
        if tipo == "ticks_quarters":
            tipo = "ticks_hours"

        style = {"ticks_hours":self.tickMarkHoursStyle, "ticks_minutes":self.tickMarkMinutesStyle}[tipo]
        size = self.scale * {"ticks_hours":self.markSizeHour, "ticks_minutes":self.markSizeMin}[tipo]

        if style & TICKS_DECIMAL or style & TICKS_ROMAN:
            lX = 2 * drawDC.GetCharWidth()
            lY = drawDC.GetCharHeight()
            size = math.sqrt(lX**2 + lY**2) * self.scale
        else:
            size=math.sqrt(2) * size
        return size


    def _drawWatch(self, drawDC):
        # Draw the watch...
        if self.watchPen or self.watchBrush:
            if self.watchPen:
                drawDC.SetPen(self.watchPen)
            if self.watchBrush:
                drawDC.SetBrush(self.watchBrush)
            else:
                drawDC.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.SOLID))
            drawDC.DrawCircle(self.centerX, self.centerY, self.radius_watch)

    def _calcSteps(self):
        circle = 360
        mStep = 6 * self.clockStep # Step in degrees...
        vq = 90 * (self.clockStyle & SHOW_QUARTERS_TICKS) / SHOW_QUARTERS_TICKS
        vh = 30 * (self.clockStyle & SHOW_HOURS_TICKS) / SHOW_HOURS_TICKS
        vm = 1  * (self.clockStyle & SHOW_MINUTES_TICKS) / SHOW_MINUTES_TICKS
        coords = {"ticks_quarters": [self.radius_ticks_hours,  60,vq,{}],
                  "ticks_hours":    [self.radius_ticks_hours,  60,vh,{}],
                  "ticks_minutes":  [self.radius_ticks_minutes,60,vm,{}],
                  "hand_hours":     [self.handHoursLength,     60,1, {}],
                  "hand_minutes":   [self.handMinutesLength,   60,1, {}],
                  "hand_seconds":   [self.handSecondsLength,   60,1, {}]}
        radiansPerDegree = math.pi / 180

        for t in coords.keys():
            for i in range(0, circle+mStep, mStep):
                radius = coords[t][0]
                if t == "ticks_minutes":
                    radius = radius - self.offM
                step_angle = 360. / coords[t][1]
                pre = coords[t][2]
                x = self.centerX + radius * math.sin(i * radiansPerDegree)
                y = self.centerY + radius * math.cos(i * radiansPerDegree)
                f = (pre and (i/step_angle == int(i/step_angle)) and (float(i)/pre == int(i/pre)))
                coords[t][3][i] = [x,y,f]

        if not self.clockStyle & OVERLAP_TICKS:
            for i in range(0, circle + mStep, mStep):
                f=coords["ticks_minutes"][3][i][2]
                if f and \
                   (coords["ticks_hours"][3].get(i,[0,0,0])[2] or coords["ticks_quarters"][3].get(i,[0,0,0])[2]):
                    f=False
                coords["ticks_minutes"][3][i][2]=f
        self.coords = coords

    def _getCoords(self, tipo, angle):
        # Returns coords and 'use flag' based on current angle...
        k = 360 - (angle + 180)
        if k <= 0:
            k = k + 360
        return self.coords[tipo][3][k]

# -----------------------------------------------------

    def SetTickShapes(self, tsh, tsm=None):
        if not tsm:
            tsm=tsh
        self.tickShapeHours = tsh
        self.tickShapeMinutes = tsm

    def SetHandWeights(self, h=None, m=None, s=None):
        if h:
           self.handHoursThickness = h
        if m:
           self.handMinutesThickness = m
        if s:
           self.handSecondsThickness = s


    def SetHandColours(self, h=None, m=None, s=None):
        if h and not m and not s:
            m=h
            s=h
        if h:
            self.handHoursColour = h
        if m:
            self.handMinutesColour = m
        if s:
            self.handSecondsColour = s


    def SetTickColours(self, h=None, m=None):
        if not m:
            m=h
        if h:
            self.tickMarkHoursPen = wx.Pen(h, 1, wx.SOLID)
            self.tickMarkHoursBrush = wx.Brush(h, wx.SOLID)
        if m:
           self.tickMarkMinutesPen = wx.Pen(m, 1, wx.SOLID)
           self.tickMarkMinutesBrush = wx.Brush(m, wx.SOLID)


    def SetTickSizes(self, h=None, m=None):
        if h:
            self.markSizeHour = h
        if m:
            self.markSizeMin = m

    def SetTickFonts(self, h=None, m=None):
        if not m:
            m=h
        if h:
            self.tickMarkHoursFont = h
            self.tickMarkHoursFont.SetPointSize(self.markSizeHour)
        if m:
            self.tickMarkMinutesFont = m
            self.tickMarkMinutesFont.SetPointSize(self.markSizeMin)

    def SetMinutesOffset(self, o):
        self.offM = o


    def SetShadowColour(self, s):
        self.shadowPenColour = self.shadowBrushColour = s


    def SetWatchPenBrush(self, p=None, b=None):
        if p:
            self.watchPen = p
        if b:
            self.watchBrush = b

    def SetClockStyle(self, style):
        self.clockStyle = style


    def SetTickStyles(self, h=None, m=None):
        if h:
            self.tickMarkHoursStyle = h
        if m:
            self.tickMarkMinutesStyle = m
	    
	    
#######################################################  END CLOCK  #######################
#######################################################  END CLOCK  #######################

################################################################### PAGE REFRESHES #####################
################################################################### PAGE REFRESHES #####################	

def refreshPage(db_name, tb_name, ftop):
	then = ftop.calend.GetDate()
	when = datetime.date(then[2], then[1], then[0])
	displayName = when.strftime("%A, &nbsp;%m/%d/%Y")
	ftop.aptTimes = []
	
	con = sqlite.connect(db_name)
	cur = con.cursor()
	query = 'pragma table_info(%s)' % tb_name
	cur.execute(query)
	ret = cur.fetchall()
	if not ret:
		if os.access(db_name, os.W_OK):
			query = 'CREATE TABLE %s(apttime str, appt str, abstime str)' % tb_name
			cur.execute(query)
			con.commit()
		
		txt = dHeadAppt + dHeader1 + displayName + dHeader2 + '<center>No appointments are listed for this date</center>' + dFooter
		AppointmentPage.reLoad(ftop.panel2, txt)
		ftop.Refresh()
			
	else:
		query = 'SELECT * FROM %s order by abstime' % tb_name
		cur.execute(query)
		data = cur.fetchall()
		if data:
			txt = dHeadAppt + dHeader1 + displayName + dHeader2
			for row in data:
				tempX = [ item for item in row]
				if len(tempX[1]) > 24:
					tapt = str(tempX[1])[:24]
				else:
					tapt = str(tempX[1])
				tapt = str(tempX[0]) + "    " + tapt
				ftop.aptTimes.append(tapt)
				txt = txt + '<p><b>' + str(tempX[0]) + '</b></p>\n<UL><LI>' + str(tempX[1]) + '</LI></UL>\n'
			txt = txt + '<\body></html>'
			AppointmentPage.reLoad(ftop.panel2,txt)
			ftop.Refresh()
		else:
			txt = dHeadAppt + dHeader1 + displayName + dHeader2 + '<center>No appointments are listed for this date</center>' + dFooter
			AppointmentPage.reLoad(ftop.panel2, txt)
			ftop.Refresh()
	cur.close()
	con.close()
	
	
def refreshContacts(db_name, ftop):
	con = sqlite.connect(db_name)
	cur = con.cursor()
	cur.execute("pragma table_info(contacts)")
	ret = cur.fetchall()
	if not ret:
		cur.execute("CREATE TABLE contacts(lname str, fname str, address1 str, address2 str, telephone str, email str, comment str)")
		con.commit()
	else:
		cur.execute("SELECT * FROM contacts order by lname")
		data = cur.fetchall()
		if data:
			txt = dHeadCont + dHeader1 + 'Contacts' + dHeader2
			for row in data:
				tempX = [ item for item in row]
				txt = txt + '<UL><LI><p><b>' + str(tempX[0]) + ', ' + str(tempX[1]) + '</b><br>'
				if tempX[2]: txt = txt +  str(tempX[2]) + '<br>'
				if tempX[3]: txt = txt +  str(tempX[3]) + '<br>'
				if tempX[4]: txt = txt +  str(tempX[4]) + '<br>'
				if tempX[5]: txt = txt +  '<a href=\"mailto:' + str(tempX[5]) + '\">' + str(tempX[5]) + '</a><br>'
				if tempX[6]: txt = txt +  str(tempX[6]) + '<br>'
				txt = txt + '\n</UL></LI><br>\n'
			txt = txt + '<\body></html>'
			AppointmentPage.reLoad(ftop.panel2,txt)
			ftop.Refresh()
		else:
			txt = dHeadCont + dHeader1 + 'Contacts' + dHeader2 + '<center>You have not yet entered any contacts</center>' + dFooter
			AppointmentPage.reLoad(ftop.panel2, txt)
			ftop.Refresh()
	cur.close()
	con.close()
	

def refreshTodo(db_name, ftop):
	con = sqlite.connect(db_name)
	cur = con.cursor()
	cur.execute("pragma table_info(todo)")
	ret = cur.fetchall()
	if not ret:
		cur.execute("CREATE TABLE todo(subject str, details str)")
		con.commit()
	else:
		cur.execute("SELECT * FROM todo")
		data = cur.fetchall()
		if data:
			txt = dHeadTodo + dHeader1 + 'To-Do List' + dHeader2
			for row in data:
				tempX = [ item for item in row]
				txt = txt + '<UL><LI><p><b>' + str(tempX[0]) + '</b><br>'
				if tempX[1]: txt = txt  + str(tempX[1]) + '<br>'
				txt = txt + '\n</UL></LI><br>\n'
				
			txt = txt + '<\body></html>'
			AppointmentPage.reLoad(ftop.panel2,txt)
			ftop.Refresh()
		else:
			txt = dHeadTodo + dHeader1 + 'To-Do List' + dHeader2 + '<center>You have no To-Do items</center>' + dFooter
			AppointmentPage.reLoad(ftop.panel2, txt)
			ftop.Refresh()
	cur.close()
	con.close()


		

class alert_frame(wx.Frame):
	def __init__(self, parent, db):
        	wx.Frame.__init__(self, parent, -1, title="Pending Appointments")
		self.SetSizeHints(250, 200, -1, -1)
		self.BLINK_STATE = 0
		haveicons = 0
		self.ID_ICON_TIMER = wx.NewId()	
		self.db =  db
		self.parent = parent
		
		try:
			self.icon1=wx.EmptyIcon()
			self.icon1.CopyFromBitmap(images.getonalertBitmap())
			self.SetIcon(self.icon1)
			self.icon2=wx.EmptyIcon()
			self.icon2.CopyFromBitmap(images.getoffalertBitmap())
			haveicons = 1
		except:
			pass
		
        	self.html = html.HtmlWindow(self)
        	self.box = wx.BoxSizer(wx.VERTICAL)
        	self.box.Add(self.html, 1, wx.GROW)
        	subbox = wx.BoxSizer(wx.HORIZONTAL)
        	btn = wx.Button(self, -1, "Close Reminders")
        	subbox.Add(btn, 1, wx.GROW | wx.ALL, 2)
		btn.Bind(wx.EVT_BUTTON, self.OnClose)
		btn.SetToolTip( wx.ToolTip( 'Close this window.\nReminders will continue hourly' ) )
		
		btn1 = wx.Button(self, -1, "Stop reminders")
		subbox.Add(btn1, 1, wx.GROW | wx.ALL, 2)
		btn1.Bind(wx.EVT_BUTTON, self.OnCloseSkip)
		btn1.SetToolTip( wx.ToolTip( 'Close this window.\nReminders will cease for TODAY\n\nTo stop them permanently, use the right-click appointment menu and uncheck \"Alerts\"' ) )
		
        	self.box.Add(subbox, 0, wx.GROW)
        	self.SetSizer(self.box)
        	self.SetAutoLayout(True)
        	self.showReminders(self.parent.dbName, haveicons)
		wx.Bell()
		
		
  
	def showReminders(self, db, icons):
		# make strings for sections of the page to be shown in the HTML page displayed for reminders
		rHeader1 = '''<html><body><center><table width="100%" cellspacing="0" cellpadding="0" border="0"><tr><td align="center"><b>							'''	
		rHeader2 = '''</b></td></tr><tr><td>'''
		rHeader3 = '''</td></tr><tr><td align="center"><b><br><br><hr><br>'''		
		rHeader4 = '''</td></tr></table></center>'''
		rFooter = '</body></html>'
		
		# make string to show current date at top of reminder page
		now = time.localtime(time.time())
		display_date = time.strftime("%A %B %d", now)
		
		tom = time.localtime(time.time() + 86400)
		display_tom = time.strftime("%A %B %d", tom)


		# get date TABLE NAMES which will be displayed (today and tomorrow)
		
		d = "a" + time.strftime("%Y%m%d",time.localtime(time.time()))
		d1 = "a" + time.strftime("%Y%m%d",time.localtime(time.time() + 86400))
	

		txt = rHeader1 + display_date + rHeader2
		
		
		con = sqlite.connect(db)
		cur = con.cursor()
		query = 'pragma table_info(%s)' % d
		cur.execute(query)
		ret = cur.fetchall()
		if not ret:
			txt = txt + '<center>No appointments are listed for this date</center>'
		else:
			query = 'SELECT * FROM %s order by abstime' % d
			cur.execute(query)
			data = cur.fetchall()
			if data:

				for row in data:
					tempX = [ item for item in row]
					if len(tempX[1]) > 24:
						tapt = str(tempX[1])[:24]
					else:
						tapt = str(tempX[1])
					tapt = str(tempX[0]) + "    " + tapt
					txt = txt + '<p><b>' + str(tempX[0]) + '</b></p>\n<UL><LI>' + str(tempX[1]) + '</LI></UL>\n'

			else:
				txt = txt + '<center>No appointments are listed for this date</center>'
		cur.close()
		con.close()
		
		txt = txt + rHeader3 + display_tom + rHeader2
		
		# next day
		con = sqlite.connect(db)
		cur = con.cursor()
		query = 'pragma table_info(%s)' % d1
		cur.execute(query)
		ret = cur.fetchall()
		if not ret:
			txt = txt + '<center>No appointments are listed for this date</center>'
		else:
			query = 'SELECT * FROM %s order by abstime' % d1
			cur.execute(query)
			data = cur.fetchall()
			if data:

				for row in data:
					tempX = [ item for item in row]
					if len(tempX[1]) > 24:
						tapt = str(tempX[1])[:24]
					else:
						tapt = str(tempX[1])
					tapt = str(tempX[0]) + "    " + tapt
					txt = txt + '<p><b>' + str(tempX[0]) + '</b></p>\n<UL><LI>' + str(tempX[1]) + '</LI></UL>\n'

			else:
				txt = txt +  '<center>No appointments are listed for this date</center>'
		cur.close()
		con.close()	
	
		txt = txt + rHeader4 + rFooter
	
        	self.html.SetPage(txt)
		if icons == 1:
			self.SetIconTimer()


	def SetIconTimer(self):
		self.icontimer = wx.Timer(self, self.ID_ICON_TIMER)
		self.Bind(wx.EVT_TIMER, self.BlinkIcon)
		self.icontimer.Start(1000)

	def BlinkIcon(self, evt):
	
		if self.BLINK_STATE == 0:
			self.SetIcon(self.icon1)
			self.BLINK_STATE = 1
		else:
			self.SetIcon(self.icon2)
			self.BLINK_STATE = 0

	def OnClose(self, evt):
		self.Destroy()
		
	def OnCloseSkip(self, evt):
		self.setSkip()
		self.Destroy()
		

	def setSkip(self):
		ftop = self.parent
		v1 = self.parent.checkOptions(self.db)
		v2 = self.parent.checkAlerts(self.db)
		con = sqlite.connect(self.db)
		cur = con.cursor()
		cur.execute("delete from options where alerts = 'y' or alerts = 'n'")
		con.commit()
		today = datetime.date.today()
		v3 = "a" + string.zfill(today.year, 4) + string.zfill(today.month, 2) + string.zfill(today.day, 2)
		vals = v1, v2, v3
		query = "insert into options (caltype, alerts, skipalert) values (?, ?, ?)"
		cur.execute(query, vals)	
		con.commit()
		cur.execute("select name from sqlite_master where type='table'")
		data = cur.fetchall()
		cur.close()
		con.close()	
				
		
def MessageDlg(self, message, type = 'Message'):
	dlg = wx.MessageDialog(self, message, type, wx.OK | wx.ICON_INFORMATION)
	dlg.ShowModal()
	dlg.Destroy()
	
	    
def opj(path):
	"""Convert paths to the platform-specific separator"""
	str = apply(os.path.join, tuple(path.split('/')))
	# HACK: on Linux, a leading / gets lost...
	if path.startswith('/'):
		str = '/' + str
	return str
   
app = wx.PySimpleApp()
frame = CalendFrame(None, -1, "pAgenda - Appointment Calendar")
frame.Show()
app.MainLoop()
