diff --git a/FinanceApp/.qtcreator/CMakeLists.txt.user b/FinanceApp/.qtcreator/CMakeLists.txt.user new file mode 100644 index 0000000..fd830ef --- /dev/null +++ b/FinanceApp/.qtcreator/CMakeLists.txt.user @@ -0,0 +1,291 @@ + + + + + + EnvironmentId + {9e0109fd-5d04-4dfc-9566-35bd2b74e164} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + 4 + 1 + true + 8 + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + false + + + 0 + true + + + + + true + + 0 + + + + ProjectExplorer.Project.Target.0 + + Desktop + true + Desktop Qt 6.11.2 MinGW 64-bit + Desktop Qt 6.11.2 MinGW 64-bit + qt.qt6.6112.win64_mingw_kit + 0 + 0 + 0 + + Debug + 2 + false + + -DCMAKE_BUILD_TYPE:STRING=Debug +-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON +-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} +-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} +-DCMAKE_GENERATOR:STRING=MinGW Makefiles +-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} +-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtcreator/cmake-helper/qtcreator-project.cmake +-DQT_CREATOR_ENABLE_MAINTENANCE_TOOL_PROVIDER:BOOL=ON +-DQT_CREATOR_ENABLE_PACKAGE_MANAGER_SETUP:BOOL=ON +-DQT_ENABLE_QML_DEBUG:BOOL=%{Qt:QT_ENABLE_QML_DEBUG} +-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} + .\build\%{FileSystemFriendly:%{Kit:Name}_%{BuildConfig:Name}} + + + + + all + + false + + true + Build + CMakeProjectManager.MakeStep + + 1 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + + + clean + + false + + true + Build + CMakeProjectManager.MakeStep + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + CMakeProjectManager.CMakeBuildConfiguration + 0 + 0 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + + + + + + + + false + + true + Build + ApplicationManagerPlugin.Deploy.CMakePackageStep + + + install-package --acknowledge + true + Install Application Manager package + ApplicationManagerPlugin.Deploy.InstallPackageStep + + + + + + + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ApplicationManagerPlugin.Deploy.Configuration + + 2 + + false + + false + + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + + CMakeProjectManager.CMakeRunConfiguration. + FinanceApp + false + + true + true + true + %{RunConfig:Executable:Path} + + 1 + + 1 + + + 0 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ProjectExplorer.DefaultDeployConfiguration + + + + + + + + + false + + true + Build + ApplicationManagerPlugin.Deploy.CMakePackageStep + + + install-package --acknowledge + true + Install Application Manager package + ApplicationManagerPlugin.Deploy.InstallPackageStep + + + + + + + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + ApplicationManagerPlugin.Deploy.Configuration + + 2 + + true + true + 0 + true + + + 2 + + false + -e cpu-cycles --call-graph "dwarf,4096" -F 250 + + CMakeProjectManager.CMakeRunConfiguration. + FinanceApp + false + + true + true + true + %{RunConfig:Executable:Path} + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + Version + 22 + + diff --git a/FinanceApp/CMakeLists.txt b/FinanceApp/CMakeLists.txt new file mode 100644 index 0000000..08a01ae --- /dev/null +++ b/FinanceApp/CMakeLists.txt @@ -0,0 +1,39 @@ +cmake_minimum_required(VERSION 3.19) + +project(FinanceApp LANGUAGES CXX) + + +find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Charts) +find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets Charts Sql) + +qt_standard_project_setup() + +qt_add_executable(FinanceApp + WIN32 MACOSX_BUNDLE + main.cpp + mainwindow.cpp + mainwindow.h + mainwindow.ui + transactionwindow.h transactionwindow.cpp transactionwindow.ui + database.cpp + database.h + add_containers.h add_containers.cpp add_containers.ui + + +) + +target_link_libraries(FinanceApp + PRIVATE + Qt6::Core + Qt6::Widgets + Qt6::Charts + Qt6::Sql +) + +include(GNUInstallDirs) + +install(TARGETS FinanceApp + BUNDLE DESTINATION . + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) \ No newline at end of file diff --git a/FinanceApp/Dashboard b/FinanceApp/Dashboard new file mode 100644 index 0000000..daa1948 --- /dev/null +++ b/FinanceApp/Dashboard @@ -0,0 +1,6 @@ + + + + diff --git a/FinanceApp/Dashboard.png b/FinanceApp/Dashboard.png new file mode 100644 index 0000000..dc4b10d Binary files /dev/null and b/FinanceApp/Dashboard.png differ diff --git a/FinanceApp/FIles/FinanceApp/FinanceApp_en_US.ts b/FinanceApp/FIles/FinanceApp/FinanceApp_en_US.ts new file mode 100644 index 0000000..5be10c4 --- /dev/null +++ b/FinanceApp/FIles/FinanceApp/FinanceApp_en_US.ts @@ -0,0 +1,6 @@ + + + + diff --git a/FinanceApp/FIles/FinanceApp/pixabot-f005.png b/FinanceApp/FIles/FinanceApp/pixabot-f005.png new file mode 100644 index 0000000..00fe284 Binary files /dev/null and b/FinanceApp/FIles/FinanceApp/pixabot-f005.png differ diff --git a/FinanceApp/Finance b/FinanceApp/Finance new file mode 100644 index 0000000..daa1948 --- /dev/null +++ b/FinanceApp/Finance @@ -0,0 +1,6 @@ + + + + diff --git a/FinanceApp/FinanceApp_en_US.ts b/FinanceApp/FinanceApp_en_US.ts new file mode 100644 index 0000000..edd0d34 --- /dev/null +++ b/FinanceApp/FinanceApp_en_US.ts @@ -0,0 +1,3 @@ + + + diff --git a/FinanceApp/FinanceMan.gif b/FinanceApp/FinanceMan.gif new file mode 100644 index 0000000..9f495f8 Binary files /dev/null and b/FinanceApp/FinanceMan.gif differ diff --git a/FinanceApp/QT_Design.png b/FinanceApp/QT_Design.png new file mode 100644 index 0000000..3a08bc5 Binary files /dev/null and b/FinanceApp/QT_Design.png differ diff --git a/FinanceApp/QT_Environmentpng.png b/FinanceApp/QT_Environmentpng.png new file mode 100644 index 0000000..080b8f0 Binary files /dev/null and b/FinanceApp/QT_Environmentpng.png differ diff --git a/FinanceApp/README.md b/FinanceApp/README.md new file mode 100644 index 0000000..0993b7e --- /dev/null +++ b/FinanceApp/README.md @@ -0,0 +1,96 @@ +# FinanceApp + +A lightweight personal finance dashboard built with **C++**, **Qt 6**, **Qt Charts**, and **SQLite**. The application provides a graphical dashboard for displaying financial information and organizing transactions by category and tag. + +## Description + +FinanceApp is a desktop personal finance dashboard created as a contribution for issue #93 of the `All-In-One-Python-Projects` repository. + +The project uses Qt Widgets for the graphical user interface and Qt Charts for financial visualization. SQLite is used through Qt's SQL module to provide local database storage. + +The application includes: + +- A graphical finance dashboard +- Transaction information displayed in a table +- Category and tag information for transactions +- A spending/money-allocation pie chart +- Transaction and deposit interface windows +- Local SQLite database support +- Database functions for recording transactions, managing category balances, and calculating financial totals + +The dashboard was designed to provide a lightweight alternative to larger personal finance applications while keeping the interface simple and easy to understand. + +## Prerequisites + +The following software is required to build and run FinanceApp: + +- C++ compiler +- Qt 6.5 or later +- Qt Widgets +- Qt Charts +- Qt SQL +- SQLite +- CMake 3.19 or later +- Qt Creator (recommended) + +## Installing Instructions + +1. Clone the repository: + +```bash +git clone https://github.com/king04aman/All-In-One-Python-Projects.git +``` + +2. Open the `FinanceApp` directory in Qt Creator. + +3. Configure the project with a Qt 6 kit and CMake. + +4. Build the project. + +5. Run `FinanceApp`. + +The application uses an SQLite database named `finance.db` for local financial data. + +## Database Structure and Behavior + +The database layer is implemented in [`database.h`](./database.h) and [`database.cpp`](./database.cpp) using Qt's SQL module with the SQLite driver. When the `Database` object is created, it opens `finance.db` in the application's current working directory and creates the database tables. + +The database contains two tables: + +| Table | Columns | Purpose | +|---|---|---| +| `containers` | `id` (auto-incrementing primary key), `category`, `tag`, `amount` | Stores the user's category balances. A category is the named container, while the tag classifies it as `Spending`, `Giving`, or `Saving`. | +| `transactions` | `id` (auto-incrementing primary key), `category`, `tag`, `amount` | Keeps a record of transaction entries, including their category, tag, and amount. | + +The `Database` class provides the following operations: + +- `create_Container_Table()` and `create_Transaction_Table()` define the tables when the database is initialized. +- `addContainer(category, tag, amount)` adds a starting balance or allocation to `containers`. +- `addTransaction(category, tag, amount)` records a transaction in `transactions` and subtracts its amount from the matching container (the same category and tag). +- `deleteContainer()` removes all rows from `containers`. It does not delete the transaction history. +- `getTotal()` returns the sum of the current amounts in all containers. +- `totalSpending()`, `totalGiving()`, and `totalSaving()` return the sum of container amounts for the corresponding tag. +- `getDatabase()` exposes the Qt database connection so other parts of the application can run queries. + +The add-container and transaction windows validate their input before calling the database methods. After a successful save, the main window reads the container rows again to refresh the category table and updates the balance and pie chart using the total functions. Transaction records are stored separately from container balances; the displayed totals are calculated from the current `containers` amounts. + +## Technologies Used + +- **C++** — application logic +- **Qt Widgets** — graphical user interface +- **Qt Charts** — financial data visualization +- **Qt SQL** — database interface +- **SQLite** — local data storage +- **CMake** — project configuration and build system + +## Screenshot + +"...\All-In-One-Python-Projects\FinanceApp\QT_Design.png" +"...\All-In-One-Python-Projects\FinanceApp\QT_Environmentpng.png" +"...\All-In-One-Python-Projects\FinanceApp\Dashboard.png" + + + +## Author + +Joshua Wilson diff --git a/FinanceApp/Tracker/Finance b/FinanceApp/Tracker/Finance new file mode 100644 index 0000000..daa1948 --- /dev/null +++ b/FinanceApp/Tracker/Finance @@ -0,0 +1,6 @@ + + + + diff --git a/FinanceApp/TransactionDashboard.png b/FinanceApp/TransactionDashboard.png new file mode 100644 index 0000000..c797a8e Binary files /dev/null and b/FinanceApp/TransactionDashboard.png differ diff --git a/FinanceApp/add_containers.cpp b/FinanceApp/add_containers.cpp new file mode 100644 index 0000000..2291332 --- /dev/null +++ b/FinanceApp/add_containers.cpp @@ -0,0 +1,70 @@ +#include "add_containers.h" +#include "ui_add_containers.h" +#include + +add_containers::add_containers(MainWindow *mainwindow, Database& database, QWidget *parent) + : QDialog(parent) + , ui(new Ui::add_containers), db(database), mainwindow(mainwindow) + +{ + ui->setupUi(this); + connect(ui->saveButton, &QPushButton::clicked, this, &add_containers::savebutton); + connect(ui->cancelButton, &QPushButton::clicked, this, &add_containers::cancelbutton); + QMovie *movie = new QMovie("C:/Users/wilso/CLionProjects/Personal Finance Tracker/All-In-One-Python-Projects/FinanceApp/FinanceMan.gif"); + + ui->tgiflabel->setMovie(movie); + movie->setScaledSize(QSize(371, 71)); + ui->tgiflabel->setAlignment(Qt::AlignCenter); + ui->tgiflabel->setMovie(movie); + movie->start(); + + +} + +add_containers::~add_containers() +{ + delete ui; +} + +void add_containers::cancelbutton(){ + this->close(); +} + +void add_containers::savebutton(){ + //backend saving + QString new_cat = ui->category_textedit->toPlainText(); + QString new_tag = ui->tag_textedit->toPlainText(); + QString amt_text = ui->amount_textedit->toPlainText(); + + bool valid; + double amount = amt_text.toDouble(&valid); + + // Validation + if (new_cat.isEmpty()) { + qDebug() << "Error: Group name is required."; + return; + } + + if (!valid || amount <= 0) { + qDebug() << "Error: Enter a valid amount greater than 0."; + return; + } + + if (new_tag != "Spending" && + new_tag != "Giving" && + new_tag != "Saving") { + + qDebug() << "Error: Enter a valid tag"; + return; + } + + //Database Updating + db.addContainer(new_cat,new_tag,amount); + mainwindow->updateContainers(); + mainwindow->updateLabels(); + mainwindow->updatePieChart(); + + + this->close(); + +} diff --git a/FinanceApp/add_containers.h b/FinanceApp/add_containers.h new file mode 100644 index 0000000..d38c313 --- /dev/null +++ b/FinanceApp/add_containers.h @@ -0,0 +1,28 @@ +#ifndef ADD_CONTAINERS_H +#define ADD_CONTAINERS_H + +#include +#include "database.h" +#include "mainwindow.h" + +namespace Ui { +class add_containers; +} + +class add_containers : public QDialog +{ + Q_OBJECT + +public: + explicit add_containers(MainWindow *mainwindow, Database& database, QWidget *parent = nullptr); + ~add_containers(); + +private: + Ui::add_containers *ui; + void cancelbutton(); + void savebutton(); + Database& db; + MainWindow *mainwindow; +}; + +#endif // ADD_CONTAINERS_H diff --git a/FinanceApp/add_containers.ui b/FinanceApp/add_containers.ui new file mode 100644 index 0000000..4528359 --- /dev/null +++ b/FinanceApp/add_containers.ui @@ -0,0 +1,133 @@ + + + add_containers + + + + 0 + 0 + 407 + 365 + + + + Dialog + + + + + 60 + 90 + 281 + 241 + + + + + + 0 + 0 + 281 + 81 + + + + + + + + 0 + 100 + 281 + 72 + + + + + + + + + + + + + + + + + + 0 + 150 + 281 + 91 + + + + + + + Save + + + + + + + Cancel + + + + + + + + + 0 + 10 + 279 + 79 + + + + + + + Category + + + + + + + Tag + + + + + + + Amount + + + + + + + + + + 20 + 10 + 371 + 71 + + + + TextLabel + + + + + + diff --git a/FinanceApp/database.cpp b/FinanceApp/database.cpp new file mode 100644 index 0000000..14c17bc --- /dev/null +++ b/FinanceApp/database.cpp @@ -0,0 +1,190 @@ +#include "database.h" +#include +#include +#include +#include + +Database::Database() { + db = QSqlDatabase::addDatabase("QSQLITE"); + + db.setDatabaseName("finance.db"); + + if (!db.open()) { + qDebug() << "Database failed:" << db.lastError().text(); + return; + } + + qDebug() << "Database connected!"; + + create_Container_Table(); + create_Transaction_Table(); +} + + +void Database::addTransaction(QString category, QString tag, double amount){ + QSqlQuery query(db); + + query.prepare( + "INSERT INTO transactions (category, tag, amount) " + "VALUES (:category, :tag, :amount)" + ); + + query.bindValue(":category", category); + query.bindValue(":tag", tag); + query.bindValue(":amount", amount); + + + if (!query.exec()) { + qDebug() << "Failed to add transaction:" << query.lastError().text(); + return; + } + + + QSqlQuery updatequery(db); + + updatequery.prepare( + "UPDATE containers " + "SET amount = amount - :amount " + "WHERE category = :category AND tag = :tag" + ); + + updatequery.bindValue(":amount", amount); + updatequery.bindValue(":category", category); + updatequery.bindValue(":tag", tag); + + if (!updatequery.exec()) { + qDebug() << "Failed to update balance:" + << updatequery.lastError().text(); + } + +} + + +double Database::getTotal(){ + QSqlQuery query(db); + query.exec( + "SELECT SUM(amount) " + "FROM containers" + ); + double total = 0; + if (query.next()) { + total = query.value(0).toDouble(); + + } + return total; + +} + +double Database::totalSpending(){ + QSqlQuery query(db); + + query.prepare( + "SELECT SUM(amount) FROM containers " + "WHERE category = :category" + ); + + query.bindValue(":category", "Spending"); + + double total = 0; + + if (query.exec() && query.next()) { + total = query.value(0).toDouble(); + } + + return total; + +} +double Database::totalGiving(){ + QSqlQuery query(db); + + query.prepare( + "SELECT SUM(amount) FROM containers " + "WHERE category = :category" + ); + + query.bindValue(":category", "Giving"); + + double total = 0; + + if (query.exec() && query.next()) { + total = query.value(0).toDouble(); + } + + return total; +} +double Database::totalSaving(){ + QSqlQuery query(db); + + query.prepare( + "SELECT SUM(amount) FROM containers " + "WHERE category = :category" + ); + + query.bindValue(":category", "Saving"); + + double total = 0; + + if (query.exec() && query.next()) { + total = query.value(0).toDouble(); + } + + return total; + +} + + +void Database::create_Transaction_Table(){ + QSqlQuery query(db); + query.exec( + "CREATE TABLE transactions (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "category TEXT," + "tag TEXT," + "amount REAL" + ")" + ); +} + + +void Database::create_Container_Table(){ + QSqlQuery query(db); + query.exec( + "CREATE TABLE containers(" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "category TEXT," + "tag TEXT," + "amount REAL" + ")" + ); +} + +void Database::addContainer(QString category, QString tag, double amount){ + + QSqlQuery query(db); + + query.prepare( + "INSERT INTO containers (category, tag, amount) " + "VALUES (:category, :tag, :amount)" + ); + + query.bindValue(":category", category); + query.bindValue(":tag", tag); + query.bindValue(":amount", amount); + + if (!query.exec()) { + qDebug() << "Failed to add container:" + << query.lastError().text(); + qDebug() << query.lastError().text(); + qDebug() << query.lastQuery(); + qDebug() << query.boundValues(); + } +} + +void Database::deleteContainer(){ + QSqlQuery query(db); + + if (!query.exec("DELETE FROM containers")) { + qDebug() << "Failed to clear containers:" + << query.lastError().text(); + } +} \ No newline at end of file diff --git a/FinanceApp/database.h b/FinanceApp/database.h new file mode 100644 index 0000000..1bb1eda --- /dev/null +++ b/FinanceApp/database.h @@ -0,0 +1,32 @@ +#ifndef DATABASE_H +#define DATABASE_H +#include +#include +#include + +class Database{ + public: + ///QSqlQuery query; + Database(); + void create_Transaction_Table(); + void create_Container_Table(); + void addTransaction(QString category, QString tag, double amount); + void addContainer(QString category, QString tag, double amount); + void deleteContainer(); + double getTotal(); + double totalSpending(); + double totalGiving(); + double totalSaving(); + QSqlDatabase getDatabase() const { + return db; + } + private: + QSqlDatabase db; + +}; + + + + + +#endif // DATABASE_H diff --git a/FinanceApp/f005.gif b/FinanceApp/f005.gif new file mode 100644 index 0000000..2132282 Binary files /dev/null and b/FinanceApp/f005.gif differ diff --git a/FinanceApp/main.cpp b/FinanceApp/main.cpp new file mode 100644 index 0000000..6e6e589 --- /dev/null +++ b/FinanceApp/main.cpp @@ -0,0 +1,26 @@ +#include "mainwindow.h" +#include "database.h" + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + + + QTranslator translator; + const QStringList uiLanguages = QLocale::system().uiLanguages(); + for (const QString &locale : uiLanguages) { + const QString baseName = "FinanceApp_" + QLocale(locale).name(); + if (translator.load(":/i18n/" + baseName)) { + a.installTranslator(&translator); + break; + } + } + MainWindow w; + w.show(); + return QApplication::exec(); +} diff --git a/FinanceApp/mainwindow.cpp b/FinanceApp/mainwindow.cpp new file mode 100644 index 0000000..bfb4419 --- /dev/null +++ b/FinanceApp/mainwindow.cpp @@ -0,0 +1,160 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "transactionwindow.h" +#include +#include +#include +#include +#include +#include +#include +#include "database.h" +#include "add_containers.h" + + + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) + , db(new Database()) +{ + ui->setupUi(this); + connect(ui->transactionButton, &QPushButton::clicked, this, &MainWindow::transactionbutton); + connect(ui->container_pushButton, &QPushButton::clicked, this, &MainWindow::containerbutton); + connect(ui->delete_container_push,&QPushButton::clicked, this, &MainWindow::deletebutton); + transaction = new transactionwindow(this,*db); + addcontainer = new add_containers(this,*db); + + //Display: + // Title + QPixmap balanceImage("C:/Users/wilso/CLionProjects/Personal Finance Tracker/All-In-One-Python-Projects/FinanceApp/title.png"); + ui->giftitle->setPixmap(balanceImage); + + + //Gif Label + QMovie *movie = new QMovie("C:/Users/wilso/CLionProjects/Personal Finance Tracker/All-In-One-Python-Projects/FinanceApp/f005.gif"); + + ui->giflabel->setMovie(movie); + movie->setScaledSize(QSize(50, 50)); + ui->giflabel->setAlignment(Qt::AlignCenter); + ui->giflabel->setMovie(movie); + movie->start(); + + + //Initialize Category Table + this->rows = 1; + ui->categories_tableWidget->setRowCount(rows); + ui->categories_tableWidget->setColumnCount(3); + ui->categories_tableWidget->setHorizontalHeaderLabels({"Category","Tag", "Amount"}); + + ui->categories_tableWidget->setItem(0,0, new QTableWidgetItem("Eden's Mission Trip")); + ui->categories_tableWidget->setItem(0,1, new QTableWidgetItem("Giving")); + ui->categories_tableWidget->setItem(0,2, new QTableWidgetItem("$40")); + ui->categories_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + + + //Income Pie Chart + series = new QPieSeries(); + + series->append("Spending", 40); + series->append("Giving", 20); + series->append("Saving", 15); + + chart = new QChart(); + + chart->addSeries(series); + chart->setTitle("Money Allocation"); + + + ui->income_tableView->setChart(chart); +} + + + + + + +//Functions +void MainWindow::transactionbutton(){ + transaction->show(); +} + +void MainWindow::containerbutton(){ + addcontainer->show(); +} + +void MainWindow::updateContainers(){ + + QSqlQuery query(db->getDatabase()); + + query.prepare("SELECT category, tag, amount FROM containers"); + + if (!query.exec()) { + qDebug() << "Failed to retrieve categories:" + << query.lastError().text(); + return; + } + + rows = 0; + this->ui->categories_tableWidget->setRowCount(rows); + + while (query.next()){ + this->ui->categories_tableWidget->insertRow(rows); + + QString category = query.value("category").toString(); + QString tag = query.value("tag").toString(); + double amount = query.value("amount").toDouble(); + + ui->categories_tableWidget->setItem( + rows, 0, new QTableWidgetItem(category) + ); + + ui->categories_tableWidget->setItem( + rows, 1, new QTableWidgetItem(tag) + ); + + ui->categories_tableWidget->setItem( + rows, 2, new QTableWidgetItem( + QString("$%1").arg(amount, 0, 'f', 2) + ) + ); + + rows++; + } + + +} + +void MainWindow::updateLabels(){ + double balance = 2000 - db->getTotal(); + this->ui->balance_value_label->setText("$" + QString::number(balance, 'f', 2)); + this->ui->giflabel->hide(); + this->ui->label_5->hide(); + +}; +void MainWindow::updatePieChart(){ + this->series->clear(); + + this->series->append("Spending", db->totalSpending()); + this->series->append("Giving", db->totalGiving()); + this->series->append("Saving", db->totalSaving()); + +}; + + +void MainWindow::deletebutton(){ + db->deleteContainer(); + this->updateLabels(); + this->updateContainers(); + this->updatePieChart(); + this->ui->giflabel->show(); + this->ui->label_5->show(); +} + + +MainWindow::~MainWindow() +{ + delete ui; + delete db; +} + diff --git a/FinanceApp/mainwindow.h b/FinanceApp/mainwindow.h new file mode 100644 index 0000000..10636ec --- /dev/null +++ b/FinanceApp/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class Database; +class transactionwindow; +class add_containers; + +QT_BEGIN_NAMESPACE +namespace Ui { +class MainWindow; +} +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + void updateContainers(); + void updateLabels(); + void updatePieChart(); + //void updateIncome(); + +private: + Ui::MainWindow *ui; + Database *db; + transactionwindow *transaction; + add_containers *addcontainer; + int rows; + QPieSeries *series; + QChart *chart; +private slots: + void transactionbutton(); + void containerbutton(); + void deletebutton(); + + + //void updateCategories(); + +}; +#endif // MAINWINDOW_H diff --git a/FinanceApp/mainwindow.ui b/FinanceApp/mainwindow.ui new file mode 100644 index 0000000..b399f82 --- /dev/null +++ b/FinanceApp/mainwindow.ui @@ -0,0 +1,248 @@ + + + MainWindow + + + + 0 + 0 + 488 + 919 + + + + MainWindow + + + + + + 70 + 740 + 313 + 80 + + + + + + + +Add Transaction + + + + + + + +Add Container + + + + + + + + Add Deposit + + + + + + + + + 60 + 0 + 341 + 111 + + + + + + + FIles/FinanceApp/title.png + + + true + + + + + + 40 + 490 + 379 + 241 + + + + + + + 40 + 230 + 381 + 201 + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + + + + 70 + 110 + 321 + 111 + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 30 + 10 + 49 + 16 + + + + Income + + + Qt::AlignmentFlag::AlignCenter + + + + + + 30 + 40 + 49 + 16 + + + + $2000 + + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 30 + 10 + 49 + 16 + + + + Balance + + + Qt::AlignmentFlag::AlignCenter + + + + + + 30 + 40 + 49 + 16 + + + + $1960 + + + + + + + + + + 110 + 380 + 251 + 51 + + + + + Fixedsys + + + + Waiting On More Containers... + + + + + + 180 + 310 + 103 + 109 + + + + TextLabel + + + + + + 180 + 450 + 101 + 24 + + + + Clear Containers + + + + + + + 0 + 0 + 488 + 21 + + + + + + + + QChartView + QTableView +
qchartview.h
+
+
+ + +
diff --git a/FinanceApp/title.png b/FinanceApp/title.png new file mode 100644 index 0000000..fbf8503 Binary files /dev/null and b/FinanceApp/title.png differ diff --git a/FinanceApp/transactiontitle.gif b/FinanceApp/transactiontitle.gif new file mode 100644 index 0000000..0bb92ab Binary files /dev/null and b/FinanceApp/transactiontitle.gif differ diff --git a/FinanceApp/transactionwindow.cpp b/FinanceApp/transactionwindow.cpp new file mode 100644 index 0000000..6f54b3f --- /dev/null +++ b/FinanceApp/transactionwindow.cpp @@ -0,0 +1,69 @@ +#include "transactionwindow.h" +#include "ui_transactionwindow.h" +#include + +transactionwindow::transactionwindow(MainWindow *mainwindow, Database& database, QWidget *parent) + : QDialog(parent) + , ui(new Ui::transactionwindow), db(database) + , mainwindow(mainwindow) +{ + ui->setupUi(this); + connect(ui->saveButton, &QPushButton::clicked, this, &transactionwindow::savebutton); + connect(ui->cancelButton, &QPushButton::clicked, this, &transactionwindow::cancelbutton); + //Gif Label + QMovie *movie = new QMovie("C:/Users/wilso/CLionProjects/Personal Finance Tracker/All-In-One-Python-Projects/FinanceApp/transactiontitle.gif"); + + ui->tgiflabel->setMovie(movie); + movie->setScaledSize(QSize(371, 71)); + ui->tgiflabel->setAlignment(Qt::AlignCenter); + ui->tgiflabel->setMovie(movie); + movie->start(); + + +} + +void transactionwindow::cancelbutton(){ + this->close(); +} +void transactionwindow::savebutton(){ + //backend saving + QString new_cat = ui->category_textEdit->toPlainText(); + QString new_tag = ui->tag_textEdit->toPlainText(); + QString amt_text = ui->amount_textEdit->toPlainText(); + + bool valid; + double amount = amt_text.toDouble(&valid); + + // Validation + if (new_cat.isEmpty()) { + qDebug() << "Error: Group name is required."; + return; + } + + if (!valid || amount <= 0) { + qDebug() << "Error: Enter a valid amount greater than 0."; + return; + } + + if (new_tag != "Spending" && + new_tag != "Giving" && + new_tag != "Saving") { + + qDebug() << "Error: Enter a valid tag"; + return; + } + + //Database Updating + db.addTransaction(new_cat,new_tag,amount); + mainwindow->updateContainers(); + mainwindow->updateLabels(); + mainwindow->updatePieChart(); + + + this->close(); +} + +transactionwindow::~transactionwindow() +{ + delete ui; +} diff --git a/FinanceApp/transactionwindow.h b/FinanceApp/transactionwindow.h new file mode 100644 index 0000000..2e4584e --- /dev/null +++ b/FinanceApp/transactionwindow.h @@ -0,0 +1,30 @@ +#ifndef TRANSACTIONWINDOW_H +#define TRANSACTIONWINDOW_H + +#include +#include "database.h" +#include "mainwindow.h" + +namespace Ui { +class transactionwindow; +} + +class transactionwindow : public QDialog +{ + Q_OBJECT + +public: + explicit transactionwindow(MainWindow *mainwindow, Database& database, QWidget *parent = nullptr); + ~transactionwindow(); + +private: + Ui::transactionwindow *ui; + Database& db; + MainWindow *mainwindow; +private slots: + void cancelbutton(); + void savebutton(); + +}; + +#endif // TRANSACTIONWINDOW_H diff --git a/FinanceApp/transactionwindow.ui b/FinanceApp/transactionwindow.ui new file mode 100644 index 0000000..d2ce1a3 --- /dev/null +++ b/FinanceApp/transactionwindow.ui @@ -0,0 +1,133 @@ + + + transactionwindow + + + + 0 + 0 + 436 + 414 + + + + Dialog + + + + + 70 + 90 + 281 + 241 + + + + + + 0 + 0 + 281 + 81 + + + + + + + + 0 + 100 + 281 + 72 + + + + + + + + + + + + + + + + + + 0 + 150 + 281 + 91 + + + + + + + Save + + + + + + + Cancel + + + + + + + + + 0 + 10 + 279 + 79 + + + + + + + Category + + + + + + + Tag + + + + + + + Amount + + + + + + + + + + 30 + 10 + 371 + 71 + + + + TextLabel + + + + + +