You may have another way to get the imports to work but main calls controller, dialogs and model.
All pasted below. I’m happy to provide access the repo if easier. Let me know.
main.py
import controller
import dialogs
import wx.adv
import os
import csv
import wx
from ObjectListView import ObjectListView, ColumnDefn
from wx.lib.wordwrap import wordwrap
# ─────────────────────────────────────────────────────────────────────────────
# Modification for Notebook
# ─────────────────────────────────────────────────────────────────────────────
class TabPanel(wx.Panel):
"""
This class is needed to add the tab panels below.
"""
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
class LedgerFrame(wx.Frame):
"""
The top level frame widget with the Program Title, Program Icon, minimize
and maximize buttons, the top file menu, bottom status bar
"""
def __init__(self):
"""Constructor"""
wx.Frame.__init__(
self,
None,
wx.ID_ANY,
"Account Manager",
size = (1200, 600)
)
panel = LedgerPanel(self)
# panel = wx.Panel(self)
icon = wx.Icon('icon/py1.ico', wx.BITMAP_TYPE_ANY)
self.SetIcon(icon)
# Add a Status Bar to the Bottom
statusBar = self.CreateStatusBar()
self.SetSizeHints(1200, 600)
# Center the program window on the screen when first opened.
self.Center()
# ───────────────────────────────────────────────────────────────────────
# Top MenuBar > File > Edit > View > Tools > Help
# ───────────────────────────────────────────────────────────────────────
# First place the MenuBar
file_menu = wx.MenuBar()
# First MenuBar menu File
menu1 = wx.Menu()
file_menu.Append(menu1, "&File")
# File > Open
fileOpen = menu1.Append(wx.ID_ANY, "&Open", "Open File")
self.Bind(wx.EVT_MENU, self.onOpen, fileOpen)
# File > New File
newFile = menu1.Append(wx.ID_ANY, "&New", "New File")
self.Bind(wx.EVT_MENU, self.onNew, newFile)
# File > Save File
onSave = menu1.Append(wx.ID_ANY, "&Save", "Save File")
self.Bind(wx.EVT_MENU, self.onSave, onSave)
menu1.AppendSeparator() # Thin line separator
# File > Exit (Closes the Program)
fileExit = menu1.Append(wx.ID_ANY, "&Exit", "Exit File")
menu1.Bind(wx.EVT_MENU, self.onQuit, fileExit)
# ───────────────────────────────────────────────────────────────────────
# Edit Menu
# ───────────────────────────────────────────────────────────────────────
menu2 = wx.Menu()
# Edit Menu
file_menu.Append(menu2, "&Edit") # Main header "Edit" added last
# Binding here
# Edit > Copy
menu2.Append(wx.ID_ANY, "&Copy", "Copy")
# Binding here
# Edit > Cut
menu2.Append(wx.ID_ANY, "&Cut", "Cut")
# Binding here
# Edit > Paste
menu2.Append(wx.ID_ANY, "Paste", "Paste")
# Binding here
menu2.AppendSeparator()
# Edit > Options
menu2.Append(wx.ID_ANY, "&Options...", "Display Options")
# Binding here
# ───────────────────────────────────────────────────────────────────────
# View Menu
# ───────────────────────────────────────────────────────────────────────
menu3 = wx.Menu()
# View
file_menu.Append(menu3, "&View") # Main header "View" added last
menu3.Append(wx.ID_ANY, "&Ledger", "Copy")
# Binding Here
menu3.Append(wx.ID_ANY, "&Budget Items", "Cut")
# Binding Here
menu3.Append(wx.ID_ANY, "&Accounts", "Cut")
# Binding Here
menu3.Append(wx.ID_ANY, "&Other", "Paste")
# Binding Here
# ───────────────────────────────────────────────────────────────────────
# Export Menu
# ───────────────────────────────────────────────────────────────────────
menu4 = wx.Menu()
# Add Export Menu
file_menu.Append(menu4, "&Export") # Main header "Tools" added last
# Tools > Export Menu
exportFile = menu4.Append(wx.ID_ANY, "&Export Ledger", "Export Ledger")
# Export Binding Here
self.Bind(wx.EVT_MENU, self.onExport, exportFile)
menu4.Append(wx.ID_ANY, "&Import Database", "Import Ledger")
# Import Binding Here
menu4.Append(wx.ID_ANY, "Paste", "Paste")
# ───────────────────────────────────────────────────────────────────────
# Help Menu
# ───────────────────────────────────────────────────────────────────────
menu5 = wx.Menu()
file_menu.Append(menu5, "&Help") # Main header "Edit" added last
menu5.Append(wx.ID_ANY, "&Copy", "Copy")
menu5.Append(wx.ID_ANY, "&Cut", "Cut")
menu5.Append(wx.ID_ANY, "Paste", "Paste")
# Separator
menu5.AppendSeparator()
aboutModal = menu5.Append(wx.ID_ANY, "&About...", "About")
menu5.Bind(wx.EVT_MENU, self.onAbout, aboutModal)
self.SetMenuBar(file_menu)
self.Show()
# ───────────────────────────────────────────────────────────────────────
def onOpen(self, event):
wx.MessageBox("onOpen event triggered, now add your code ...")
# ───────────────────────────────────────────────────────────────────────
def onNew(self, event):
wx.MessageBox("onNew event triggered, now add your code ...")
# ───────────────────────────────────────────────────────────────────────
def onSave(self, event):
wx.MessageBox("onSave event triggered, now add your code ...")
# ───────────────────────────────────────────────────────────────────────
def onQuit(self, event):
self.Close()
# ───────────────────────────────────────────────────────────────────────
def onAbout(self, event):
info = wx.adv.AboutDialogInfo()
info.Name = "DataBase Front End"
info.Version = " v1.0"
info.Copyright = "(c) 2023"
info.Description = wordwrap(
"The \"DataBase Editor\" front end for an SQL DataBase "
"\nPut some more text here ...",
350, wx.ClientDC(self))
info.WebSite = ("http://en.wikipedia.org/wiki/Hello_world", "Hello World home page")
info.Developers = ["Barny Rubble",
"Fred Flintstone"]
licenseText = "blah " * 250 + "\n\n" + "yadda " * 100
# ClientDC
info.License = wordwrap(licenseText, 500, wx.ClientDC(self))
# Then we call wx.AboutBox giving it that info object
wx.adv.AboutBox(info)
# ─────────────────────────────────────────────────────────────────────────────
# Export Ledger to CSV. Exports everything mapped below.
# @ add the ability to choose what fields you want to export.
# ─────────────────────────────────────────────────────────────────────────────
def onExport(self, event):
# wx.MessageBox("onExport event triggered, now add your code ...")
self.session = controller.connect_to_database()
self.ledger_results = controller.get_all_records(self.session)
# get all ledger items.
records = self.ledger_results
print("\nwxAccMan.py > Ledger Results")
for record in records:
print(f"Export Records: {record.id}, {record.itemDate}, {record.description}")
# Create csv writer
with open('export.csv', 'w', newline='') as csvfile:
csv_writer = csv.writer(csvfile)
#Column headings for CSV
csv_writer.writerow(
['Date',
'Description',
'Budget Item',
'Credit',
'Debit',
'Balance'
])
# model fields, must be the correctly spelled field in models.py
for record in records:
csv_writer.writerow([
record.itemDate,
record.description,
record.budgetItem,
record.credit,
record.debit,
record.balance,
])
return csvfile
# ───── BookFrame Class End ───── #
# ─────────────────────────────────────────────────────────────────────────────
# BookPanel Class > holds the list display. Frame is the parent.
# ─────────────────────────────────────────────────────────────────────────────
class LedgerPanel(wx.Panel):
"""
The main display of the UI. Displaying the db records. Checks to see if db
is present, if not it's created.
Search By: drop down, search text box.
The 4 buttons in the bottom middle under the view panel, Add, Edit, Delete
and Show All.
"""
# ─────────────────────────────────────────────────────────────────────────────
# The built-in super() (Python 3) function’s primary purpose in wxPython is
# used for referring to the parent class without actually naming it.
# ─────────────────────────────────────────────────────────────────────────────
def __init__(self, parent):
super().__init__(parent)
# ─────────────────────────────────────────────────────────────────────
# NoteBook
# ─────────────────────────────────────────────────────────────────────
# Items we wish to put in the Notebook must be a children of the Notebook
# panel = LedgerPanel(self)
panel = wx.Panel(self)
notebook = wx.Notebook(panel, style=wx.NB_TOP)
tabOne = TabPanel(notebook)
notebook.AddPage(tabOne, 'tabOne')
tabOne.SetBackgroundColour((255, 255, 255))
tabTwo = TabPanel(notebook)
notebook.AddPage(tabTwo, 'TabTwo')
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5)
panel.SetSizer(sizer)
self.Show()
if not os.path.exists("wxAccMan.db"):
controller.setup_database()
self.session = controller.connect_to_database()
try:
self.ledger_results = controller.get_all_records(self.session)
records = self.ledger_results
for record in records:
# print(f"Records: {record.itemDate}")
print(f"Record: {record.itemDate}, {record.description}")
# print(f"Ledger Results {self.ledger_results}")
# print("wxAccMan.py > Ledger Results")
except:
self.ledger_results = []
# Search widgets sizers
main_sizer = wx.BoxSizer(wx.VERTICAL)
search_sizer = wx.BoxSizer(wx.HORIZONTAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD)
# create the search related widgets
categories = ["Budget Item", "Date", "Credit", "Balance"]
search_label = wx.StaticText(tabOne, label="Search By:")
search_label.SetFont(font)
search_sizer.Add(search_label, 0, wx.ALL, 5)
# Categories Choices and sizer
self.categories = wx.ComboBox(tabOne, value="Budget Item", choices=categories)
search_sizer.Add(self.categories, 0, wx.ALL, 5)
# self.search_ctrl = wx.SearchCtrl(self, style=wx.TE_PROCESS_ENTER)
self.search_ctrl = wx.TextCtrl(tabOne, style=wx.TE_PROCESS_ENTER)
self.search_ctrl.Bind(wx.EVT_TEXT_ENTER, self.search)
search_sizer.Add(self.search_ctrl, 0, wx.ALL, 5)
self.ledger_results_olv = ObjectListView(tabOne,
style=wx.LC_REPORT | wx.SUNKEN_BORDER)
self.ledger_results_olv.evenRowsBackColor = wx.Colour(230, 230, 230)
self.ledger_results_olv.oddRowsBackColor = wx.Colour(250, 250, 250)
self.ledger_results_olv.SetEmptyListMsg("No Records Found")
self.update_ledger_results()
add_record_btn = wx.Button(tabOne, label="Add")
add_record_btn.Bind(wx.EVT_BUTTON, self.add_record)
btn_sizer.Add(add_record_btn, 0, wx.ALL, 5)
# ─────────────────────────────────────────────────────────────────────────────
# Edit Record
edit_record_btn = wx.Button(tabOne, label="Edit")
edit_record_btn.Bind(wx.EVT_BUTTON, self.edit_record)
btn_sizer.Add(edit_record_btn, 0, wx.ALL, 5)
# ─────────────────────────────────────────────────────────────────────────────
# Delete Record
delete_record_btn = wx.Button(tabOne, label="Delete")
delete_record_btn.Bind(wx.EVT_BUTTON, self.delete_record)
btn_sizer.Add(delete_record_btn, 0, wx.ALL, 5)
# ─────────────────────────────────────────────────────────────────────────────
# Show All
show_all_btn = wx.Button(tabOne, label="Show All")
show_all_btn.Bind(wx.EVT_BUTTON, self.on_show_all)
btn_sizer.Add(show_all_btn, 0, wx.ALL, 5)
# ─────────────────────────────────────────────────────────────────────────────
# Add search to main sizer
main_sizer.Add(search_sizer)
main_sizer.Add(self.ledger_results_olv, 1, wx.ALL|wx.EXPAND, 5)
main_sizer.Add(btn_sizer, 0, wx.CENTER)
self.SetSizer(main_sizer)
self.Show()
# ─────────────────────────────────────────────────────────────────────────────
def add_record(self, event):
"""
Add a record to the database
"""
os.system('cls')
print("ADD Record Button Clicked...")
with dialogs.RecordDialog(self.session) as dlg:
dlg.ShowModal()
self.show_all_records()
# ─────────────────────────────────────────────────────────────────────────────
def edit_record(self, event):
"""
Edit a record
"""
selected_row = self.ledger_results_olv.GetSelectedObject()
if selected_row is None:
dialogs.show_message('No row selected!', 'Error')
return
with dialogs.RecordDialog(self.session,
selected_row,
title='Modify',
addRecord=False) as dlg:
dlg.ShowModal()
self.show_all_records()
# ─────────────────────────────────────────────────────────────────────────────
def delete_record(self, event):
"""
Delete a record
"""
selected_row = self.ledger_results_olv.GetSelectedObject()
if selected_row is None:
dialogs.show_message('No row selected!', 'Error')
return
controller.delete_record(self.session, selected_row.id)
self.show_all_records()
# Called each time a change is made and the display is updated
def show_all_records(self):
"""
Updates the record list to show all of them
"""
self.ledger_results = controller.get_all_records(self.session)
self.update_ledger_results()
# ─────────────────────────────────────────────────────────────────────────────
def search(self, event):
"""
Searches database based on the user's filter
choice and keyword
"""
filter_choice = self.categories.GetValue()
keyword = self.search_ctrl.GetValue()
self.ledger_results = controller.search_records(self.session,
filter_choice, keyword)
self.update_ledger_results()
# ─────────────────────────────────────────────────────────────────────────────
def on_show_all(self, event):
"""
Updates the record list to show all the records
"""
self.show_all_records()
# ─────────────────────────────────────────────────────────────────────────────
def update_ledger_results(self):
"""
Updates the ObjectListView's properties
https://objectlistview-python-edition.readthedocs.io/en/latest/gettingStarted.html
"""
# Show the column headers
# self.book_results_olv.CreateCheckStateColumn()
self.ledger_results_olv.SetColumns([
# Mapped to model.py
ColumnDefn("Date", "left", 150, "itemDate"),
ColumnDefn("Description", "left", 350, "description"),
ColumnDefn("Budget Item", "left", 200, "budgetItem"),
ColumnDefn("Credit", "left", 100, "credit"),
ColumnDefn("Debit", "left", 100, "debit"),
ColumnDefn("Balance", "left", 100, "balance"),
])
# Puts a checkbox column at the first position in the view.
# the call must be placed after SetColumns()
self.ledger_results_olv.CreateCheckStateColumn()
self.ledger_results_olv.SetObjects(self.ledger_results)
# ───── BookPanel Class End ───── #
if __name__ == "__main__":
app = wx.App(False)
frame = LedgerFrame()
app.MainLoop()
# ─────────────────────────────────── Σ ───────────────────────────────────────
Controller
# ─────────────────────────────────────────────────────────────────────────────
from model import Ledger, OlvLedger
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# ─────────────────────────────────────────────────────────────────────────────
def add_record(session, data):
""""""
ledger = Ledger()
ledger.itemDate = data["ledger"]["itemDate"]
ledger.description = data["ledger"]["description"]
ledger.budgetItem = data["ledger"]["budgetItem"]
ledger.credit = data["ledger"]["credit"]
ledger.debit = data["ledger"]["debit"]
ledger.balance = data["ledger"]["balance"]
print(ledger)
session.add(ledger)
session.commit()
def connect_to_database():
""""""
engine = create_engine("sqlite:///test.db", echo=True)
Session = sessionmaker(bind=engine)
session = Session()
return session
def convert_results(results):
""""""
print(f" Contorller.py convert_results: {results}")
ledgerItems = []
for record in results:
ledger = OlvLedger(record.id, record.itemDate,
record.description, record.budgetItem,
record.credit, record.debit, record.balance
)
ledger.append(ledgerItems)
print(f"convert_results: {ledgerItems}")
return ledgerItems
def delete_record(session, id_num):
"""
Delete a record from the database
"""
record = session.query(Ledger).filter_by(id=id_num).one()
session.delete(record)
session.commit()
# ─────────────────────────────────────────────────────────────────────────────
# look up db row id to edit.
# ─────────────────────────────────────────────────────────────────────────────
def edit_record(session, id_num, row):
"""
Edit a record
"""
record = session.query(Ledger).filter_by(id=id_num).one()
record.itemDate = row["itemDate"]
record.description = row["description"]
record.budgetItem = row["budgetItem"]
record.credit = row["credit"]
record.debit = row["debit"]
record.balance = row["balance"]
session.add(record)
session.commit()
def get_all_records(session):
"""
Get all records and return them
"""
# Get all records in db
result = session.query(Ledger).all()
# Pass all records to convert.
# ledgerItems = convert_results(result)
# return ledgerItems
return result
# ─────────────────────────────────────────────────────────────────────────────
def search_records(session, filter_choice, keyword):
"""
Searches the database based on the filter chosen and the keyword
given by the user
"""
if filter_choice == "Budget Item":
qry = session.query(Ledger)
result = qry.filter(Ledger.budgetItem.contains('%s' % keyword)).all()
records = []
for record in result:
for record in record.LedgerItems:
records.append()
result = records
elif filter_choice == "Date":
qry = session.query(Ledger)
result = qry.filter(Ledger.itemDate.contains('%s' % keyword)).all()
else:
qry = session.query(Ledger)
result = qry.filter(Ledger.debit.contains('%s' % keyword)).all()
results = convert_results(result)
return results
def setup_database():
""""""
metadata.create_all()
# ─────────────────────────────────── Σ ───────────────────────────────────────
dialogs
import controller
import wx
# ─────────────────────────────────────────────────────────────────────────────
class RecordDialog(wx.Dialog):
"""
Add / Modify Record dialog
"""
def __init__(self, session, row=None, title="Add", addRecord=True):
"""Constructor"""
super().__init__(None, title="%s Record" % title)
self.addRecord = addRecord
self.selected_row = row
self.session = session
if row:
itemDate = self.selected_row.itemDate
description = self.selected_row.description
budgetItem = self.selected_row.budgetItem
credit = self.selected_row.credit
debit = self.selected_row.debit
balance = self.selected_row.balance
else:
itemDate = description = budgetItem = credit = debit = balance = ""
# Sizers
main_sizer = wx.BoxSizer(wx.VERTICAL)
btn_sizer = wx.BoxSizer(wx.HORIZONTAL)
# Pop up Dialog size and font variables
size = (200, -1)
font = wx.Font(10, wx.SWISS, wx.NORMAL, wx.BOLD)
# Date
date_lbl = wx.StaticText(self, label="Date:", size=size)
# date_lbl = wx.DateTime(self, label="Date:", size=size)
date_lbl.SetFont(font)
# value comes from the if statement above.
self.date_txt = wx.TextCtrl(self, value=itemDate, size=(110, -1))
# self.date_txt = wx.adv.DatePickerCtrl(self, style = wx.adv.DP_SPIN)
# self.date_txt = wx.adv.DatePickerCtrl(self, style = wx.adv.DP_DROPDOWN)
main_sizer.Add(self.row_builder([date_lbl, self.date_txt]),
0, wx.ALL)
# ─────────────────────────────────────────────────────────────────────────────
# Description
description_lbl = wx.StaticText(self, label="Description:", size=size)
description_lbl.SetFont(font)
self.description_txt = wx.TextCtrl(self, value=description,
size=(300, -1))
main_sizer.Add(self.row_builder([description_lbl, self.description_txt]),
0, wx.ALL)
# Budget Item > Move this to a table.
budgetItem_lbl = wx.StaticText(self, label="Budget Item:", size=size)
budgetItem_lbl.SetFont(font)
self.budgetItem_txt = wx.ComboBox(self, size=size, value=budgetItem,
choices=["AAA Registration Fee",
"Administration",
"Apparel",
"Athletic Therapist",
"Banking Fee's",
"Bus (Playoffs)",
"Bus (Tournament)",
"Cash Calendars",
"Checks",
"Deposit",
"Expense Reimbursement",
"Fundraising",
"Game Ice (Regular Season)",
"Game Officials (Playoffs)",
"Game Officials (Regular Season)",
"Gate Profit (Playoffs)",
"Gate Profit (Regular Season)",
"Goal Tending Coach",
"Hotels (Playoffs)",
"Hotels (Regular Season)",
"Hotels (Tournaments)",
"League Fee's",
"Meals (Playoffs)",
"Meals (Regular Season)",
"Meals (Tournaments)",
"Medical Supplies",
"Misc.",
"Misc. (Tournament)",
"MMHL Playoff Assessments",
"Other Income",
"Player Fees",
"Playoff Game Ice",
"Practice Ice (Playoffs)",
"Practice Ice (Regular Season)",
"Practice Jerseys/Socks",
"Pre-Season",
"Team Sponsorships",
"Team Supplies",
"Tournament Fees",
"Tournament",
"Tournament Flights",
"50/50 (Playoffs)",
"50/50 (Regular Season)",
])
main_sizer.Add(self.row_builder([budgetItem_lbl, self.budgetItem_txt]),
0, wx.ALL)
# ─────────────────────────────────────────────────────────────────────────────
# Credit
credit_lbl = wx.StaticText(self, label="Credit:", size=size)
credit_lbl.SetFont(font)
self.credit_txt = wx.TextCtrl(self, value=credit)
main_sizer.Add(self.row_builder([credit_lbl, self.credit_txt]),
0, wx.ALL)
# ─────────────────────────────────────────────────────────────────────────────
#Debit
debit_lbl = wx.StaticText(self, label="Debit:", size=size)
debit_lbl.SetFont(font)
self.debit_txt = wx.TextCtrl(self, value=debit)
main_sizer.Add(self.row_builder([debit_lbl, self.debit_txt]),
0, wx.ALL)
# ─────────────────────────────────────────────────────────────────────────────
# Balance
balance_lbl = wx.StaticText(self, label="Balance:", size=size)
balance_lbl.SetFont(font)
self.balance_txt = wx.TextCtrl(self, value=balance)
main_sizer.Add(self.row_builder([balance_lbl, self.balance_txt]),
0, wx.ALL)
# ─────────────────────────────────────────────────────────────────────────────
# Add Record Button bound to on_record()
ok_btn = wx.Button(self, label="%s Record" % title)
ok_btn.Bind(wx.EVT_BUTTON, self.on_record)
btn_sizer.Add(ok_btn, 0, wx.ALL, 5)
# Close Button
cancel_btn = wx.Button(self, label="Close")
cancel_btn.Bind(wx.EVT_BUTTON, self.on_close)
btn_sizer.Add(cancel_btn, 0, wx.ALL, 5)
main_sizer.Add(btn_sizer, 0, wx.CENTER)
self.SetSizerAndFit(main_sizer)
def get_data(self):
"""
Gets the data from the widgets in the dialog
Also display an error message if required fields
are empty
"""
ledger_dict = {}
# Get the user entered text and store it in each variable.
itemDate = self.date_txt.GetValue()
description = self.description_txt.GetValue()
budgetItem = self.budgetItem_txt.GetValue()
credit = self.credit_txt.GetValue()
debit = self.debit_txt.GetValue()
balance = self.balance_txt.GetValue()
# Add the user entered data to ledger_dict.
ledger_dict["itemDate"] = itemDate
ledger_dict["description"] = description
ledger_dict["budgetItem"] = budgetItem
ledger_dict["credit"] = credit
ledger_dict["debit"] = debit
ledger_dict["balance"] = balance
# if itemDate == "":
# show_message("Date is required !",
# "Error")
# return None
return ledger_dict
def on_add(self):
"""
Add the record to the database
"""
ledger_dict = self.get_data()
if ledger_dict is None:
print("Nothing in get_data")
return
data = ({"ledger":ledger_dict})
controller.add_record(self.session, data)
print(f'on_add > {ledger_dict}')
# show dialog upon completion
show_message("Ledger Item Added",
"Success!", wx.ICON_INFORMATION)
# clear dialog so we can add another record
for child in self.GetChildren():
if isinstance(child, wx.TextCtrl):
child.SetValue("")
# ─────────────────────────────────────────────────────────────────────────────
def on_close(self, event):
"""
Close the dialog
"""
self.Close()
# ─────────────────────────────────────────────────────────────────────────────
def on_edit(self):
"""
Edit a record in the database
"""
ledger_dict = self.get_data()
controller.edit_record(self.session, self.selected_row.id, ledger_dict)
show_message("Ledger Edited Successfully!", "Success",
wx.ICON_INFORMATION)
self.Close()
# ─────────────────────────────────────────────────────────────────────────────
# Bound to Add and Edit Buttons > append
def on_record(self, event):
"""
Add or edit a record
"""
if self.addRecord:
self.on_add()
else:
self.on_edit()
self.date_txt.SetFocus()
# ─────────────────────────────────────────────────────────────────────────────
# Build a row of widgets.
# ─────────────────────────────────────────────────────────────────────────────
def row_builder(self, widgets):
"""
Helper function for building a row of widgets
"""
sizer = wx.BoxSizer(wx.HORIZONTAL)
lbl, txt = widgets
# txt = widgets
sizer.Add(lbl, 0, wx.ALL, 5)
sizer.Add(txt, 1, wx.ALL, 5)
return sizer
# ─────────────────────────────────────────────────────────────────────────────
# End of Class RecordDialog(wx.Dialog)
# ─────────────────────────────────────────────────────────────────────────────
# Called when required information is missing
# ─────────────────────────────────────────────────────────────────────────────
def show_message(message, caption, flag=wx.ICON_ERROR):
"""
Show a message dialog
"""
msg = wx.MessageDialog(None, message=message,
caption=caption, style=flag)
msg.ShowModal()
msg.Destroy()
if __name__ == "__main__":
app = wx.App(False)
dlg = RecordDialog(session=None)
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()
model
from sqlalchemy import Table, Column, create_engine
from sqlalchemy import Integer, ForeignKey, Date, String, Unicode, CHAR
import re
# from sqlalchemy.dialects.sqlite import DATE
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import backref, relation, sessionmaker
from datetime import date
# ─────────────────────────────────────────────────────────────────────────────
# disable echo=True for release. echo=True sends the SQL commands to stdout so
# you can see what's happening. Not needed for a final product.
engine = create_engine("sqlite:///test.db", echo=True)
Base = declarative_base()
metadata = Base.metadata
print(engine.table_names())
class OlvLedger(object):
"""
Ledger model (Object) for ObjectListView in main
"""
def __init__(self, id, itemDate, description, budgetItem, credit,
debit, balance):
self.id = id # unique row id from database
self.ItemDate = itemDate
self.description = description
self.budgetItem = budgetItem
self.credit = credit
self.debit = debit
self.balance = balance
class Ledger(Base):
""""""
__tablename__ = "ledger"
id = Column(Integer, primary_key=True)
itemDate = Column("Date", CHAR)
description = Column("Description", CHAR)
budgetItem = Column("Budget Item", CHAR)
credit = Column("Credit", CHAR)
debit = Column("Debit", CHAR)
balance = Column("Balance", CHAR)
metadata.create_all(engine)
# ─────────────────────────────────── Σ ───────────────────────────────────────