aboutsummaryrefslogtreecommitdiff
path: root/core/src/UI/UI_DatabaseView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/UI/UI_DatabaseView.cpp')
-rw-r--r--core/src/UI/UI_DatabaseView.cpp705
1 files changed, 309 insertions, 396 deletions
diff --git a/core/src/UI/UI_DatabaseView.cpp b/core/src/UI/UI_DatabaseView.cpp
index b9d9d81..bc65080 100644
--- a/core/src/UI/UI_DatabaseView.cpp
+++ b/core/src/UI/UI_DatabaseView.cpp
@@ -19,17 +19,24 @@
namespace {
// TODO move to Settings
-constexpr int kMaxEntriesPerPage = 20;
+constexpr int kMaxEntriesPerPage = 32;
constexpr int kSummaryItemCount = 3;
constexpr int kSummaryMaxLength = 25;
+std::pair<int, int> SplitEntryIndex(int entryIdx)
+{
+ int page = entryIdx / kMaxEntriesPerPage;
+ int row = entryIdx % kMaxEntriesPerPage;
+ return { page, row };
+}
+
enum class DeliveryDirection
{
FactoryToWarehouse,
WarehouseToCustomer,
};
-struct ItemEntry
+struct Item
{
int ItemId;
int Count;
@@ -37,7 +44,7 @@ struct ItemEntry
struct DeliveryEntry
{
- std::vector<ItemEntry> Items;
+ std::vector<Item> Items;
std::string ItemsSummary;
std::string ShipmentTime;
std::string ArriveTime;
@@ -52,55 +59,93 @@ struct DeliveryEntry
}
};
+struct SaleEntry
+{
+ static constexpr auto kType = DeliveryDirection::WarehouseToCustomer;
+
+ std::vector<DeliveryEntry> AssociatedDeliveries;
+ std::vector<Item> Items;
+ std::string ItemsSummary;
+ std::string Customer;
+ std::string Deadline;
+ std::string DeliveryTime;
+ int Id;
+ bool DeliveriesCached = false;
+};
+
+struct PurchaseEntry
+{
+ static constexpr auto kType = DeliveryDirection::FactoryToWarehouse;
+
+ std::vector<DeliveryEntry> AssociatedDeliveries;
+ std::vector<Item> Items;
+ std::string ItemsSummary;
+ std::string Factory;
+ std::string OrderTime;
+ std::string DeliveryTime;
+ int Id;
+ bool DeliveriesCached;
+};
+
+template <class T>
class GenericTableView
{
+public:
+ // clang-format off
+ static constexpr bool kHasItems = requires(T t)
+ {
+ t.Items;
+ t.ItemsSummary;
+ };
+ static constexpr bool kHasCustomer = requires(T t) { t.Customer; };
+ static constexpr bool kHasDeadline = requires(T t) { t.Deadline; };
+ static constexpr bool kHasFactory = requires(T t) { t.Factory; };
+ static constexpr bool kHasOrderTime = requires(T t) { t.OrderTime; };
+ static constexpr bool kHasCompletionTime = requires(T t) { t.DeliveryTime; };
+ static constexpr int kColumnCount = kHasItems + kHasCustomer + kHasDeadline + kHasFactory + kHasOrderTime + kHasCompletionTime;
+ // clang-format on
+
+ using Page = std::vector<T>;
+
+ struct QueryStatements
+ {
+ SQLite::Statement* GetRowCount;
+ SQLite::Statement* GetRows;
+ SQLite::Statement* GetItems;
+ SQLite::Statement* FilterRows;
+ } Statements;
+
protected:
// Translation entries for implementer to fill out
const char* mEditDialogTitle;
- SQLite::Statement* mGetRowCountStatement;
- SQLite::Statement* mGetRowsStatement;
- SQLite::Statement* mFilterRowsStatement;
-
Project* mProject;
+ Page* mCurrentPage = nullptr;
/// Current active filter object, or \c nullptr.
std::unique_ptr<TableRowsFilter> mActiveFilter;
- /// Inclusive.
- /// \see mLastCachedRowId
- int64_t mFirstCachedRowId;
- /// Inclusive.
- /// \see mFirstCachedRowId
- int64_t mLastCachedRowId;
+ tsl::robin_map<int, Page> mPages;
- /// A vector of row ids of entries (in \c mEntries) that are visible under the current filter. To use these indices, the elements should be mapped to
- /// index of the list of entries by adding \c mFirstCachedRowId.
- /// The list of entries is a cached, contiguous (row id of each entry is monotonically increasing, but not necessarily starts at 0) list
- /// of ready-to-be-presented entries, held by the implementer.
+ /// A vector of entry indices (in \c mEntries) that are visible under the current filter.
std::vector<int> mActiveEntries;
/// Number of rows in the table.
int mRowCount;
/// Last possible page for the current set table and filter (inclusive).
int mLastPage;
+
/// The current page the user is on.
- int mCurrentPage;
+ int mCurrentPageNumber;
- int mSelectedEntryRowId;
+ /// Row index of the select entry
+ int mSelectRow;
public:
- static int CalcPageForRowId(int64_t rowId)
+ /// Calculate the first visible row's entry index.
+ int GetFirstVisibleRowIdx() const
{
- return rowId / kMaxEntriesPerPage;
- }
-
- /// Calculate range [begin, end) of index for the list of entries that are currently visible that the path-th page would show.
- /// i.e. when there is a filter, look into \c mActiveEntryIndices; when there is no filter, use directly.
- static std::pair<int64_t, int64_t> CalcRangeForPage(int page)
- {
- int begin = page * kMaxEntriesPerPage;
- return { begin, begin + kMaxEntriesPerPage };
+ return mCurrentPageNumber * kMaxEntriesPerPage;
}
Project* GetProject() const
@@ -108,27 +153,27 @@ public:
return mProject;
}
- virtual void OnProjectChanged(Project* newProject)
+ void OnProjectChanged(Project* newProject)
{
mProject = newProject;
- if (mGetRowCountStatement->executeStep()) {
- mRowCount = mGetRowCountStatement->getColumn(0).getInt();
+ auto& stmt = *Statements.GetRowCount;
+ if (stmt.executeStep()) {
+ mRowCount = stmt.getColumn(0).getInt();
} else {
std::cerr << "Failed to fetch row count from SQLite.\n";
mRowCount = 0;
}
- mFirstCachedRowId = 0;
- mLastCachedRowId = 0;
-
- ClearEntries();
+ mActiveFilter = nullptr;
mActiveEntries.clear();
+ mPages.clear();
+ mCurrentPage = nullptr;
UpdateLastPage();
SetPage(0);
- mSelectedEntryRowId = -1;
+ mSelectRow = -1;
}
TableRowsFilter* GetFilter() const
@@ -136,9 +181,9 @@ public:
return mActiveFilter.get();
}
- virtual void OnFilterChanged()
+ void OnFilterChanged()
{
- auto& stmt = *mFilterRowsStatement;
+ auto& stmt = *Statements.FilterRows;
// clang-format off
DEFER { stmt.reset(); };
// clang-format on
@@ -153,7 +198,7 @@ public:
UpdateLastPage();
SetPage(0);
- mSelectedEntryRowId = -1;
+ mSelectRow = -1;
}
void OnFilterChanged(std::unique_ptr<TableRowsFilter> filter)
@@ -162,32 +207,32 @@ public:
OnFilterChanged();
}
- void Draw()
+ void Display()
{
bool dummy = true;
auto ls = LocaleStrings::Instance.get();
- if (ImGui::Button(ICON_FA_ARROW_LEFT, mCurrentPage == 0)) {
- mSelectedEntryRowId = -1;
- SetPage(mCurrentPage - 1);
+ if (ImGui::Button(ICON_FA_ARROW_LEFT, mCurrentPageNumber == 0)) {
+ SetPage(mCurrentPageNumber - 1);
}
ImGui::SameLine();
// +1 to convert from 0-based indices to 1-based, for human legibility
- ImGui::Text("%d/%d", mCurrentPage + 1, mLastPage + 1);
+ ImGui::Text("%d/%d", mCurrentPageNumber + 1, mLastPage + 1);
ImGui::SameLine();
- if (ImGui::Button(ICON_FA_ARROW_RIGHT, mCurrentPage == mLastPage)) {
- mSelectedEntryRowId = -1;
- SetPage(mCurrentPage + 1);
+ if (ImGui::Button(ICON_FA_ARROW_RIGHT, mCurrentPageNumber == mLastPage)) {
+ SetPage(mCurrentPageNumber + 1);
}
ImGui::SameLine();
- if (ImGui::Button(ls->Edit.Get(), mSelectedEntryRowId == -1)) {
+ if (ImGui::Button(ls->Edit.Get(), mSelectRow == -1)) {
ImGui::OpenPopup(mEditDialogTitle);
}
if (ImGui::BeginPopupModal(mEditDialogTitle, &dummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- EditEntry(mSelectedEntryRowId);
+ auto& entry = (*mCurrentPage)[mSelectRow];
+ int entryIdx = GetFirstVisibleRowIdx() + mSelectRow;
+ EditEntry(entry, entryIdx, mSelectRow);
ImGui::EndPopup();
}
@@ -197,42 +242,74 @@ public:
}
ImGui::SameLine();
- if (ImGui::Button(ls->Delete.Get(), mSelectedEntryRowId == -1)) {
+ if (ImGui::Button(ls->Delete.Get(), mSelectRow == -1)) {
// TODO
}
ImGui::Columns(2);
{
- DrawMainTable();
+ DisplayMainTable();
ImGui::NextColumn();
- if (mSelectedEntryRowId == -1) {
+ if (mSelectRow == -1) {
ImGui::TextWrapped("%s", ls->SelectOrderToShowAssociatedDeliveries.Get());
} else {
- DrawDeliveriesTable();
+ DisplayDeliveriesTable();
}
ImGui::NextColumn();
}
ImGui::Columns(1);
}
- void DrawMainTable()
+ void SetPage(int page)
{
- if (ImGui::BeginTable("DataTable", GetTableColumnCount(), ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX)) {
- SetupTableColumns();
+ mCurrentPageNumber = page;
+ mCurrentPage = &LoadAndGetPage(page);
+ mSelectRow = -1;
+ }
+
+private:
+ static int CalcPageForRowId(int64_t entryIdx)
+ {
+ return entryIdx / kMaxEntriesPerPage;
+ }
+
+ /// Calculate range [begin, end) of index for the list of entries that are currently visible that the path-th page would show.
+ /// i.e. when there is a filter, look into \c mActiveEntryIndices; when there is no filter, use directly.
+ static std::pair<int64_t, int64_t> CalcRangeForPage(int page)
+ {
+ int begin = page * kMaxEntriesPerPage;
+ return { begin, begin + kMaxEntriesPerPage };
+ }
+
+ void DisplayMainTable()
+ {
+ auto ls = LocaleStrings::Instance.get();
+ if (ImGui::BeginTable("DataTable", kColumnCount, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX)) {
+
+ if constexpr (kHasCustomer) ImGui::TableSetupColumn(ls->DatabaseCustomerColumn.Get());
+ if constexpr (kHasDeadline) ImGui::TableSetupColumn(ls->DatabaseDeadlineColumn.Get());
+ if constexpr (kHasFactory) ImGui::TableSetupColumn(ls->DatabaseFactoryColumn.Get());
+ if constexpr (kHasOrderTime) ImGui::TableSetupColumn(ls->DatabaseOrderTimeColumn.Get());
+ if constexpr (kHasCompletionTime) ImGui::TableSetupColumn(ls->DatabaseCompletionTimeColumn.Get());
+ if constexpr (kHasItems) ImGui::TableSetupColumn(ls->DatabaseItemsColumn.Get());
ImGui::TableHeadersRow();
- auto [begin, end] = CalcRangeForPage(mCurrentPage);
if (mActiveFilter) {
+ // TODO
+ auto [begin, end] = CalcRangeForPage(mCurrentPageNumber);
end = std::min(end, (int64_t)mActiveEntries.size() - 1);
for (int i = begin; i < end; ++i) {
- int rowId = mActiveEntries[i];
- DisplayEntry(rowId);
+ int rowIdx = mActiveEntries[i];
+ DisplayEntry(rowIdx);
}
} else {
- end = std::min(end, mLastCachedRowId);
- for (int rowId = begin; rowId < end; ++rowId) {
- DisplayEntry(rowId);
+ int firstRowIdx = mCurrentPageNumber * kMaxEntriesPerPage;
+ auto& page = *mCurrentPage;
+
+ int end = std::min((int)page.size(), kMaxEntriesPerPage);
+ for (int i = 0; i < end; ++i) {
+ DisplayEntry(page[i], i, firstRowIdx + i);
}
}
@@ -240,7 +317,71 @@ public:
}
}
- void DrawDeliveriesTable()
+ void DisplayEntry(int rowIdx)
+ {
+ // TODO
+ // auto [pageNumber, pageEntry] = SplitRowIndex(rowIdx);
+ // auto& entry = LoadAndGetPage(pageNumber)[pageEntry];
+ // DisplayEntry(entry, rowIdx);
+ }
+
+ void DisplayEntry(T& entry, int rowIdx, int entryIdx)
+ {
+ auto ls = LocaleStrings::Instance.get();
+
+ ImGui::PushID(rowIdx);
+ ImGui::TableNextRow();
+
+ if constexpr (kHasCustomer) {
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(entry.Customer.c_str(), mSelectRow == rowIdx, ImGuiSelectableFlags_SpanAllColumns)) {
+ mSelectRow = rowIdx;
+ }
+ }
+
+ if constexpr (kHasDeadline) {
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(entry.Deadline.c_str());
+ }
+
+ if constexpr (kHasFactory) {
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(entry.Factory.c_str(), mSelectRow == rowIdx, ImGuiSelectableFlags_SpanAllColumns)) {
+ mSelectRow = rowIdx;
+ }
+ }
+
+ if constexpr (kHasOrderTime) {
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(entry.OrderTime.c_str());
+ }
+
+ if constexpr (kHasCompletionTime) {
+ ImGui::TableNextColumn();
+ if (entry.DeliveryTime.empty()) {
+ ImGui::TextUnformatted(ls->NotDelivered.Get());
+ } else {
+ ImGui::TextUnformatted(entry.DeliveryTime.c_str());
+ }
+ }
+
+ if constexpr (kHasItems) {
+ ImGui::TableNextColumn();
+ if (ImGui::TreeNode(entry.ItemsSummary.c_str())) {
+ DrawItems(entry.Items);
+ ImGui::TreePop();
+ }
+ }
+
+ ImGui::PopID();
+ }
+
+ void EditEntry(T& entry, int rowIdx, int entryIdx)
+ {
+ // TODO
+ }
+
+ void DisplayDeliveriesTable()
{
auto ls = LocaleStrings::Instance.get();
if (ImGui::BeginTable("DeliveriesTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollX)) {
@@ -250,7 +391,8 @@ public:
ImGui::TableSetupColumn(ls->DatabaseItemsColumn.Get());
ImGui::TableHeadersRow();
- auto& deliveries = GetEntryAssociatedDeliveries(mSelectedEntryRowId);
+ auto& entry = (*mCurrentPage)[mSelectRow];
+ auto& deliveries = entry.AssociatedDeliveries;
for (auto& delivery : deliveries) {
ImGui::TableNextRow();
@@ -271,35 +413,19 @@ public:
}
}
- void SetPage(int page)
- {
- mCurrentPage = page;
- EnsureCacheCoversPage(page);
- }
-
- int RowIdToIndex(int64_t rowId) const
- {
- return rowId - mFirstCachedRowId;
- }
-
- int64_t IndexToRowId(int index) const
- {
- return index + mFirstCachedRowId;
- }
-
- std::vector<ItemEntry> LoadItems(SQLite::Statement& stmt, int64_t rowId)
+ std::vector<Item> LoadItems(SQLite::Statement& stmt, int64_t id)
{
// clang-format off
DEFER { stmt.reset(); };
// clang-format on
- stmt.bind(1, rowId);
+ stmt.bind(1, id);
- std::vector<ItemEntry> entries;
+ std::vector<Item> entries;
int itemIdCol = stmt.getColumnIndex("ItemId");
int countCol = stmt.getColumnIndex("Count");
while (stmt.executeStep()) {
- entries.push_back(ItemEntry{
+ entries.push_back(Item{
.ItemId = stmt.getColumn(itemIdCol).getInt(),
.Count = stmt.getColumn(countCol).getInt(),
});
@@ -308,7 +434,7 @@ public:
return entries;
}
- std::string CreateItemsSummary(const std::vector<ItemEntry>& items)
+ std::string CreateItemsSummary(const std::vector<Item>& items)
{
if (items.empty()) {
return "<empty>";
@@ -334,7 +460,7 @@ public:
return result;
}
- std::vector<DeliveryEntry> LoadDeliveriesEntries(int64_t orderRowId, DeliveryDirection type)
+ std::vector<DeliveryEntry> LoadDeliveriesEntries(int64_t orderId, DeliveryDirection type)
{
bool outgoingFlag;
switch (type) {
@@ -347,7 +473,7 @@ public:
DEFER { stmt.reset(); };
// clang-format on
- stmt.bind(1, orderRowId);
+ stmt.bind(1, orderId);
stmt.bind(2, outgoingFlag);
std::vector<DeliveryEntry> entries;
@@ -372,94 +498,96 @@ public:
return entries;
}
-protected:
- virtual int GetTableColumnCount() const = 0;
- virtual void SetupTableColumns() = 0;
+ Page& LoadAndGetPage(int page)
+ {
+ auto iter = mPages.find(page);
+ if (iter != mPages.end()) {
+ return iter.value();
+ }
- virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) = 0;
- virtual void DisplayEntry(int rowId) = 0;
- virtual void EditEntry(int rowId) = 0;
+ auto& stmt = *Statements.GetRows;
+ // clang-format off
+ DEFER { stmt.reset(); };
+ // clang-format on
- virtual void ClearEntries() = 0;
+ stmt.bind(1, kMaxEntriesPerPage);
+ stmt.bind(2, page * kMaxEntriesPerPage);
- void DrawItems(const std::vector<ItemEntry>& items)
- {
- for (auto& item : items) {
- auto& name = mProject->Products.Find(item.ItemId)->GetName();
- ImGui::Text("%s × %d", name.c_str(), item.Count);
- }
- }
+ // If a field flag is false, the column index won't be used (controlled by other if constexpr's downstream)
+ // so there is no UB here
- void EnsureCacheCoversPage(int page)
- {
- auto [begin, end] = CalcRangeForPage(page);
- EnsureCacheCovers(begin, end - 1);
- }
+ // This column is always necessary (and present) because the deliveries table require it
+ int idCol = stmt.getColumnIndex("Id");
- void EnsureCacheCovers(int64_t firstRow, int64_t lastRow)
- {
- if (firstRow > lastRow) {
- std::swap(firstRow, lastRow);
- }
+ int customerCol;
+ if constexpr (kHasCustomer) customerCol = stmt.getColumnIndex("Customer");
- int newFirst = mFirstCachedRowId;
- int newLast = mLastCachedRowId;
+ int deadlineCol;
+ if constexpr (kHasDeadline) deadlineCol = stmt.getColumnIndex("Deadline");
- bool doRebuild = false;
- if (firstRow < mFirstCachedRowId) {
- newFirst = (CalcPageForRowId(firstRow) + 1) * kMaxEntriesPerPage;
- doRebuild = true;
- }
- if (lastRow > mLastCachedRowId) {
- newLast = (CalcPageForRowId(lastRow) + 1) * kMaxEntriesPerPage;
- doRebuild = true;
- }
- if (!doRebuild) return;
+ int factoryCol;
+ if constexpr (kHasFactory) factoryCol = stmt.getColumnIndex("Factory");
- EnsureCacheCoversImpl(newFirst, newLast);
- }
+ int orderTimeCol;
+ if constexpr (kHasOrderTime) orderTimeCol = stmt.getColumnIndex("OrderTime");
- /// To be implemented by child classes, presumable calling LoadRange() to get the front and back new contents.
- /// \param newFirst The first rowid the new cache should cover
- /// \param newLast The last rowid the new cache should cover
- virtual void EnsureCacheCoversImpl(int newFirst, int newLast) = 0;
+ int deliveryTimeCol;
+ if constexpr (kHasCompletionTime) deliveryTimeCol = stmt.getColumnIndex("DeliveryTime");
- template <class TEntry, class TCollector>
- void LoadExtraEntries(std::vector<TEntry>& entries, int newFirst, int newLast, TCollector&& collector)
- {
- auto front = LoadRange<TEntry>(newFirst, mFirstCachedRowId, collector);
- auto back = LoadRange<TEntry>(mLastCachedRowId + 1, newLast + 1, collector);
+ Page entries;
+ while (stmt.executeStep()) {
+ auto& entry = entries.emplace_back();
- mFirstCachedRowId -= front.size();
- mLastCachedRowId += back.size();
+ auto id = stmt.getColumn(idCol).getInt64();
+ entry.AssociatedDeliveries = LoadDeliveriesEntries(id, T::kType);
- entries.insert(entries.begin(), std::make_move_iterator(front.begin()), std::make_move_iterator(front.end()));
- entries.insert(entries.end(), std::make_move_iterator(back.begin()), std::make_move_iterator(back.end()));
- }
+ if constexpr (kHasItems) {
+ auto items = LoadItems(
+ *Statements.GetItems,
+ id);
+ auto itemsSummary = CreateItemsSummary(items);
+ entry.Items = std::move(items);
+ entry.ItemsSummary = std::move(itemsSummary);
+ }
- template <class TEntry, class TCollector>
- std::vector<TEntry> LoadRange(int64_t begin, int64_t end, TCollector&& collector)
- {
- std::vector<TEntry> result;
+ if constexpr (kHasCustomer) {
+ auto customerId = stmt.getColumn(customerCol).getInt();
+ entry.Customer = mProject->Customers.Find(customerId)->GetName();
+ }
- size_t size = end - begin;
- if (size == 0) {
- return result;
- }
+ if constexpr (kHasDeadline) {
+ auto timeStamp = stmt.getColumn(deadlineCol).getInt64();
+ entry.Deadline = StringifyTimeStamp(timeStamp);
+ }
- result.reserve(size);
+ if constexpr (kHasFactory) {
+ auto factoryId = stmt.getColumn(factoryCol).getInt();
+ entry.Factory = mProject->Factories.Find(factoryId)->GetName();
+ }
- // clang-format off
- DEFER { mGetRowsStatement->reset(); };
- // clang-format on
- mGetRowsStatement->bind(1, begin);
- mGetRowsStatement->bind(2, end);
+ if constexpr (kHasOrderTime) {
+ auto timeStamp = stmt.getColumn(orderTimeCol).getInt64();
+ entry.OrderTime = StringifyTimeStamp(timeStamp);
+ }
- collector(result);
- return result;
+ if constexpr (kHasCompletionTime) {
+ auto timeStamp = stmt.getColumn(deliveryTimeCol).getInt64();
+ entry.DeliveryTime = StringifyTimeStamp(timeStamp);
+ }
+ }
+
+ auto [res, _] = mPages.try_emplace(page, std::move(entries));
+ return res.value();
+ }
+
+ void DrawItems(const std::vector<Item>& items)
+ {
+ for (auto& item : items) {
+ auto& name = mProject->Products.Find(item.ItemId)->GetName();
+ ImGui::Text("%s × %d", name.c_str(), item.Count);
+ }
}
-private:
void UpdateLastPage()
{
mLastPage = mActiveEntries.empty()
@@ -468,23 +596,8 @@ private:
}
};
-struct SaleEntry
+class SalesTableView : public GenericTableView<SaleEntry>
{
- std::vector<DeliveryEntry> AssociatedDeliveries;
- std::vector<ItemEntry> Items;
- std::string ItemsSummary;
- std::string Customer;
- std::string Deadline;
- std::string DeliveryTime;
- bool DeliveriesCached = false;
-};
-
-class SalesTableView : public GenericTableView
-{
-private:
- /// A cached, contiguous (row id of each entry is monotonically increasing, but not necessarily starts at 0) list ready-to-be-presented entries. May be incomplete.
- std::vector<SaleEntry> mEntries;
-
public:
SalesTableView()
{
@@ -492,129 +605,24 @@ public:
mEditDialogTitle = ls->EditSaleEntryDialogTitle.Get();
}
- virtual void OnProjectChanged(Project* newProject) override
- {
- auto& sales = newProject->GetTransactionsModel().GetSales();
- mGetRowCountStatement = &sales.GetRowCount;
- mGetRowsStatement = &sales.GetRows;
- // mFilterRowsStatement = &sales.FilterRows;
-
- GenericTableView::OnProjectChanged(newProject);
- }
-
-protected:
- virtual int GetTableColumnCount() const override
- {
- return 4;
- }
-
- virtual void SetupTableColumns() override
- {
- auto ls = LocaleStrings::Instance.get();
- ImGui::TableSetupColumn(ls->DatabaseCustomerColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseDeadlineColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseCompletionTimeColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseItemsColumn.Get());
- }
-
- virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) override
- {
- auto& entry = mEntries[RowIdToIndex(rowId)];
- if (!entry.DeliveriesCached) {
- entry.AssociatedDeliveries = LoadDeliveriesEntries(rowId, DeliveryDirection::FactoryToWarehouse);
- entry.DeliveriesCached = true;
- }
- return entry.AssociatedDeliveries;
- }
-
- virtual void DisplayEntry(int rowId) override
- {
- auto& entry = mEntries[RowIdToIndex(rowId)];
- auto ls = LocaleStrings::Instance.get();
-
- ImGui::PushID(rowId);
- ImGui::TableNextRow();
-
- ImGui::TableNextColumn();
- if (ImGui::Selectable(entry.Customer.c_str(), mSelectedEntryRowId == rowId, ImGuiSelectableFlags_SpanAllColumns)) {
- mSelectedEntryRowId = rowId;
- }
-
- ImGui::TableNextColumn();
- ImGui::TextUnformatted(entry.Deadline.c_str());
-
- ImGui::TableNextColumn();
- if (entry.DeliveryTime.empty()) {
- ImGui::TextUnformatted(ls->NotDelivered.Get());
- } else {
- ImGui::TextUnformatted(entry.DeliveryTime.c_str());
- }
-
- ImGui::TableNextColumn();
- if (ImGui::TreeNode(entry.ItemsSummary.c_str())) {
- DrawItems(entry.Items);
- ImGui::TreePop();
- }
-
- ImGui::PopID();
- }
-
- virtual void EditEntry(int rowId) override
+#pragma clang diagnostic push
+#pragma ide diagnostic ignored "HidingNonVirtualFunction"
+ void OnProjectChanged(Project* newProject)
{
+ auto& table = newProject->GetTransactionsModel().GetSales();
+ Statements.GetRowCount = &table.GetRowCount;
+ Statements.GetRows = &table.GetRows;
+ Statements.GetItems = &table.GetItems;
// TODO
- }
+ // stmts.FilterRowsStatement = ;
- virtual void ClearEntries() override
- {
- mEntries.clear();
+ GenericTableView<SaleEntry>::OnProjectChanged(newProject);
}
-
- virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override
- {
- auto CollectRows = [&](std::vector<SaleEntry>& result) {
- auto& stmt = *mGetRowsStatement;
- int rowIdCol = stmt.getColumnIndex("Id");
- int customerCol = stmt.getColumnIndex("Customer");
- int deadlineCol = stmt.getColumnIndex("Deadline");
- int deliveryTimeCol = stmt.getColumnIndex("DeliveryTime");
-
- while (stmt.executeStep()) {
- auto customerId = stmt.getColumn(customerCol).getInt();
- auto items = LoadItems(
- mProject->GetTransactionsModel().GetSales().GetItems,
- stmt.getColumn(rowIdCol).getInt64());
- auto itemsSummary = CreateItemsSummary(items);
-
- result.push_back(SaleEntry{
- .Items = std::move(items),
- .ItemsSummary = std::move(itemsSummary),
- .Customer = mProject->Customers.Find(customerId)->GetName(),
- .Deadline = StringifyTimeStamp(stmt.getColumn(deadlineCol).getInt64()),
- .DeliveryTime = StringifyTimeStamp(stmt.getColumn(deliveryTimeCol).getInt64()),
- });
- }
- };
-
- LoadExtraEntries<SaleEntry>(mEntries, newFirst, newLast, CollectRows);
- }
-};
-
-struct PurchaseEntry
-{
- std::vector<DeliveryEntry> AssociatedDeliveries;
- std::vector<ItemEntry> Items;
- std::string ItemsSummary;
- std::string Factory;
- std::string OrderTime;
- std::string DeliveryTime;
- bool DeliveriesCached;
+#pragma clang diagnostic pop
};
-class PurchasesTableView : public GenericTableView
+class PurchasesTableView : public GenericTableView<PurchaseEntry>
{
-private:
- std::vector<PurchaseEntry> mEntries;
-
public:
PurchasesTableView()
{
@@ -622,115 +630,20 @@ public:
mEditDialogTitle = ls->EditPurchaseEntryDialogTitle.Get();
}
- virtual void OnProjectChanged(Project* newProject) override
- {
- auto& purchases = newProject->GetTransactionsModel().GetPurchases();
- mGetRowCountStatement = &purchases.GetRowCount;
- mGetRowsStatement = &purchases.GetRows;
- // mFilterRowsStatement = &purchases.FilterRowsStatement;
-
- GenericTableView::OnProjectChanged(newProject);
- }
-
-protected:
- virtual int GetTableColumnCount() const override
- {
- return 4;
- }
-
- virtual void SetupTableColumns() override
- {
- auto ls = LocaleStrings::Instance.get();
- ImGui::TableSetupColumn(ls->DatabaseFactoryColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseOrderTimeColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseCompletionTimeColumn.Get());
- ImGui::TableSetupColumn(ls->DatabaseItemsColumn.Get());
- }
-
- virtual const std::vector<DeliveryEntry>& GetEntryAssociatedDeliveries(int rowId) override
- {
- auto& entry = mEntries[RowIdToIndex(rowId)];
- if (!entry.DeliveriesCached) {
- entry.AssociatedDeliveries = LoadDeliveriesEntries(rowId, DeliveryDirection::FactoryToWarehouse);
- entry.DeliveriesCached = true;
- }
- return entry.AssociatedDeliveries;
- }
-
- virtual void DisplayEntry(int rowId) override
- {
- auto& entry = mEntries[RowIdToIndex(rowId)];
- auto ls = LocaleStrings::Instance.get();
-
- ImGui::PushID(rowId);
- ImGui::TableNextRow();
-
- ImGui::TableNextColumn();
- if (ImGui::Selectable(entry.Factory.c_str(), mSelectedEntryRowId == rowId, ImGuiSelectableFlags_SpanAllColumns)) {
- mSelectedEntryRowId = rowId;
- }
-
- ImGui::TableNextColumn();
- if (entry.OrderTime.empty()) {
- ImGui::TextUnformatted(ls->NotDelivered.Get());
- } else {
- ImGui::TextUnformatted(entry.OrderTime.c_str());
- }
-
- ImGui::TableNextColumn();
- if (entry.DeliveryTime.empty()) {
- ImGui::TextUnformatted(ls->NotDelivered.Get());
- } else {
- ImGui::TextUnformatted(entry.DeliveryTime.c_str());
- }
-
- ImGui::TableNextColumn();
- if (ImGui::TreeNode(entry.ItemsSummary.c_str())) {
- DrawItems(entry.Items);
- ImGui::TreePop();
- }
-
- ImGui::PopID();
- }
-
- virtual void EditEntry(int rowId) override
+#pragma clang diagnostic push
+#pragma ide diagnostic ignored "HidingNonVirtualFunction"
+ void OnProjectChanged(Project* newProject)
{
+ auto& table = newProject->GetTransactionsModel().GetPurchases();
+ Statements.GetRowCount = &table.GetRowCount;
+ Statements.GetRows = &table.GetRows;
+ Statements.GetItems = &table.GetItems;
// TODO
- }
-
- virtual void ClearEntries() override
- {
- mEntries.clear();
- }
-
- virtual void EnsureCacheCoversImpl(int newFirst, int newLast) override
- {
- auto CollectRows = [&](std::vector<PurchaseEntry>& result) {
- auto& stmt = *mGetRowsStatement;
- int rowIdCol = stmt.getColumnIndex("Id");
- int factoryCol = stmt.getColumnIndex("Factory");
- int orderTimeCol = stmt.getColumnIndex("OrderTime");
- int deliveryTimeCol = stmt.getColumnIndex("DeliveryTime");
-
- while (stmt.executeStep()) {
- auto factoryId = stmt.getColumn(factoryCol).getInt();
- auto items = LoadItems(
- mProject->GetTransactionsModel().GetPurchases().GetItems,
- stmt.getColumn(rowIdCol).getInt64());
- auto itemsSummary = CreateItemsSummary(items);
-
- result.push_back(PurchaseEntry{
- .Items = std::move(items),
- .ItemsSummary = std::move(itemsSummary),
- .Factory = mProject->Factories.Find(factoryId)->GetName(),
- .OrderTime = StringifyTimeStamp(stmt.getColumn(orderTimeCol).getInt64()),
- .DeliveryTime = StringifyTimeStamp(stmt.getColumn(deliveryTimeCol).getInt64()),
- });
- }
- };
+ // stmts.FilterRowsStatement = ;
- LoadExtraEntries<PurchaseEntry>(mEntries, newFirst, newLast, CollectRows);
+ GenericTableView<PurchaseEntry>::OnProjectChanged(newProject);
}
+#pragma clang diagnostic pop
};
} // namespace
@@ -751,11 +664,11 @@ void UI::DatabaseViewTab()
if (ImGui::BeginTabBar("##DatabaseViewTabs")) {
if (ImGui::BeginTabItem(ls->SalesViewTab.Get())) {
- sales.Draw();
+ sales.Display();
ImGui::EndTabItem();
}
if (ImGui::BeginTabItem(ls->PurchasesViewTab.Get())) {
- purchases.Draw();
+ purchases.Display();
ImGui::EndTabItem();
}
ImGui::EndTabBar();