Change the way the ui file is processed
This commit is contained in:
parent
5e78751921
commit
1bf13e77e3
@ -1,118 +0,0 @@
|
|||||||
import sys
|
|
||||||
import typing
|
|
||||||
|
|
||||||
import pandas as pd
|
|
||||||
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, \
|
|
||||||
QListView, QTableView
|
|
||||||
from PyQt5 import uic, QtGui, QtCore
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class PandasModel(QtCore.QAbstractTableModel):
|
|
||||||
def __init__(self, df: pd.DataFrame, parent=None):
|
|
||||||
QtCore.QAbstractTableModel.__init__(self, parent)
|
|
||||||
self._data = df
|
|
||||||
|
|
||||||
self.horizontalHeaders = [''] * len(df.columns)
|
|
||||||
|
|
||||||
for i, column in enumerate(df.columns):
|
|
||||||
self.setHeaderData(i, QtCore.Qt.Horizontal, column)
|
|
||||||
|
|
||||||
def setHeaderData(self, section, orientation, data,
|
|
||||||
role=QtCore.Qt.EditRole):
|
|
||||||
if orientation == QtCore.Qt.Horizontal and role in (
|
|
||||||
QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
|
|
||||||
try:
|
|
||||||
self.horizontalHeaders[section] = data
|
|
||||||
return True
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
return super().setHeaderData(section, orientation, data, role)
|
|
||||||
|
|
||||||
def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
|
|
||||||
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
|
|
||||||
try:
|
|
||||||
return self.horizontalHeaders[section]
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return super().headerData(section, orientation, role)
|
|
||||||
|
|
||||||
def rowCount(self, parent=None):
|
|
||||||
return len(self._data.values)
|
|
||||||
|
|
||||||
def columnCount(self, parent=None):
|
|
||||||
return self._data.columns.size
|
|
||||||
|
|
||||||
def data(self, index, role=QtCore.Qt.DisplayRole):
|
|
||||||
if index.isValid():
|
|
||||||
if role == QtCore.Qt.DisplayRole:
|
|
||||||
item = self._data.iloc[index.row()].iloc[index.column()]
|
|
||||||
|
|
||||||
if type(item) is pd.Timestamp:
|
|
||||||
return QtCore.QVariant(item.strftime('%Y-%m-%d'))
|
|
||||||
else:
|
|
||||||
return QtCore.QVariant(str(item))
|
|
||||||
return QtCore.QVariant()
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
|
||||||
def __init__(self, ui_file: str, categories: typing.Sequence):
|
|
||||||
super(MainWindow, self).__init__()
|
|
||||||
uic.loadUi(ui_file, self)
|
|
||||||
|
|
||||||
self._createCategoryButton \
|
|
||||||
= self.findChild(QPushButton, "createCategoryButton")
|
|
||||||
self._deleteCategoryButton \
|
|
||||||
= self.findChild(QPushButton, "deleteCategoryButton")
|
|
||||||
self._applyCategoryButton \
|
|
||||||
= self.findChild(QPushButton, "applyCategoryButton")
|
|
||||||
|
|
||||||
self._categoryListView = self.findChild(QListView, "categoryListView")
|
|
||||||
self._statementTableView = self.findChild(QTableView,
|
|
||||||
"statementTableView")
|
|
||||||
|
|
||||||
self._set_categories(categories)
|
|
||||||
|
|
||||||
self._statementTableView.setSelectionBehavior(QTableView.SelectRows)
|
|
||||||
|
|
||||||
def _set_categories(self, categories: typing.Sequence[str]):
|
|
||||||
model = QtGui.QStandardItemModel()
|
|
||||||
self._categoryListView.setModel(model)
|
|
||||||
|
|
||||||
for category in categories:
|
|
||||||
item = QtGui.QStandardItem(category)
|
|
||||||
model.appendRow(item)
|
|
||||||
|
|
||||||
def set_statement_data(self, df: pd.DataFrame):
|
|
||||||
model = PandasModel(df)
|
|
||||||
self._statementTableView.setModel(model)
|
|
||||||
|
|
||||||
|
|
||||||
def show_main_window(ui_file, categories: typing.Sequence[str] = None,
|
|
||||||
df: pd.DataFrame = None):
|
|
||||||
if categories is None:
|
|
||||||
categories = []
|
|
||||||
|
|
||||||
app = QApplication(sys.argv)
|
|
||||||
window = MainWindow(ui_file, categories)
|
|
||||||
|
|
||||||
if df is not None:
|
|
||||||
window.set_statement_data(df)
|
|
||||||
|
|
||||||
window.show()
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
from banking_breakdown.statement_parser import get_stripped_statement
|
|
||||||
|
|
||||||
categories = ["Food", "Rent & Utilities", "Hobbies", "Education",
|
|
||||||
"Transportation", "Social Life", "Other"]
|
|
||||||
|
|
||||||
df = get_stripped_statement("../res/banking_statement_2023.csv")
|
|
||||||
|
|
||||||
show_main_window("../res/main_window.ui", categories, df)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
37
banking_breakdown/ui/__init__.py
Normal file
37
banking_breakdown/ui/__init__.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import sys
|
||||||
|
import typing
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from PyQt6.QtWidgets import QApplication
|
||||||
|
|
||||||
|
from banking_breakdown.ui.generated_wrapper import GeneratedWindowWrapper
|
||||||
|
|
||||||
|
|
||||||
|
def show_main_window(ui_file, categories: typing.Sequence[str] = None,
|
||||||
|
df: pd.DataFrame = None):
|
||||||
|
if categories is None:
|
||||||
|
categories = []
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
window = GeneratedWindowWrapper(ui_file, categories)
|
||||||
|
|
||||||
|
if df is not None:
|
||||||
|
window.set_statement_data(df)
|
||||||
|
|
||||||
|
window.show()
|
||||||
|
app.exec()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
from banking_breakdown.statement_parser import get_stripped_statement
|
||||||
|
|
||||||
|
categories = ["Food", "Rent & Utilities", "Hobbies", "Education",
|
||||||
|
"Transportation", "Social Life", "Other"]
|
||||||
|
|
||||||
|
df = get_stripped_statement("../../res/banking_statement_2023.csv")
|
||||||
|
|
||||||
|
show_main_window("../../res/main_window.ui", categories, df)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
74
banking_breakdown/ui/generated.py
Normal file
74
banking_breakdown/ui/generated.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Form implementation generated from reading ui file 'main_window.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt6 UI code generator 6.6.1
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_MainWindow(object):
|
||||||
|
def setupUi(self, MainWindow):
|
||||||
|
MainWindow.setObjectName("MainWindow")
|
||||||
|
MainWindow.resize(800, 600)
|
||||||
|
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
|
||||||
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
|
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||||
|
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||||
|
self.groupBox = QtWidgets.QGroupBox(parent=self.centralwidget)
|
||||||
|
self.groupBox.setObjectName("groupBox")
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox)
|
||||||
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.createCategoryButton = QtWidgets.QPushButton(parent=self.groupBox)
|
||||||
|
self.createCategoryButton.setObjectName("createCategoryButton")
|
||||||
|
self.horizontalLayout.addWidget(self.createCategoryButton)
|
||||||
|
self.deleteCategoryButton = QtWidgets.QPushButton(parent=self.groupBox)
|
||||||
|
self.deleteCategoryButton.setObjectName("deleteCategoryButton")
|
||||||
|
self.horizontalLayout.addWidget(self.deleteCategoryButton)
|
||||||
|
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||||
|
self.categoryListView = QtWidgets.QListView(parent=self.groupBox)
|
||||||
|
self.categoryListView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.SizeAdjustPolicy.AdjustToContents)
|
||||||
|
self.categoryListView.setObjectName("categoryListView")
|
||||||
|
self.verticalLayout_2.addWidget(self.categoryListView)
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
|
self.horizontalLayout_2.addItem(spacerItem)
|
||||||
|
self.applyCategoryButton = QtWidgets.QPushButton(parent=self.groupBox)
|
||||||
|
self.applyCategoryButton.setObjectName("applyCategoryButton")
|
||||||
|
self.horizontalLayout_2.addWidget(self.applyCategoryButton)
|
||||||
|
self.verticalLayout_2.addLayout(self.horizontalLayout_2)
|
||||||
|
self.horizontalLayout_3.addWidget(self.groupBox)
|
||||||
|
self.groupBox_2 = QtWidgets.QGroupBox(parent=self.centralwidget)
|
||||||
|
self.groupBox_2.setObjectName("groupBox_2")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_2)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.statementTableView = QtWidgets.QTableView(parent=self.groupBox_2)
|
||||||
|
self.statementTableView.setObjectName("statementTableView")
|
||||||
|
self.verticalLayout.addWidget(self.statementTableView)
|
||||||
|
self.horizontalLayout_3.addWidget(self.groupBox_2)
|
||||||
|
self.horizontalLayout_3.setStretch(1, 1)
|
||||||
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
|
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
|
||||||
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
|
||||||
|
self.menubar.setObjectName("menubar")
|
||||||
|
MainWindow.setMenuBar(self.menubar)
|
||||||
|
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
|
||||||
|
self.statusbar.setObjectName("statusbar")
|
||||||
|
MainWindow.setStatusBar(self.statusbar)
|
||||||
|
|
||||||
|
self.retranslateUi(MainWindow)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||||
|
|
||||||
|
def retranslateUi(self, MainWindow):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||||
|
self.groupBox.setTitle(_translate("MainWindow", "Categories"))
|
||||||
|
self.createCategoryButton.setText(_translate("MainWindow", "Create"))
|
||||||
|
self.deleteCategoryButton.setText(_translate("MainWindow", "Delete"))
|
||||||
|
self.applyCategoryButton.setText(_translate("MainWindow", "Apply"))
|
||||||
|
self.groupBox_2.setTitle(_translate("MainWindow", "Bank statement"))
|
||||||
87
banking_breakdown/ui/generated_wrapper.py
Normal file
87
banking_breakdown/ui/generated_wrapper.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import typing
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
from PyQt6.QtWidgets import QMainWindow, QTableView
|
||||||
|
from PyQt6 import uic, QtGui, QtCore
|
||||||
|
from PyQt6.QtCore import Qt
|
||||||
|
|
||||||
|
from banking_breakdown.ui.generated import Ui_MainWindow
|
||||||
|
|
||||||
|
|
||||||
|
class PandasModel(QtCore.QAbstractTableModel):
|
||||||
|
def __init__(self, df: pd.DataFrame, parent=None):
|
||||||
|
QtCore.QAbstractTableModel.__init__(self, parent)
|
||||||
|
self._data = df
|
||||||
|
|
||||||
|
self._horizontalHeaders = [''] * len(df.columns)
|
||||||
|
|
||||||
|
for i, column in enumerate(df.columns):
|
||||||
|
self.setHeaderData(i, Qt.Orientation.Horizontal, column)
|
||||||
|
|
||||||
|
def setHeaderData(self, section, orientation, data,
|
||||||
|
role=Qt.ItemDataRole.EditRole):
|
||||||
|
|
||||||
|
if ((orientation == Qt.Orientation.Horizontal)
|
||||||
|
and ((role == Qt.ItemDataRole.DisplayRole)
|
||||||
|
or (role == Qt.ItemDataRole.EditRole))):
|
||||||
|
|
||||||
|
self._horizontalHeaders[section] = data
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return super().setHeaderData(section, orientation, data, role)
|
||||||
|
|
||||||
|
def headerData(self, section, orientation,
|
||||||
|
role=Qt.ItemDataRole.DisplayRole):
|
||||||
|
|
||||||
|
if (orientation == Qt.Orientation.Horizontal
|
||||||
|
and role == Qt.ItemDataRole.DisplayRole):
|
||||||
|
|
||||||
|
return self._horizontalHeaders[section]
|
||||||
|
else:
|
||||||
|
return super().headerData(section, orientation, role)
|
||||||
|
|
||||||
|
def rowCount(self, parent=None):
|
||||||
|
return len(self._data.values)
|
||||||
|
|
||||||
|
def columnCount(self, parent=None):
|
||||||
|
return self._data.columns.size
|
||||||
|
|
||||||
|
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
|
||||||
|
if not index.isValid():
|
||||||
|
return QtCore.QVariant()
|
||||||
|
if role != Qt.ItemDataRole.DisplayRole:
|
||||||
|
return QtCore.QVariant()
|
||||||
|
|
||||||
|
item = self._data.iloc[index.row()].iloc[index.column()]
|
||||||
|
|
||||||
|
if type(item) is pd.Timestamp:
|
||||||
|
return QtCore.QVariant(item.strftime('%Y-%m-%d'))
|
||||||
|
else:
|
||||||
|
return QtCore.QVariant(str(item))
|
||||||
|
|
||||||
|
|
||||||
|
class GeneratedWindowWrapper(QMainWindow):
|
||||||
|
def __init__(self, ui_file: str, categories: typing.Sequence):
|
||||||
|
super(GeneratedWindowWrapper, self).__init__()
|
||||||
|
|
||||||
|
self._window = Ui_MainWindow()
|
||||||
|
self._window.setupUi(self)
|
||||||
|
|
||||||
|
# Set up window
|
||||||
|
|
||||||
|
self._window.statementTableView.setSelectionBehavior(
|
||||||
|
QTableView.SelectionBehavior.SelectRows)
|
||||||
|
|
||||||
|
self._set_categories(categories)
|
||||||
|
|
||||||
|
def _set_categories(self, categories: typing.Sequence[str]):
|
||||||
|
model = QtGui.QStandardItemModel()
|
||||||
|
self._window.categoryListView.setModel(model)
|
||||||
|
|
||||||
|
for category in categories:
|
||||||
|
item = QtGui.QStandardItem(category)
|
||||||
|
model.appendRow(item)
|
||||||
|
|
||||||
|
def set_statement_data(self, df: pd.DataFrame):
|
||||||
|
model = PandasModel(df)
|
||||||
|
self._window.statementTableView.setModel(model)
|
||||||
@ -14,38 +14,15 @@
|
|||||||
<string>MainWindow</string>
|
<string>MainWindow</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Categories</string>
|
<string>Categories</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="createCategoryButton">
|
<widget class="QPushButton" name="createCategoryButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -63,12 +40,16 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListView" name="categoryListView"/>
|
<widget class="QListView" name="categoryListView">
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_2">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -91,17 +72,25 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Bank Statement</string>
|
<string>Bank statement</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="statementTableView"/>
|
<widget class="QTableView" name="statementTableView">
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -114,42 +103,8 @@
|
|||||||
<height>23</height>
|
<height>23</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
|
||||||
<property name="title">
|
|
||||||
<string>File</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionOpen"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="actionSave"/>
|
|
||||||
<addaction name="actionSave_As"/>
|
|
||||||
</widget>
|
|
||||||
<addaction name="menuFile"/>
|
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<action name="actionSave">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+S</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionSave_As">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save As...</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+Shift+S</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionOpen">
|
|
||||||
<property name="text">
|
|
||||||
<string>Open...</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+O</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user