Finance Dashboard
Finance Dashboard
import csv
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QLineEdit,
QPushButton,
QVBoxLayout, QWidget, QListWidget, QComboBox,
QHBoxLayout,
QFileDialog, QMessageBox, QDateEdit, QSplitter,
QCheckBox)
from PyQt5.QtCore import Qt, QDate
from PyQt5.QtGui import QFont, QFontDatabase
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import locale
class FinanceDashboard(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Finance Dashboard")
self.setGeometry(100, 100, 800, 600)
self.transactions = []
self.init_ui()
def init_ui(self):
self.layout = QHBoxLayout()
# Create a splitter
self.splitter = QSplitter(Qt.Horizontal)
# Transaction Date
self.date_input = QDateEdit()
self.date_input.setDate(QDate.currentDate())
self.date_input.setFont(self.custom_font)
left_layout.addWidget(self.date_input)
# Transaction Amount
self.amount_input = QLineEdit()
self.amount_input.setPlaceholderText("Amount (e.g., 1000.00)")
self.amount_input.setFont(self.custom_font)
left_layout.addWidget(self.amount_input)
# Transaction Category
self.category_combobox = QComboBox()
self.category_combobox.addItems(["Select Category", "Income", "Expense"])
self.category_combobox.setFont(self.custom_font)
left_layout.addWidget(self.category_combobox)
# Transaction Description
self.description_input = QLineEdit()
self.description_input.setPlaceholderText("Description (e.g., Salary,
Grocery)")
self.description_input.setFont(self.custom_font)
left_layout.addWidget(self.description_input)
# Transaction List
self.transaction_list = QListWidget()
self.transaction_list.setFont(self.custom_font)
left_layout.addWidget(self.transaction_list)
# Summary Layout
summary_layout = QHBoxLayout()
self.total_income_label = QLabel("Total Income: ₹0.00")
self.total_income_label.setFont(self.custom_font)
summary_layout.addWidget(self.total_income_label)
left_layout.addLayout(summary_layout)
self.visualization_layout.addWidget(QLabel("Income vs Expenses"))
self.visualization_layout.addWidget(self.canvas_income_expenses)
self.visualization_layout.addWidget(QLabel("Expense Distribution by
Category"))
self.visualization_layout.addWidget(self.canvas_category_distribution)
self.layout.addWidget(self.splitter)
self.central_widget = QWidget()
self.central_widget.setLayout(self.layout)
self.setCentralWidget(self.central_widget)
self.apply_light_theme()
def add_transaction(self):
try:
date = self.date_input.date().toString(Qt.ISODate) #"yyyy-MM-dd"
amount = float(self.amount_input.text())
category = self.category_combobox.currentText()
description = self.description_input.text()
def update_summary(self):
total_income = sum(amount for _, category, _, amount in self.transactions
if category.lower() == "income")
total_expenses = sum(amount for _, category, _, amount in self.transactions
if category.lower() == "expense")
net_savings = total_income - total_expenses
def update_visualizations(self):
if self.transactions:
self.plot_income_vs_expenses()
self.plot_category_distribution()
def plot_income_vs_expenses(self):
income = sum(amount for _, category, _, amount in self.transactions if
category.lower() == "income")
expenses = sum(amount for _, category, _, amount in self.transactions if
category.lower() == "expense")
ax = self.canvas_income_expenses.figure.add_subplot(111)
ax.clear() # Clear the previous plot
self.canvas_income_expenses.draw()
def plot_category_distribution(self):
# Prepare data for individual expenses in the pie chart
expense_labels = [f"{description} ({category}) - ₹{amount:.2f}" for _,
category, description, amount in
self.transactions if category.lower() == "expense"]
expense_values = [amount for _, category, _, amount in self.transactions if
category.lower() == "expense"]
ax = self.canvas_category_distribution.figure.add_subplot(111)
ax.clear() # Clear the previous plot
self.canvas_category_distribution.draw()
def export_to_csv(self):
path, _ = QFileDialog.getSaveFileName(self, "Export Transactions", "", "CSV
Files (*.csv)")
if path:
with open(path, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(["Date", "Category", "Description", "Amount"])
writer.writerows(self.transactions)
QMessageBox.information(self, "Export Successful", "Transactions
exported successfully!")
def import_from_csv(self):
path, _ = QFileDialog.getOpenFileName(self, "Import Transactions", "", "CSV
Files (*.csv)")
if path:
with open(path, 'r', newline='') as file:
reader = csv.reader(file)
next(reader) # Skip header
for row in reader:
try:
date, category, description, amount = row
amount = float(amount)
self.transactions.append((date, category, description,
amount))
self.transaction_list.addItem(f"{date} | {category} |
{description} | ₹{amount:.2f}")
except ValueError:
continue # Skip rows with invalid data
self.update_summary()
self.update_visualizations()
def apply_dark_theme(self):
self.setStyleSheet("background-color: #2E2E2E; color: white;")
for widget in self.findChildren(QWidget):
widget.setStyleSheet("background-color: #2E2E2E; color: white;")
if isinstance(widget, QLineEdit):
widget.setStyleSheet("background-color: #3C3C3C; color: white;")
elif isinstance(widget, QPushButton):
widget.setStyleSheet("background-color: #4A4A4A; color: white;")
self.update_visualizations() # Update visualizations to reflect the new
theme
def apply_light_theme(self):
self.setStyleSheet("background-color: white; color: black;")
for widget in self.findChildren(QWidget):
widget.setStyleSheet("background-color: white; color: black;")
if isinstance(widget, QLineEdit):
widget.setStyleSheet("background-color: #E0E0E0; color: black;")
elif isinstance(widget, QPushButton):
widget.setStyleSheet("background-color: #E0E0E0; color: black;")
self.update_visualizations() # Update visualizations to reflect the new
theme
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FinanceDashboard()
window.show()
sys.exit(app.exec_())