platform edit error checking, more comments, misc other changes

This commit is contained in:
2025-02-10 22:11:57 +00:00
parent 6b4f6bb35f
commit 1748fb849f
6 changed files with 250 additions and 94 deletions

View File

@ -7,6 +7,14 @@ import platform_edit
app = QApplication(sys.argv)
# Show platform edit window first, before main win
window = platform_edit.PlatformEdit()
# When debugging, can be useful to autofill values to save time
if len(sys.argv) > 1:
if sys.argv[1] == "--DEBUG_AUTOFILL":
window = platform_edit.PlatformEdit(True)
else:
window = platform_edit.PlatformEdit(False)
else:
window = platform_edit.PlatformEdit(False)
window.show()
app.exec()

View File

@ -1,3 +1,4 @@
from PyQt6.QtGui import QIntValidator
from PyQt6.QtWidgets import QMainWindow
from PyQt6 import uic
@ -8,9 +9,11 @@ class SIPPCompare(QMainWindow):
# Receive instance of PlatformEdit() as parameter
def __init__(self, plat_edit_win):
super().__init__()
# Import Qt Designer UI XML file
uic.loadUi("gui/main_gui.ui", self)
# Initialise class variables
# Inputs
self.fund_plat_fee = 0.0
self.plat_name = ""
self.fund_deal_fee = 0.0
@ -20,6 +23,7 @@ class SIPPCompare(QMainWindow):
self.share_deal_reduce_trades = 0.0
self.share_deal_reduce_amount = 0.0
# Results
self.fund_plat_fees = 0.0
self.fund_deal_fees = 0.0
self.share_plat_fees = 0.0
@ -31,16 +35,22 @@ class SIPPCompare(QMainWindow):
# Handle events
self.calc_but.clicked.connect(self.calculate_fees)
# Menu bar entry (File -> Edit Platforms)
self.actionEdit_Platforms.triggered.connect(self.show_platform_edit)
# Update percentage mix label when slider moved
self.mix_slider.valueChanged.connect(self.update_slider_lab)
# Set validators
self.share_trades_combo.setValidator(QIntValidator(0, 999))
self.fund_trades_combo.setValidator(QIntValidator(0, 99))
# Display slider position as mix between two nums (funds/shares)
def update_slider_lab(self):
slider_val = self.mix_slider.value()
mix_lab_str = f"Investment mix (funds {slider_val}% / shares {100 - slider_val}%)"
self.mix_lab.setText(mix_lab_str)
# Get local variables from user input
# Get variables from platform editor input fields
def init_variables(self):
self.plat_name = self.platform_win.get_plat_name()
self.fund_plat_fee = self.platform_win.get_fund_plat_fee()
@ -52,15 +62,17 @@ class SIPPCompare(QMainWindow):
self.share_deal_reduce_amount = self.platform_win.get_share_deal_reduce_amount()
# Calculate fees
# TODO: Error checking on combo boxes
def calculate_fees(self):
self.init_variables()
# Set to zero each time to avoid persistence
self.fund_plat_fees = 0
value_num = float(self.value_input.text()[1:]) # Filter out '£' symbol
value_num = float(self.value_input.value())
# Funds/shares mix
slider_val = self.mix_slider.value()
funds_value = (slider_val / 100) * value_num
fund_trades_num = int(self.fund_trades_combo.currentText())
self.fund_deal_fees = fund_trades_num * self.fund_deal_fee
remaining = funds_value
for i in range(1, len(self.fund_plat_fee[0])):
band = self.fund_plat_fee[0][i]
@ -68,11 +80,11 @@ class SIPPCompare(QMainWindow):
fee = self.fund_plat_fee[1][i]
gap = (band - prev_band)
if remaining > gap:
if funds_value > gap:
self.fund_plat_fees += gap * (fee / 100)
remaining -= gap
funds_value -= gap
else:
self.fund_plat_fees += remaining * (fee / 100)
self.fund_plat_fees += funds_value * (fee / 100)
break
shares_value = (1 - (slider_val / 100)) * value_num
@ -93,7 +105,9 @@ class SIPPCompare(QMainWindow):
def show_output_win(self):
# Refresh the results when new fees are calculated
self.output_win.display_output(self.fund_plat_fees, self.fund_deal_fees,
self.share_plat_fees, self.share_deal_fees, self.plat_name)
self.share_plat_fees, self.share_deal_fees,
self.plat_name
)
self.output_win.show()
# Show the platform editor window (currently run-time only)

View File

@ -8,6 +8,7 @@ import os
class OutputWindow(QWidget):
def __init__(self):
super().__init__()
# Import Qt Designer UI XML file
uic.loadUi("gui/output_window.ui", self)
# Initialise class variables

View File

@ -1,3 +1,5 @@
from PyQt6.QtCore import QRegularExpression, QEvent, QObject, QTimer
from PyQt6.QtGui import QRegularExpressionValidator
from PyQt6.QtWidgets import QWidget
from PyQt6 import uic
@ -5,8 +7,9 @@ import main_window
class PlatformEdit(QWidget):
def __init__(self):
def __init__(self, autofill: bool):
super().__init__()
# Import Qt Designer UI XML file
uic.loadUi("gui/platform_edit.ui", self)
# Initialise class variables
@ -22,28 +25,83 @@ class PlatformEdit(QWidget):
self.share_deal_fee = 0.0
self.share_deal_reduce_trades = 0.0
self.share_deal_reduce_amount = 0.0
# Debugging feature: set with "--DEBUG_AUTOFILL" cmd argument
self.autofill = autofill
# Create main window object, passing this instance as param
self.main_win = main_window.SIPPCompare(self)
# Handle events
# NOTE: Signal defined in Qt designer to close window when clicked
# NOTE: Signal defined in UI file to close window when save button clicked
self.save_but.clicked.connect(self.init_variables)
self.fund_deal_fee_box.valueChanged.connect(self.check_valid)
self.share_plat_fee_box.valueChanged.connect(self.check_valid)
self.share_deal_fee_box.valueChanged.connect(self.check_valid)
# Get fee structure variables from user input
# Install event filter on input boxes in order to select all text on focus
self.fund_deal_fee_box.installEventFilter(self)
self.share_plat_fee_box.installEventFilter(self)
self.share_plat_max_fee_box.installEventFilter(self)
self.share_deal_fee_box.installEventFilter(self)
self.share_deal_reduce_trades_box.installEventFilter(self)
self.share_deal_reduce_amount_box.installEventFilter(self)
# Set validators
# Regex accepts any characters that match [a-Z], [0-9] or _
self.plat_name_box.setValidator(
QRegularExpressionValidator(QRegularExpression("\\w*"))
)
# Get fee structure variables from user input when "Save" clicked
def init_variables(self):
self.plat_name = self.plat_name_box.text()
self.fund_deal_fee = float(self.fund_deal_fee_box.text())
self.share_plat_fee = float(self.share_plat_fee_box.text()) / 100
self.share_plat_max_fee = float(self.share_plat_max_fee_box.text())
self.share_deal_fee = float(self.share_deal_fee_box.text())
self.share_deal_reduce_trades = float(self.share_deal_reduce_trades_box.text())
self.share_deal_reduce_amount = float(self.share_deal_reduce_amount_box.text())
# If debugging, save time by hardcoding
if self.autofill:
self.plat_name = "AJBell"
self.fund_deal_fee = 1.50
self.share_plat_fee = 0.0025
self.share_plat_max_fee = 3.50
self.share_deal_fee = 5.00
self.share_deal_reduce_trades = 10
self.share_deal_reduce_amount = 3.50
else:
self.plat_name = self.plat_name_box.text()
self.fund_deal_fee = float(self.fund_deal_fee_box.value())
self.share_plat_fee = float(self.share_plat_fee_box.value()) / 100
self.share_plat_max_fee = float(self.share_plat_max_fee_box.value())
self.share_deal_fee = float(self.share_deal_fee_box.value())
self.share_deal_reduce_trades = float(self.share_deal_reduce_trades_box.value())
self.share_deal_reduce_amount = float(self.share_deal_reduce_amount_box.value())
# Once user input is received show main window
self.main_win.show()
# Getter functions
# When focus is given to an input box, select all text in it (easier to edit)
def eventFilter(self, obj: QObject, event: QEvent):
if event.type() == QEvent.Type.FocusIn:
# Alternative condition for % suffix - currently unused
#if obj.value() == 0 or obj == self.share_plat_fee_box:
QTimer.singleShot(0, obj.selectAll)
return False
# Check if all required fields have valid (non-zero) input
# TODO: Find a better way of doing this if possible
def check_valid(self):
values = [self.fund_deal_fee_box.value(),
self.share_plat_fee_box.value(),
self.share_deal_fee_box.value()
]
valid = True
for value in values:
if value == 0:
valid = False
if valid:
self.save_but.setEnabled(True)
else:
self.save_but.setEnabled(False)
# Getter functions (is this necessary? maybe directly reading class vars would be best...)
def get_plat_name(self):
return self.plat_name