Initial commit for unified repo.

This commit is contained in:
2020-11-17 14:22:59 -06:00
parent 0bc0e7d278
commit 780646b254
44 changed files with 1156 additions and 1 deletions

8
Linux/LICENSE Normal file
View File

@ -0,0 +1,8 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

BIN
Linux/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

3
Linux/README.md Normal file
View File

@ -0,0 +1,3 @@
# pecos
Polaris Emergency Check Out System

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

BIN
Linux/archive/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
Linux/bg-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

BIN
Linux/checkouts.db Normal file

Binary file not shown.

BIN
Linux/emptybase.db Normal file

Binary file not shown.

24
Linux/export.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<title>
PECOS Export - 13:36:32 on Tuesday, November 17, 2020
</title>
<h2>PECOS Export File &ndash; 13:36:32 on Tuesday, November 17, 2020</h2>
<hr>
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-cly1{text-align:left;vertical-align:middle}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-cly1"><strong>Patron Library Card</strong></th><th class="tg-cly1"><strong>Batch Number</strong></th><th class="tg-cly1"><strong>Item Barcode</strong>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567890.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567891.svg" width=200>
</tr>

View File

@ -0,0 +1 @@
Item data will go here.

View File

@ -0,0 +1 @@
Patron data will go here.

288
Linux/pecos.py Normal file
View File

@ -0,0 +1,288 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# GUI module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:32:51 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
import os
import shutil
from tkinter import messagebox
from xlsxwriter.workbook import Workbook
from barcode import Code39
from barcode.writer import ImageWriter
import subprocess
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import pecos_support
# --- SET UP A TIMESTAMP FUNCTION THAT UPDATES PROPERLY ---
def timestamp():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def ReportTime():
return datetime.now().strftime('%H:%M:%S on %A, %B %d, %Y')
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
pecos_support.init(root, top)
root.iconbitmap('PECOS.ico')
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
pecos_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
# Close database connection
conn.close()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x500+650+150")
top.minsize(1, 1)
top.maxsize(1905, 1050)
top.resizable(0, 0)
top.title("PECOS - Polaris Emergency Check Out System 1.0b (Windows)")
# --- CHECKOUT ITEM AND UPDATE DATABASE ---
def CheckOutItem(event=None):
if len(self.item_entry.get()) == 0:
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
else:
# Set up database connections
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO CheckOuts VALUES (:PatronID, :ItemID, :TransactionDateTime, :ItemLink, :PatronLink, :BatchNumber)",
{
'PatronID': self.patron_entry.get(),
'ItemID': self.item_entry.get(),
'TransactionDateTime': timestamp(),
'ItemLink': ("item/" + self.item_entry.get()),
'PatronLink': ("patron/" + self.patron_entry.get()),
'BatchNumber': CurrentBatchNumber
}
)
# Commit changes
conn.commit()
#PatronBarcode = self.patron_entry.get()
PatCode = Code39(self.patron_entry.get(), add_checksum=False)
PatCode.save("patron/"+self.patron_entry.get())
ItemCode = Code39(self.item_entry.get(), add_checksum=False)
ItemCode.save("item/"+self.item_entry.get())
self.item_entry.delete(0, tk.END)
# --- PATRON SCANNED - MOVE TO ITEM FIELD ---
def ChangeFocus(event):
self.item_entry.focus_set()
self.patron_entry.configure(state='disabled')
# --- FINISH CHECKOUT AND CLEAR FIELDS ---
def CheckOutComplete():
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
# --- DELETE THE CURRENT DATABASE AND SUPPLANT WITH AN EMPTY ONE ---
def ClearDatabase():
self.ClearConfirm = tk.messagebox.askquestion ('PECOS - Clear Database','Are you sure you wish to clear the database? This cannot be undone!')
if self.ClearConfirm == 'yes':
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Re-establish connection to the database
#conn.close # Close out the current database
os.remove("checkouts.db") # Delete the current database
shutil.copy("emptybase.db", "checkouts.db") # Copy over an empty database
shutil.rmtree('item')
shutil.rmtree('patron')
os.makedirs('item')
os.makedirs('patron')
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Restablish connection to the database
#c = conn.cursor()
else:
messagebox.showinfo('PECOS - Database Retained','Database retained. No changes made.')
# --- EXPORT DATABASE TO HTML ---
def ExportDatabase():
if os.path.exists("export.html"):
os.remove("export.html")
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
with open("export.html", "w") as f:
f.write("<html>\n")
f.write("<head>\n")
f.write("<title>\n")
f.write("PECOS Export - " + ReportTime() + "\n")
f.write("</title>\n")
f.write("<h2>PECOS Export File &ndash; " + ReportTime() + "</h2>\n<hr>\n")
f.write("<style type=\"text/css\">\n")
f.write(".tg {border-collapse:collapse;border-spacing:0;}\n")
f.write(".tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg .tg-cly1{text-align:left;vertical-align:middle}\n")
f.write("</style>\n")
f.write("<table class=\"tg\">\n")
f.write("<thead>\n")
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><strong>Patron Library Card</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch Number</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Item Barcode</strong>\n")
f.write("</tr>\n")
for row in c.execute("SELECT BatchNumber, PatronLink, ItemLink FROM CheckOuts ORDER By BatchNumber"):
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[1] + ".svg\" width=200></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch: </strong>" + str(row[0]) + "</th>")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[2] + ".svg\" width=200>\n")
f.write("</tr>\n")
subprocess.run(['open', 'export.html'], check=True) # Open export.html in the default web browser (macOS)
#os.startfile('export.html') # Open export.html in the default web browser (Windows)
self.Canvas1 = tk.Canvas(top)
self.image = ImageTk.PhotoImage(Image.open("bg-01.png"))
self.Canvas1.create_image(0,0,anchor="nw",image=self.image)
self.Canvas1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="blue")
self.Canvas1.configure(selectforeground="white")
self.Frame1 = tk.Frame(self.Canvas1)
self.Frame1.place(relx=0.05, rely=0.06, relheight=0.17, relwidth=0.908)
self.Frame1.configure(relief='sunken')
self.Frame1.configure(borderwidth="2")
self.Frame1.configure(relief="sunken")
self.patron_label = tk.Label(self.Canvas1)
self.patron_label.place(relx=0.067, rely=0.08, height=19, width=100)
self.patron_label.configure(text='''Patron barcode:''')
self.patron_entry = tk.Entry(self.Canvas1)
self.patron_entry.place(relx=0.25, rely=0.08,height=25, relwidth=0.377)
self.patron_entry.configure(background="white")
self.patron_entry.configure(font="TkFixedFont")
self.patron_entry.bind('<Return>', ChangeFocus)
self.item_label = tk.Label(self.Canvas1)
self.item_label.place(relx=0.067, rely=0.16, height=19, width=89)
self.item_label.configure(text='''Item barcode:''')
self.item_entry = tk.Entry(self.Canvas1)
self.item_entry.place(relx=0.25, rely=0.16,height=25, relwidth=0.377)
self.item_entry.configure(background="white")
self.item_entry.configure(font="TkFixedFont")
self.item_entry.bind('<Return>', CheckOutItem)
self.finish_button = tk.Button(self.Canvas1, command=CheckOutComplete)
self.finish_button.place(relx=0.7, rely=0.12, height=29, width=123)
self.finish_button.configure(text='''Finish checkout''')
self.LowerFrame = tk.Frame(self.Canvas1)
self.LowerFrame.place(relx=0.05, rely=0.78, relheight=0.13, relwidth=0.908)
self.LowerFrame.configure(relief='sunken')
self.LowerFrame.configure(borderwidth="2")
self.LowerFrame.configure(relief="sunken")
self.export_button = tk.Button(self.LowerFrame, command=ExportDatabase)
self.export_button.place(relx=0.092, rely=0.308, height=29, width=130)
self.export_button.configure(text='''Export Checkouts''')
self.clear_button = tk.Button(self.LowerFrame, command=ClearDatabase)
self.clear_button.place(relx=0.679, rely=0.308, height=29, width=130)
self.clear_button.configure(text='''Clear Database''')
if __name__ == '__main__':
vp_start_gui()

43
Linux/pecos_support.py Normal file
View File

@ -0,0 +1,43 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Support module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:33:24 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
# --- DEFINE FUNCTIONS ---
def init(top, gui, *args, **kwargs):
global w, top_level, root
w = gui
top_level = top
root = top
def destroy_window():
# Function which closes the window.
global top_level
top_level.destroy()
top_level = None
if __name__ == '__main__':
import pecos
pecos.vp_start_gui()

BIN
PECOS Manual.pages Executable file

Binary file not shown.

View File

@ -1,3 +1,3 @@
# pecos-unified
# PECOS Unified
Polaris Emergency Check Out System - unified code repository for Windows, macOS, and Linux.

8
Windows/LICENSE Normal file
View File

@ -0,0 +1,8 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

BIN
Windows/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

3
Windows/README.md Normal file
View File

@ -0,0 +1,3 @@
# pecos
Polaris Emergency Check Out System

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

BIN
Windows/archive/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
Windows/bg-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

BIN
Windows/checkouts.db Normal file

Binary file not shown.

BIN
Windows/emptybase.db Normal file

Binary file not shown.

36
Windows/export.html Normal file
View File

@ -0,0 +1,36 @@
<html>
<head>
<title>
PECOS Export - 06:14:31 on Wednesday, November 11, 2020
</title>
<h2>PECOS Export File &ndash; 06:14:31 on Wednesday, November 11, 2020</h2>
<hr>
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-cly1{text-align:left;vertical-align:middle}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-cly1"><strong>Patron Library Card</strong></th><th class="tg-cly1"><strong>Batch Number</strong></th><th class="tg-cly1"><strong>Item Barcode</strong>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567890.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567891.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567892.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004233141.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>3</th><th class="tg-cly1"><img src="item/1234567893.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004233141.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>3</th><th class="tg-cly1"><img src="item/1234567894.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004233141.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>3</th><th class="tg-cly1"><img src="item/1234567895.svg" width=200>
</tr>

View File

@ -0,0 +1 @@
Item data will go here.

View File

@ -0,0 +1 @@
Patron data will go here.

288
Windows/pecos.py Normal file
View File

@ -0,0 +1,288 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# GUI module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:32:51 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
import os
import shutil
from tkinter import messagebox
from xlsxwriter.workbook import Workbook
from barcode import Code39
from barcode.writer import ImageWriter
import subprocess
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import pecos_support
# --- SET UP A TIMESTAMP FUNCTION THAT UPDATES PROPERLY ---
def timestamp():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def ReportTime():
return datetime.now().strftime('%H:%M:%S on %A, %B %d, %Y')
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
pecos_support.init(root, top)
root.iconbitmap('PECOS.ico')
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
pecos_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
# Close database connection
conn.close()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x500+650+150")
top.minsize(1, 1)
top.maxsize(1905, 1050)
top.resizable(0, 0)
top.title("PECOS - Polaris Emergency Check Out System 1.0b (Windows)")
# --- CHECKOUT ITEM AND UPDATE DATABASE ---
def CheckOutItem(event=None):
if len(self.item_entry.get()) == 0:
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
else:
# Set up database connections
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO CheckOuts VALUES (:PatronID, :ItemID, :TransactionDateTime, :ItemLink, :PatronLink, :BatchNumber)",
{
'PatronID': self.patron_entry.get(),
'ItemID': self.item_entry.get(),
'TransactionDateTime': timestamp(),
'ItemLink': ("item/" + self.item_entry.get()),
'PatronLink': ("patron/" + self.patron_entry.get()),
'BatchNumber': CurrentBatchNumber
}
)
# Commit changes
conn.commit()
#PatronBarcode = self.patron_entry.get()
PatCode = Code39(self.patron_entry.get(), add_checksum=False)
PatCode.save("patron/"+self.patron_entry.get())
ItemCode = Code39(self.item_entry.get(), add_checksum=False)
ItemCode.save("item/"+self.item_entry.get())
self.item_entry.delete(0, tk.END)
# --- PATRON SCANNED - MOVE TO ITEM FIELD ---
def ChangeFocus(event):
self.item_entry.focus_set()
self.patron_entry.configure(state='disabled')
# --- FINISH CHECKOUT AND CLEAR FIELDS ---
def CheckOutComplete():
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
# --- DELETE THE CURRENT DATABASE AND SUPPLANT WITH AN EMPTY ONE ---
def ClearDatabase():
self.ClearConfirm = tk.messagebox.askquestion ('PECOS - Clear Database','Are you sure you wish to clear the database? This cannot be undone!')
if self.ClearConfirm == 'yes':
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Re-establish connection to the database
#conn.close # Close out the current database
os.remove("checkouts.db") # Delete the current database
shutil.copy("emptybase.db", "checkouts.db") # Copy over an empty database
shutil.rmtree('item')
shutil.rmtree('patron')
os.makedirs('item')
os.makedirs('patron')
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Restablish connection to the database
#c = conn.cursor()
else:
messagebox.showinfo('PECOS - Database Retained','Database retained. No changes made.')
# --- EXPORT DATABASE TO HTML ---
def ExportDatabase():
if os.path.exists("export.html"):
os.remove("export.html")
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
with open("export.html", "w") as f:
f.write("<html>\n")
f.write("<head>\n")
f.write("<title>\n")
f.write("PECOS Export - " + ReportTime() + "\n")
f.write("</title>\n")
f.write("<h2>PECOS Export File &ndash; " + ReportTime() + "</h2>\n<hr>\n")
f.write("<style type=\"text/css\">\n")
f.write(".tg {border-collapse:collapse;border-spacing:0;}\n")
f.write(".tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg .tg-cly1{text-align:left;vertical-align:middle}\n")
f.write("</style>\n")
f.write("<table class=\"tg\">\n")
f.write("<thead>\n")
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><strong>Patron Library Card</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch Number</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Item Barcode</strong>\n")
f.write("</tr>\n")
for row in c.execute("SELECT BatchNumber, PatronLink, ItemLink FROM CheckOuts ORDER By BatchNumber"):
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[1] + ".svg\" width=200></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch: </strong>" + str(row[0]) + "</th>")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[2] + ".svg\" width=200>\n")
f.write("</tr>\n")
#subprocess.run(['open', 'export.html'], check=True) # Open export.html in the default web browser (macOS)
os.startfile('export.html') # Open export.html in the default web browser (Windows)
self.Canvas1 = tk.Canvas(top)
self.image = ImageTk.PhotoImage(Image.open("bg-01.png"))
self.Canvas1.create_image(0,0,anchor="nw",image=self.image)
self.Canvas1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="blue")
self.Canvas1.configure(selectforeground="white")
self.Frame1 = tk.Frame(self.Canvas1)
self.Frame1.place(relx=0.05, rely=0.06, relheight=0.17, relwidth=0.908)
self.Frame1.configure(relief='sunken')
self.Frame1.configure(borderwidth="2")
self.Frame1.configure(relief="sunken")
self.patron_label = tk.Label(self.Canvas1)
self.patron_label.place(relx=0.067, rely=0.08, height=19, width=100)
self.patron_label.configure(text='''Patron barcode:''')
self.patron_entry = tk.Entry(self.Canvas1)
self.patron_entry.place(relx=0.25, rely=0.08,height=25, relwidth=0.377)
self.patron_entry.configure(background="white")
self.patron_entry.configure(font="TkFixedFont")
self.patron_entry.bind('<Return>', ChangeFocus)
self.item_label = tk.Label(self.Canvas1)
self.item_label.place(relx=0.067, rely=0.16, height=19, width=89)
self.item_label.configure(text='''Item barcode:''')
self.item_entry = tk.Entry(self.Canvas1)
self.item_entry.place(relx=0.25, rely=0.16,height=25, relwidth=0.377)
self.item_entry.configure(background="white")
self.item_entry.configure(font="TkFixedFont")
self.item_entry.bind('<Return>', CheckOutItem)
self.finish_button = tk.Button(self.Canvas1, command=CheckOutComplete)
self.finish_button.place(relx=0.7, rely=0.12, height=29, width=123)
self.finish_button.configure(text='''Finish checkout''')
self.LowerFrame = tk.Frame(self.Canvas1)
self.LowerFrame.place(relx=0.05, rely=0.78, relheight=0.13, relwidth=0.908)
self.LowerFrame.configure(relief='sunken')
self.LowerFrame.configure(borderwidth="2")
self.LowerFrame.configure(relief="sunken")
self.export_button = tk.Button(self.LowerFrame, command=ExportDatabase)
self.export_button.place(relx=0.092, rely=0.308, height=29, width=130)
self.export_button.configure(text='''Export Checkouts''')
self.clear_button = tk.Button(self.LowerFrame, command=ClearDatabase)
self.clear_button.place(relx=0.679, rely=0.308, height=29, width=130)
self.clear_button.configure(text='''Clear Database''')
if __name__ == '__main__':
vp_start_gui()

43
Windows/pecos_support.py Normal file
View File

@ -0,0 +1,43 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Support module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:33:24 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
# --- DEFINE FUNCTIONS ---
def init(top, gui, *args, **kwargs):
global w, top_level, root
w = gui
top_level = top
root = top
def destroy_window():
# Function which closes the window.
global top_level
top_level.destroy()
top_level = None
if __name__ == '__main__':
import pecos
pecos.vp_start_gui()

8
macOS/LICENSE Normal file
View File

@ -0,0 +1,8 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

BIN
macOS/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

3
macOS/README.md Normal file
View File

@ -0,0 +1,3 @@
# pecos
Polaris Emergency Check Out System

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

BIN
macOS/archive/PECOS.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
macOS/bg-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

BIN
macOS/checkouts.db Normal file

Binary file not shown.

BIN
macOS/emptybase.db Normal file

Binary file not shown.

24
macOS/export.html Normal file
View File

@ -0,0 +1,24 @@
<html>
<head>
<title>
PECOS Export - 13:36:32 on Tuesday, November 17, 2020
</title>
<h2>PECOS Export File &ndash; 13:36:32 on Tuesday, November 17, 2020</h2>
<hr>
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}
.tg .tg-cly1{text-align:left;vertical-align:middle}
</style>
<table class="tg">
<thead>
<tr>
<th class="tg-cly1"><strong>Patron Library Card</strong></th><th class="tg-cly1"><strong>Batch Number</strong></th><th class="tg-cly1"><strong>Item Barcode</strong>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567890.svg" width=200>
</tr>
<tr>
<th class="tg-cly1"><img src="patron/1230004231819.svg" width=200></th><th class="tg-cly1"><strong>Batch: </strong>2</th><th class="tg-cly1"><img src="item/1234567891.svg" width=200>
</tr>

View File

@ -0,0 +1 @@
Item data will go here.

View File

@ -0,0 +1 @@
Patron data will go here.

288
macOS/pecos.py Normal file
View File

@ -0,0 +1,288 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# GUI module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:32:51 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
import os
import shutil
from tkinter import messagebox
from xlsxwriter.workbook import Workbook
from barcode import Code39
from barcode.writer import ImageWriter
import subprocess
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
import pecos_support
# --- SET UP A TIMESTAMP FUNCTION THAT UPDATES PROPERLY ---
def timestamp():
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def ReportTime():
return datetime.now().strftime('%H:%M:%S on %A, %B %d, %Y')
def vp_start_gui():
'''Starting point when module is the main routine.'''
global val, w, root
root = tk.Tk()
top = Toplevel1 (root)
pecos_support.init(root, top)
root.iconbitmap('PECOS.ico')
root.mainloop()
w = None
def create_Toplevel1(rt, *args, **kwargs):
'''Starting point when module is imported by another module.
Correct form of call: 'create_Toplevel1(root, *args, **kwargs)' .'''
global w, w_win, root
#rt = root
root = rt
w = tk.Toplevel (root)
top = Toplevel1 (w)
pecos_support.init(w, top, *args, **kwargs)
return (w, top)
def destroy_Toplevel1():
global w
w.destroy()
w = None
# Close database connection
conn.close()
class Toplevel1:
def __init__(self, top=None):
'''This class configures and populates the toplevel window.
top is the toplevel containing window.'''
_bgcolor = '#d9d9d9' # X11 color: 'gray85'
_fgcolor = '#000000' # X11 color: 'black'
_compcolor = '#d9d9d9' # X11 color: 'gray85'
_ana1color = '#d9d9d9' # X11 color: 'gray85'
_ana2color = '#ececec' # Closest X11 color: 'gray92'
top.geometry("600x500+650+150")
top.minsize(1, 1)
top.maxsize(1905, 1050)
top.resizable(0, 0)
top.title("PECOS - Polaris Emergency Check Out System 1.0b (Windows)")
# --- CHECKOUT ITEM AND UPDATE DATABASE ---
def CheckOutItem(event=None):
if len(self.item_entry.get()) == 0:
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
else:
# Set up database connections
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO CheckOuts VALUES (:PatronID, :ItemID, :TransactionDateTime, :ItemLink, :PatronLink, :BatchNumber)",
{
'PatronID': self.patron_entry.get(),
'ItemID': self.item_entry.get(),
'TransactionDateTime': timestamp(),
'ItemLink': ("item/" + self.item_entry.get()),
'PatronLink': ("patron/" + self.patron_entry.get()),
'BatchNumber': CurrentBatchNumber
}
)
# Commit changes
conn.commit()
#PatronBarcode = self.patron_entry.get()
PatCode = Code39(self.patron_entry.get(), add_checksum=False)
PatCode.save("patron/"+self.patron_entry.get())
ItemCode = Code39(self.item_entry.get(), add_checksum=False)
ItemCode.save("item/"+self.item_entry.get())
self.item_entry.delete(0, tk.END)
# --- PATRON SCANNED - MOVE TO ITEM FIELD ---
def ChangeFocus(event):
self.item_entry.focus_set()
self.patron_entry.configure(state='disabled')
# --- FINISH CHECKOUT AND CLEAR FIELDS ---
def CheckOutComplete():
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
row = c.execute("SELECT BatchNumber FROM Batches ORDER BY BatchNumber DESC LIMIT 1").fetchone()
if row is not None:
GetLastBatchNumber = row[0]
CurrentBatchNumber = GetLastBatchNumber + 1
c.execute("INSERT INTO Batches VALUES (:BatchNumber, :PatronID)",
{
'BatchNumber': CurrentBatchNumber,
'PatronID': self.patron_entry.get()
}
)
# Commit changes
conn.commit()
self.patron_entry.delete(0, tk.END)
self.item_entry.delete(0, tk.END)
self.patron_entry.configure(state='normal')
self.patron_entry.delete(0, tk.END)
self.patron_entry.focus_set()
# --- DELETE THE CURRENT DATABASE AND SUPPLANT WITH AN EMPTY ONE ---
def ClearDatabase():
self.ClearConfirm = tk.messagebox.askquestion ('PECOS - Clear Database','Are you sure you wish to clear the database? This cannot be undone!')
if self.ClearConfirm == 'yes':
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Re-establish connection to the database
#conn.close # Close out the current database
os.remove("checkouts.db") # Delete the current database
shutil.copy("emptybase.db", "checkouts.db") # Copy over an empty database
shutil.rmtree('item')
shutil.rmtree('patron')
os.makedirs('item')
os.makedirs('patron')
# Next two lines commented out in Windows version - the connection commands work on macOS
#conn = sqlite3.connect('checkouts.db') # Restablish connection to the database
#c = conn.cursor()
else:
messagebox.showinfo('PECOS - Database Retained','Database retained. No changes made.')
# --- EXPORT DATABASE TO HTML ---
def ExportDatabase():
if os.path.exists("export.html"):
os.remove("export.html")
conn = sqlite3.connect('checkouts.db')
c = conn.cursor()
with open("export.html", "w") as f:
f.write("<html>\n")
f.write("<head>\n")
f.write("<title>\n")
f.write("PECOS Export - " + ReportTime() + "\n")
f.write("</title>\n")
f.write("<h2>PECOS Export File &ndash; " + ReportTime() + "</h2>\n<hr>\n")
f.write("<style type=\"text/css\">\n")
f.write(".tg {border-collapse:collapse;border-spacing:0;}\n")
f.write(".tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px; overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n")
f.write(".tg .tg-cly1{text-align:left;vertical-align:middle}\n")
f.write("</style>\n")
f.write("<table class=\"tg\">\n")
f.write("<thead>\n")
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><strong>Patron Library Card</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch Number</strong></th>")
f.write("<th class=\"tg-cly1\"><strong>Item Barcode</strong>\n")
f.write("</tr>\n")
for row in c.execute("SELECT BatchNumber, PatronLink, ItemLink FROM CheckOuts ORDER By BatchNumber"):
f.write("<tr>\n")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[1] + ".svg\" width=200></th>")
f.write("<th class=\"tg-cly1\"><strong>Batch: </strong>" + str(row[0]) + "</th>")
f.write("<th class=\"tg-cly1\"><img src=\"" + row[2] + ".svg\" width=200>\n")
f.write("</tr>\n")
subprocess.run(['open', 'export.html'], check=True) # Open export.html in the default web browser (macOS)
#os.startfile('export.html') # Open export.html in the default web browser (Windows)
self.Canvas1 = tk.Canvas(top)
self.image = ImageTk.PhotoImage(Image.open("bg-01.png"))
self.Canvas1.create_image(0,0,anchor="nw",image=self.image)
self.Canvas1.place(relx=0.0, rely=0.0, relheight=1.0, relwidth=1.0)
self.Canvas1.configure(borderwidth="2")
self.Canvas1.configure(relief="ridge")
self.Canvas1.configure(selectbackground="blue")
self.Canvas1.configure(selectforeground="white")
self.Frame1 = tk.Frame(self.Canvas1)
self.Frame1.place(relx=0.05, rely=0.06, relheight=0.17, relwidth=0.908)
self.Frame1.configure(relief='sunken')
self.Frame1.configure(borderwidth="2")
self.Frame1.configure(relief="sunken")
self.patron_label = tk.Label(self.Canvas1)
self.patron_label.place(relx=0.067, rely=0.08, height=19, width=100)
self.patron_label.configure(text='''Patron barcode:''')
self.patron_entry = tk.Entry(self.Canvas1)
self.patron_entry.place(relx=0.25, rely=0.08,height=25, relwidth=0.377)
self.patron_entry.configure(background="white")
self.patron_entry.configure(font="TkFixedFont")
self.patron_entry.bind('<Return>', ChangeFocus)
self.item_label = tk.Label(self.Canvas1)
self.item_label.place(relx=0.067, rely=0.16, height=19, width=89)
self.item_label.configure(text='''Item barcode:''')
self.item_entry = tk.Entry(self.Canvas1)
self.item_entry.place(relx=0.25, rely=0.16,height=25, relwidth=0.377)
self.item_entry.configure(background="white")
self.item_entry.configure(font="TkFixedFont")
self.item_entry.bind('<Return>', CheckOutItem)
self.finish_button = tk.Button(self.Canvas1, command=CheckOutComplete)
self.finish_button.place(relx=0.7, rely=0.12, height=29, width=123)
self.finish_button.configure(text='''Finish checkout''')
self.LowerFrame = tk.Frame(self.Canvas1)
self.LowerFrame.place(relx=0.05, rely=0.78, relheight=0.13, relwidth=0.908)
self.LowerFrame.configure(relief='sunken')
self.LowerFrame.configure(borderwidth="2")
self.LowerFrame.configure(relief="sunken")
self.export_button = tk.Button(self.LowerFrame, command=ExportDatabase)
self.export_button.place(relx=0.092, rely=0.308, height=29, width=130)
self.export_button.configure(text='''Export Checkouts''')
self.clear_button = tk.Button(self.LowerFrame, command=ClearDatabase)
self.clear_button.place(relx=0.679, rely=0.308, height=29, width=130)
self.clear_button.configure(text='''Clear Database''')
if __name__ == '__main__':
vp_start_gui()

43
macOS/pecos_support.py Normal file
View File

@ -0,0 +1,43 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Support module generated by PAGE version 5.4
# in conjunction with Tcl version 8.6
# Sep 30, 2020 01:33:24 PM CDT platform: Linux
import sys
from PIL import Image, ImageTk
import sqlite3
from datetime import datetime
from datetime import date
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
try:
import ttk
py3 = False
except ImportError:
import tkinter.ttk as ttk
py3 = True
# --- DEFINE FUNCTIONS ---
def init(top, gui, *args, **kwargs):
global w, top_level, root
w = gui
top_level = top
root = top
def destroy_window():
# Function which closes the window.
global top_level
top_level.destroy()
top_level = None
if __name__ == '__main__':
import pecos
pecos.vp_start_gui()