From 05e4f8f9a9f4429c0c3446ec24af8fff53027da9 Mon Sep 17 00:00:00 2001 From: aiekick Date: Wed, 19 Jun 2024 09:51:04 +0200 Subject: [PATCH] [FIX] : fix the ADataTable for support row selections and context menu --- src/Frontend/Tables/CategoriesTable.cpp | 34 +++++-- src/Frontend/Tables/CategoriesTable.h | 9 +- src/Frontend/Tables/EntitiesTable.cpp | 34 +++++-- src/Frontend/Tables/EntitiesTable.h | 9 +- src/Frontend/Tables/OperationsTable.cpp | 34 +++++-- src/Frontend/Tables/OperationsTable.h | 9 +- src/Frontend/Tables/TransactionsTable.cpp | 76 ++++++++++++++++ src/Frontend/Tables/TransactionsTable.h | 28 ++++++ src/Frontend/Tables/abstract/ADataTable.cpp | 98 ++++++++++++++++++++- src/Frontend/Tables/abstract/ADataTable.h | 23 ++++- src/Headers/CashMeBuild.h | 4 +- src/Models/DataBase.cpp | 63 +++++++------ src/Models/DataBase.h | 3 + src/Panes/StatsPane.cpp | 4 +- 14 files changed, 356 insertions(+), 72 deletions(-) create mode 100644 src/Frontend/Tables/TransactionsTable.cpp create mode 100644 src/Frontend/Tables/TransactionsTable.h diff --git a/src/Frontend/Tables/CategoriesTable.cpp b/src/Frontend/Tables/CategoriesTable.cpp index a3708f8..040e990 100644 --- a/src/Frontend/Tables/CategoriesTable.cpp +++ b/src/Frontend/Tables/CategoriesTable.cpp @@ -25,24 +25,30 @@ bool CategoriesTable::drawMenu() { return false; } -double CategoriesTable::m_getAmount(const size_t& vIdx) { +size_t CategoriesTable::m_getItemsCount() const { + return m_Categories.size(); +} + +RowID CategoriesTable::m_getItemRowID(const size_t& vIdx) const { + if (vIdx < m_Categories.size()) { + return m_Categories.at(vIdx).id; + } + return 0; // the db row id cant be 0 +} + +double CategoriesTable::m_getItemAmount(const size_t& vIdx) const { return m_Categories.at(vIdx).amount; } -void CategoriesTable::m_drawContent(const size_t& vIdx, const double& vMaxAmount) { +void CategoriesTable::m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) { const auto& e = m_Categories.at(vIdx); - ImGui::TableNextColumn(); - ImGui::Text("%s", e.name.c_str()); + m_drawColumnSelectable(vIdx, e.id, e.name); m_drawColumnDebit(e.debit); m_drawColumnCredit(e.credit); m_drawColumnAmount(e.amount); m_drawColumnBars(e.amount, vMaxAmount); } -size_t CategoriesTable::m_getItemsCount() { - return m_Categories.size(); -} - void CategoriesTable::m_setupColumns() { ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); @@ -53,16 +59,26 @@ void CategoriesTable::m_setupColumns() { ImGui::TableHeadersRow(); } +void CategoriesTable::m_drawContextMenuContent() { + CTOOL_DEBUG_BREAK; +} + +void CategoriesTable::m_doActionOnDblClick() { + CTOOL_DEBUG_BREAK; +} + void CategoriesTable::m_updateCategories() { const auto account_id = m_getAccountID(); if (account_id > 0) { m_Categories.clear(); DataBase::Instance()->GetCategoriesStats( // account_id, - [this](const CategoryName& vCategoryName, + [this](const RowID& vRowID, + const CategoryName& vCategoryName, const TransactionDebit& vTransactionDebit, const TransactionCredit& vTransactionCredit) { // Category e; + e.id = vRowID; e.name = vCategoryName; e.debit = vTransactionDebit; e.credit = vTransactionCredit; diff --git a/src/Frontend/Tables/CategoriesTable.h b/src/Frontend/Tables/CategoriesTable.h index 0c7cc4c..a490c2b 100644 --- a/src/Frontend/Tables/CategoriesTable.h +++ b/src/Frontend/Tables/CategoriesTable.h @@ -15,10 +15,13 @@ class CategoriesTable : public ADataTable { bool drawMenu(); protected: - double m_getAmount(const size_t& vIdx) final; - void m_drawContent(const size_t& vIdx, const double& vMaxAmount) final; - size_t m_getItemsCount() final; + size_t m_getItemsCount() const final; + RowID m_getItemRowID(const size_t& vIdx) const final; + double m_getItemAmount(const size_t& vIdx) const final; + void m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) final; void m_setupColumns() final; + void m_drawContextMenuContent() final; + void m_doActionOnDblClick() final; private: void m_updateCategories(); diff --git a/src/Frontend/Tables/EntitiesTable.cpp b/src/Frontend/Tables/EntitiesTable.cpp index 38c5b2b..284345e 100644 --- a/src/Frontend/Tables/EntitiesTable.cpp +++ b/src/Frontend/Tables/EntitiesTable.cpp @@ -25,24 +25,30 @@ bool EntitiesTable::drawMenu() { return false; } -double EntitiesTable::m_getAmount(const size_t& vIdx) { +size_t EntitiesTable::m_getItemsCount() const { + return m_Entities.size(); +} + +RowID EntitiesTable::m_getItemRowID(const size_t& vIdx) const { + if (vIdx < m_Entities.size()) { + return m_Entities.at(vIdx).id; + } + return 0; // the db row id cant be 0 +} + +double EntitiesTable::m_getItemAmount(const size_t& vIdx) const { return m_Entities.at(vIdx).amount; } -void EntitiesTable::m_drawContent(const size_t& vIdx, const double& vMaxAmount) { +void EntitiesTable::m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) { const auto& e = m_Entities.at(vIdx); - ImGui::TableNextColumn(); - ImGui::Text("%s", e.name.c_str()); + m_drawColumnSelectable(vIdx, e.id, e.name); m_drawColumnDebit(e.debit); m_drawColumnCredit(e.credit); m_drawColumnAmount(e.amount); m_drawColumnBars(e.amount, vMaxAmount); } -size_t EntitiesTable::m_getItemsCount() { - return m_Entities.size(); -} - void EntitiesTable::m_setupColumns() { ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); @@ -53,16 +59,26 @@ void EntitiesTable::m_setupColumns() { ImGui::TableHeadersRow(); } +void EntitiesTable::m_drawContextMenuContent() { + CTOOL_DEBUG_BREAK; +} + +void EntitiesTable::m_doActionOnDblClick() { + CTOOL_DEBUG_BREAK; +} + void EntitiesTable::m_updateEntities() { const auto account_id = m_getAccountID(); if (account_id > 0) { m_Entities.clear(); DataBase::Instance()->GetEntitiesStats( // account_id, - [this](const EntityName& vEntityName, + [this](const RowID& vRowID, + const EntityName& vEntityName, const TransactionDebit& vTransactionDebit, const TransactionCredit& vTransactionCredit) { // Entity e; + e.id = vRowID; e.name = vEntityName; e.debit = vTransactionDebit; e.credit = vTransactionCredit; diff --git a/src/Frontend/Tables/EntitiesTable.h b/src/Frontend/Tables/EntitiesTable.h index 4cc7751..4712c9a 100644 --- a/src/Frontend/Tables/EntitiesTable.h +++ b/src/Frontend/Tables/EntitiesTable.h @@ -15,10 +15,13 @@ class EntitiesTable : public ADataTable { bool drawMenu(); protected: - double m_getAmount(const size_t& vIdx) final; - void m_drawContent(const size_t& vIdx, const double& vMaxAmount) final; - size_t m_getItemsCount() final; + size_t m_getItemsCount() const final; + RowID m_getItemRowID(const size_t& vIdx) const final; + double m_getItemAmount(const size_t& vIdx) const final; + void m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) final; void m_setupColumns() final; + void m_drawContextMenuContent() final; + void m_doActionOnDblClick() final; private: void m_updateEntities(); diff --git a/src/Frontend/Tables/OperationsTable.cpp b/src/Frontend/Tables/OperationsTable.cpp index c44690c..babfeed 100644 --- a/src/Frontend/Tables/OperationsTable.cpp +++ b/src/Frontend/Tables/OperationsTable.cpp @@ -25,24 +25,30 @@ bool OperationsTable::drawMenu() { return false; } -double OperationsTable::m_getAmount(const size_t& vIdx) { +size_t OperationsTable::m_getItemsCount() const { + return m_Operations.size(); +} + +RowID OperationsTable::m_getItemRowID(const size_t& vIdx) const { + if (vIdx < m_Operations.size()) { + return m_Operations.at(vIdx).id; + } + return 0; // the db row id cant be 0 +} + +double OperationsTable::m_getItemAmount(const size_t& vIdx) const { return m_Operations.at(vIdx).amount; } -void OperationsTable::m_drawContent(const size_t& vIdx, const double& vMaxAmount) { +void OperationsTable::m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) { const auto& e = m_Operations.at(vIdx); - ImGui::TableNextColumn(); - ImGui::Text("%s", e.name.c_str()); + m_drawColumnSelectable(vIdx, e.id, e.name); m_drawColumnDebit(e.debit); m_drawColumnCredit(e.credit); m_drawColumnAmount(e.amount); m_drawColumnBars(e.amount, vMaxAmount); } -size_t OperationsTable::m_getItemsCount() { - return m_Operations.size(); -} - void OperationsTable::m_setupColumns() { ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); @@ -53,16 +59,26 @@ void OperationsTable::m_setupColumns() { ImGui::TableHeadersRow(); } +void OperationsTable::m_drawContextMenuContent() { + CTOOL_DEBUG_BREAK; +} + +void OperationsTable::m_doActionOnDblClick() { + CTOOL_DEBUG_BREAK; +} + void OperationsTable::m_updateOperations() { const auto account_id = m_getAccountID(); if (account_id > 0) { m_Operations.clear(); DataBase::Instance()->GetOperationsStats( // account_id, - [this](const OperationName& vOperationName, + [this](const RowID& vRowID, + const OperationName& vOperationName, const TransactionDebit& vTransactionDebit, const TransactionCredit& vTransactionCredit) { // Operation e; + e.id = vRowID; e.name = vOperationName; e.debit = vTransactionDebit; e.credit = vTransactionCredit; diff --git a/src/Frontend/Tables/OperationsTable.h b/src/Frontend/Tables/OperationsTable.h index fc98331..ba9a4f6 100644 --- a/src/Frontend/Tables/OperationsTable.h +++ b/src/Frontend/Tables/OperationsTable.h @@ -15,10 +15,13 @@ class OperationsTable : public ADataTable { bool drawMenu(); protected: - double m_getAmount(const size_t& vIdx) final; - void m_drawContent(const size_t& vIdx, const double& vMaxAmount) final; - size_t m_getItemsCount() final; + size_t m_getItemsCount() const final; + RowID m_getItemRowID(const size_t& vIdx) const final; + double m_getItemAmount(const size_t& vIdx) const final; + void m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) final; void m_setupColumns() final; + void m_drawContextMenuContent() final; + void m_doActionOnDblClick() final; private: void m_updateOperations(); diff --git a/src/Frontend/Tables/TransactionsTable.cpp b/src/Frontend/Tables/TransactionsTable.cpp new file mode 100644 index 0000000..d740aab --- /dev/null +++ b/src/Frontend/Tables/TransactionsTable.cpp @@ -0,0 +1,76 @@ +#include +#include + +TransactionsTable::TransactionsTable() : ADataTable("TransactionsTable", 5) { +} + +TransactionsTable::~TransactionsTable() { +} + +bool TransactionsTable::load() { + ADataTable::load(); + m_updateTransactions(); + return true; +} + +void TransactionsTable::unload() { + ADataTable::unload(); +} + +bool TransactionsTable::drawMenu() { + if (ADataTable::drawMenu()) { + m_updateTransactions(); + return true; + } + return false; +} + +size_t TransactionsTable::m_getItemsCount() const { + return m_Transactions.size(); +} + +RowID TransactionsTable::m_getItemRowID(const size_t& vIdx) const { + if (vIdx < m_Transactions.size()) { + return m_Transactions.at(vIdx).id; + } + return 0; // the db row id cant be 0 +} + +double TransactionsTable::m_getItemAmount(const size_t& vIdx) const { + return m_Transactions.at(vIdx).amount; +} + +void TransactionsTable::m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) { + const auto& t = m_Transactions.at(vIdx); + m_drawColumnSelectable(vIdx, t.id, t.description); + m_drawColumnDebit(t.debit); + m_drawColumnCredit(t.credit); + m_drawColumnAmount(t.amount); + m_drawColumnBars(t.amount, vMaxAmount); +} + +void TransactionsTable::m_setupColumns() { + ImGui::TableSetupScrollFreeze(0, 1); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Debit", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Credit", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Amount", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("Bars", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableHeadersRow(); +} + +void TransactionsTable::m_drawContextMenuContent() { + CTOOL_DEBUG_BREAK; +} + +void TransactionsTable::m_doActionOnDblClick() { + CTOOL_DEBUG_BREAK; +} + +void TransactionsTable::m_updateTransactions() { + const auto account_id = m_getAccountID(); + if (account_id > 0) { + m_Transactions.clear(); + CTOOL_DEBUG_BREAK; + } +} diff --git a/src/Frontend/Tables/TransactionsTable.h b/src/Frontend/Tables/TransactionsTable.h new file mode 100644 index 0000000..9b18e63 --- /dev/null +++ b/src/Frontend/Tables/TransactionsTable.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +class TransactionsTable : public ADataTable { +private: + std::vector m_Transactions; + +public: + TransactionsTable(); + ~TransactionsTable(); + + bool load(); + void unload(); + bool drawMenu(); + +protected: + size_t m_getItemsCount() const final; + RowID m_getItemRowID(const size_t& vIdx) const final; + double m_getItemAmount(const size_t& vIdx) const final; + void m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) final; + void m_setupColumns() final; + void m_drawContextMenuContent() final; + void m_doActionOnDblClick() final; + +private: + void m_updateTransactions(); +}; diff --git a/src/Frontend/Tables/abstract/ADataTable.cpp b/src/Frontend/Tables/abstract/ADataTable.cpp index ea154f9..41dcfb6 100644 --- a/src/Frontend/Tables/abstract/ADataTable.cpp +++ b/src/Frontend/Tables/abstract/ADataTable.cpp @@ -24,7 +24,7 @@ bool ADataTable::drawMenu() { void ADataTable::draw(const ImVec2& vSize) { ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 30.0f); static auto flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY; - if (ImGui::BeginTable(m_TableName, m_ColummCount, flags, vSize)) { + if (ImGui::BeginTable(m_TableName, m_ColummCount, flags, vSize)) { m_setupColumns(); int32_t idx = 0; double max_amount = DBL_MIN; @@ -37,10 +37,26 @@ void ADataTable::draw(const ImVec2& vSize) { if (idx < 0) { continue; } - m_drawContent((size_t)idx, max_amount); + ImGui::TableNextRow(); + m_drawTableContent((size_t)idx, max_amount); } } m_ListClipper.End(); + + if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { + if (ImGui::IsKeyDown(ImGuiKey_A)) { + m_selectRows(0, m_getItemsCount()); + } + } + + // shift selection + if (ImGui::IsKeyDown(ImGuiMod_Shift) && m_LastSelectedItemIdx > -1 && m_CurrSelectedItemIdx > -1) { + int32_t min_idx = ImMin(m_LastSelectedItemIdx, m_CurrSelectedItemIdx); + int32_t max_idx = ImMax(m_LastSelectedItemIdx, m_CurrSelectedItemIdx); + m_ResetSelection(); + m_selectRows(min_idx, max_idx); + } + ImGui::EndTable(); } ImGui::PopStyleVar(); @@ -79,7 +95,7 @@ double ADataTable::m_computeMaxPrice() { if (idx < 0) { continue; } - const auto& as = std::abs(m_getAmount(idx)); + const auto& as = std::abs(m_getItemAmount(idx)); if (as > max_price) { max_price = as; } @@ -87,6 +103,21 @@ double ADataTable::m_computeMaxPrice() { return max_price; } +void ADataTable::m_showContextMenu(const size_t& vIdx) { + if (!m_SelectedItems.empty()) { + ImGui::PushID(vIdx); + if (ImGui::BeginPopupContextItem( // + NULL, // + ImGuiPopupFlags_NoOpenOverItems | // + ImGuiPopupFlags_MouseButtonRight | // + ImGuiPopupFlags_NoOpenOverExistingPopup)) { + m_drawContextMenuContent(); + ImGui::EndPopup(); + } + ImGui::PopID(); + } +} + RowID ADataTable::m_getAccountID() { if (m_AccountsCombo.getIndex() < m_Accounts.size()) { return m_Accounts.at(m_AccountsCombo.getIndex()).id; @@ -94,6 +125,57 @@ RowID ADataTable::m_getAccountID() { return 0U; } +void ADataTable::m_drawColumnSelectable(const size_t& vIdx, const RowID& vRowID, const std::string& vText) { + ImGui::TableNextColumn(); + ImGui::PushID(vRowID); + auto is_selected = m_IsRowSelected(vRowID); + ImGui::Selectable(vText.c_str(), &is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap); + if (ImGui::IsItemHovered()) { + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { + m_doActionOnDblClick(); + } else if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + if (ImGui::IsKeyDown(ImGuiMod_Shift)) { + m_CurrSelectedItemIdx = vIdx; + } else { + m_LastSelectedItemIdx = vIdx; + if (!ImGui::IsKeyDown(ImGuiMod_Ctrl)) { + m_ResetSelection(); + } + m_SelectOrDeselectRow(vRowID); + } + } + } + ImGui::HideByFilledRectForHiddenMode(SettingsDialog::Instance()->isHiddenMode(), "%s", vText.c_str()); + ImGui::PopID(); + m_showContextMenu(vIdx); +} + +void ADataTable::m_drawColumnText(const std::string& vText) { + ImGui::TableNextColumn(); + ImGui::Text("%s", vText.c_str()); + ImGui::HideByFilledRectForHiddenMode(SettingsDialog::Instance()->isHiddenMode(), "%s", vText.c_str()); +} + +void ADataTable::m_SelectRow(const RowID& vRowID) { + m_SelectedItems.emplace(vRowID); // selection +} + +void ADataTable::m_SelectOrDeselectRow(const RowID& vRowID) { + if (m_SelectedItems.find(vRowID) != m_SelectedItems.end()) { + m_SelectedItems.erase(vRowID); // deselection + } else { + m_SelectedItems.emplace(vRowID); // selection + } +} + +void ADataTable::m_ResetSelection() { + m_SelectedItems.clear(); +} + +bool ADataTable::m_IsRowSelected(const RowID& vRowID) const { + return (m_SelectedItems.find(vRowID) != m_SelectedItems.end()); +} + void ADataTable::m_drawColumnDebit(const double& vDebit) { ImGui::TableNextColumn(); if (vDebit < 0.0) { @@ -152,3 +234,13 @@ void ADataTable::m_drawColumnBars(const double vAmount, const double vMaxAmount) } ImGui::SetCursorScreenPos(pMax); } + +const std::set& ADataTable::m_getSelectedRows() { + return m_SelectedItems; +} + +void ADataTable::m_selectRows(const size_t& vStartIdx, const size_t& vEndIdx) { + for (size_t idx = vStartIdx; idx < vEndIdx; ++idx) { + m_SelectRow(m_getItemRowID(idx)); + } +} \ No newline at end of file diff --git a/src/Frontend/Tables/abstract/ADataTable.h b/src/Frontend/Tables/abstract/ADataTable.h index 7cdeb08..7a9cd93 100644 --- a/src/Frontend/Tables/abstract/ADataTable.h +++ b/src/Frontend/Tables/abstract/ADataTable.h @@ -13,6 +13,9 @@ class ADataTable { float m_TextHeight = 0.0f; ImVec4 m_BadColor = ImVec4(1, 0, 0, 1); ImVec4 m_GoodColor = ImVec4(0, 1, 0, 1); + std::set m_SelectedItems; + int32_t m_CurrSelectedItemIdx = -1; + int32_t m_LastSelectedItemIdx = -1; public: explicit ADataTable(const char* vTableName, const int32_t& vCloumnsCount); @@ -23,17 +26,31 @@ class ADataTable { void draw(const ImVec2& vSize); protected: - virtual double m_getAmount(const size_t& vIdx) = 0; - virtual void m_drawContent(const size_t& vIdx, const double& vMaxAmount) = 0; - virtual size_t m_getItemsCount() = 0; + virtual size_t m_getItemsCount() const = 0; + virtual RowID m_getItemRowID(const size_t& vIdx) const = 0; + virtual double m_getItemAmount(const size_t& vIdx) const = 0; + virtual void m_drawTableContent(const size_t& vIdx, const double& vMaxAmount) = 0; virtual void m_setupColumns() = 0; + virtual void m_drawContextMenuContent() = 0; + virtual void m_doActionOnDblClick() = 0; + +protected: RowID m_getAccountID(); void m_updateAccounts(); + void m_drawColumnSelectable(const size_t& vIdx, const RowID& vRowID, const std::string& vText); + void m_drawColumnText(const std::string& vText); void m_drawColumnDebit(const double& vDebit); void m_drawColumnCredit(const double& vCredit); void m_drawColumnAmount(const double& vAmount); void m_drawColumnBars(const double vAmount, const double vMaxAmount); + const std::set& m_getSelectedRows(); + void m_selectRows(const size_t& vStartIdx, const size_t& vEndIdx); private: + bool m_IsRowSelected(const RowID& vRowID) const; + void m_SelectRow(const RowID& vRowID); + void m_SelectOrDeselectRow(const RowID& vRowID); + void m_ResetSelection(); double m_computeMaxPrice(); + void m_showContextMenu(const size_t& vIdx); }; diff --git a/src/Headers/CashMeBuild.h b/src/Headers/CashMeBuild.h index f263faa..2377f4c 100644 --- a/src/Headers/CashMeBuild.h +++ b/src/Headers/CashMeBuild.h @@ -1,7 +1,7 @@ #pragma once #define CashMe_Prefix "CashMe" -#define CashMe_BuildNumber 618 +#define CashMe_BuildNumber 625 #define CashMe_MinorNumber 0 #define CashMe_MajorNumber 0 -#define CashMe_BuildId "0.0.618" +#define CashMe_BuildId "0.0.625" diff --git a/src/Models/DataBase.cpp b/src/Models/DataBase.cpp index fbd99d0..81f1800 100644 --- a/src/Models/DataBase.cpp +++ b/src/Models/DataBase.cpp @@ -266,6 +266,7 @@ void DataBase::GetEntities(std::function vCallback) { void DataBase::GetEntitiesStats( // const RowID& vAccountID, std::function vCallback) { @@ -274,18 +275,19 @@ void DataBase::GetEntitiesStats( // const auto& select_query = ct::toStr( u8R"( SELECT - entities.name AS new_entity, - ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS new_debit, - ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS new_credit + entities.id, + entities.name, + ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS debit, + ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS credit FROM transactions LEFT JOIN entities ON transactions.entity_id = entities.id WHERE account_id = %u GROUP BY - new_entity + entities.name ORDER BY - new_entity; + entities.name; )", vAccountID); if (m_OpenDB()) { @@ -297,10 +299,11 @@ ORDER BY while (res == SQLITE_OK || res == SQLITE_ROW) { res = sqlite3_step(stmt); if (res == SQLITE_OK || res == SQLITE_ROW) { - auto name = (const char*)sqlite3_column_text(stmt, 0); - auto debit = (TransactionDebit)sqlite3_column_double(stmt, 1); - auto credit = (TransactionCredit)sqlite3_column_double(stmt, 2); - vCallback(name != nullptr ? name : "", debit, credit); + auto row_id = sqlite3_column_int(stmt, 0); + auto name = (const char*)sqlite3_column_text(stmt, 1); + auto debit = (TransactionDebit)sqlite3_column_double(stmt, 2); + auto credit = (TransactionCredit)sqlite3_column_double(stmt, 3); + vCallback(row_id, name != nullptr ? name : "", debit, credit); } } } @@ -382,6 +385,7 @@ void DataBase::GetCategories(std::function vCallback) void DataBase::GetCategoriesStats( // const RowID& vAccountID, std::function vCallback) { @@ -390,18 +394,19 @@ void DataBase::GetCategoriesStats( // const auto& select_query = ct::toStr( u8R"( SELECT - categories.name AS new_category, - ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS new_debit, - ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS new_credit + categories.id, + categories.name, + ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS debit, + ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS credit FROM transactions LEFT JOIN categories ON transactions.category_id = categories.id WHERE account_id = %u GROUP BY - new_category + categories.name ORDER BY - new_category; + categories.name; )", vAccountID); if (m_OpenDB()) { @@ -413,10 +418,11 @@ ORDER BY while (res == SQLITE_OK || res == SQLITE_ROW) { res = sqlite3_step(stmt); if (res == SQLITE_OK || res == SQLITE_ROW) { - auto name = (const char*)sqlite3_column_text(stmt, 0); - auto debit = (TransactionDebit)sqlite3_column_double(stmt, 1); - auto credit = (TransactionCredit)sqlite3_column_double(stmt, 2); - vCallback(name != nullptr ? name : "", debit, credit); + auto row_id = sqlite3_column_int(stmt, 0); + auto name = (const char*)sqlite3_column_text(stmt, 1); + auto debit = (TransactionDebit)sqlite3_column_double(stmt, 2); + auto credit = (TransactionCredit)sqlite3_column_double(stmt, 3); + vCallback(row_id, name != nullptr ? name : "", debit, credit); } } } @@ -498,6 +504,7 @@ void DataBase::GetOperations(std::function vCallback void DataBase::GetOperationsStats( // const RowID& vAccountID, std::function vCallback) { @@ -506,18 +513,19 @@ void DataBase::GetOperationsStats( // const auto& select_query = ct::toStr( u8R"( SELECT - operations.name AS new_operation, - ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS new_debit, - ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS new_credit + operations.id, + operations.name, + ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS debit, + ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS credit FROM transactions LEFT JOIN operations ON transactions.operation_id = operations.id WHERE account_id = %u GROUP BY - new_operation + operations.name ORDER BY - new_operation; + operations.name; )", vAccountID); if (m_OpenDB()) { @@ -529,10 +537,11 @@ ORDER BY while (res == SQLITE_OK || res == SQLITE_ROW) { res = sqlite3_step(stmt); if (res == SQLITE_OK || res == SQLITE_ROW) { - auto name = (const char*)sqlite3_column_text(stmt, 0); - auto debit = (TransactionDebit)sqlite3_column_double(stmt, 1); - auto credit = (TransactionCredit)sqlite3_column_double(stmt, 2); - vCallback(name != nullptr ? name : "", debit, credit); + auto row_id = sqlite3_column_int(stmt, 0); + auto name = (const char*)sqlite3_column_text(stmt, 1); + auto debit = (TransactionDebit)sqlite3_column_double(stmt, 2); + auto credit = (TransactionCredit)sqlite3_column_double(stmt, 3); + vCallback(row_id, name != nullptr ? name : "", debit, credit); } } } diff --git a/src/Models/DataBase.h b/src/Models/DataBase.h index 8c05fa7..611f179 100644 --- a/src/Models/DataBase.h +++ b/src/Models/DataBase.h @@ -55,6 +55,7 @@ class DataBase { void GetEntitiesStats( // const RowID& vAccountID, std::function vCallback); @@ -67,6 +68,7 @@ class DataBase { void GetCategoriesStats( // const RowID& vAccountID, std::function vCallback); @@ -79,6 +81,7 @@ class DataBase { void GetOperationsStats( // const RowID& vAccountID, std::function vCallback); diff --git a/src/Panes/StatsPane.cpp b/src/Panes/StatsPane.cpp index 44102b5..d64fc8f 100644 --- a/src/Panes/StatsPane.cpp +++ b/src/Panes/StatsPane.cpp @@ -124,10 +124,12 @@ void StatsPane::m_updateEntities() { m_Entities.clear(); DataBase::Instance()->GetEntitiesStats( // account_id, - [this](const EntityName& vEntityName, + [this](const RowID& vRowID, + const EntityName& vEntityName, const TransactionDebit& vTransactionDebit, const TransactionCredit& vTransactionCredit) { // Entity e; + e.id = vRowID; e.name = vEntityName; e.debit = vTransactionDebit; e.credit = vTransactionCredit;