From 1bf13e77e35223d5231e792b811dea99cb362228 Mon Sep 17 00:00:00 2001 From: Andreas Tsouchlos Date: Wed, 3 Jan 2024 15:38:17 +0100 Subject: [PATCH] Change the way the ui file is processed --- banking_breakdown/ui.py | 118 ------------- banking_breakdown/ui/__init__.py | 37 +++++ banking_breakdown/ui/generated.py | 74 +++++++++ banking_breakdown/ui/generated_wrapper.py | 87 ++++++++++ res/main_window.ui | 193 +++++++++------------- 5 files changed, 272 insertions(+), 237 deletions(-) delete mode 100644 banking_breakdown/ui.py create mode 100644 banking_breakdown/ui/__init__.py create mode 100644 banking_breakdown/ui/generated.py create mode 100644 banking_breakdown/ui/generated_wrapper.py diff --git a/banking_breakdown/ui.py b/banking_breakdown/ui.py deleted file mode 100644 index cc167c2..0000000 --- a/banking_breakdown/ui.py +++ /dev/null @@ -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() diff --git a/banking_breakdown/ui/__init__.py b/banking_breakdown/ui/__init__.py new file mode 100644 index 0000000..3b11f61 --- /dev/null +++ b/banking_breakdown/ui/__init__.py @@ -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() diff --git a/banking_breakdown/ui/generated.py b/banking_breakdown/ui/generated.py new file mode 100644 index 0000000..1311a6f --- /dev/null +++ b/banking_breakdown/ui/generated.py @@ -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")) diff --git a/banking_breakdown/ui/generated_wrapper.py b/banking_breakdown/ui/generated_wrapper.py new file mode 100644 index 0000000..c19914a --- /dev/null +++ b/banking_breakdown/ui/generated_wrapper.py @@ -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) diff --git a/res/main_window.ui b/res/main_window.ui index cd803a2..7f80b23 100644 --- a/res/main_window.ui +++ b/res/main_window.ui @@ -14,93 +14,82 @@ MainWindow - + - - - Qt::Horizontal + + + Categories - - - - 0 - 0 - - - - Categories - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Create - - - - - - - Delete - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Apply - - - - - - - - - - Bank Statement - - - - - - - + + + + + + + Create + + + + + + + Delete + + + + + + + + + QAbstractScrollArea::AdjustToContents + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Apply + + + + + + + + + + + + Bank statement + + + + + + true + + + false + + + + @@ -114,42 +103,8 @@ 23 - - - File - - - - - - - - - - Save - - - Ctrl+S - - - - - Save As... - - - Ctrl+Shift+S - - - - - Open... - - - Ctrl+O - -