ORE Studio 0.0.4
Loading...
Searching...
No Matches
ClientCurrencyModel.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * Copyright (C) 2024 Marco Craveiro <marco.craveiro@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 51
17 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20#ifndef ORES_QT_CLIENT_CURRENCY_MODEL_HPP
21#define ORES_QT_CLIENT_CURRENCY_MODEL_HPP
22
23#include <vector>
24#include <unordered_set>
25#include <QSize>
26#include <QFutureWatcher>
27#include <QAbstractTableModel>
28#include "ores.qt/AbstractClientModel.hpp"
29#include "ores.qt/ClientManager.hpp"
30#include "ores.qt/RecencyPulseManager.hpp"
31#include "ores.qt/RecencyTracker.hpp"
32#include "ores.qt/ColumnMetadata.hpp"
33#include "ores.logging/make_logger.hpp"
34#include "ores.refdata.api/domain/currency.hpp"
35
36namespace ores::qt {
37
38class ImageCache;
39
47 Q_OBJECT
48
49private:
50 inline static std::string_view logger_name =
51 "ores.qt.client_currency_model";
52
53 [[nodiscard]] static auto& lg() {
54 using namespace ores::logging;
55 static auto instance = make_logger(logger_name);
56 return instance;
57 }
58
59public:
66 enum Column {
67 IsoCode,
68 CurrencyName,
69 NumericCode,
70 Symbol,
71 FractionSymbol,
72 FractionsPerUnit,
73 RoundingType,
74 RoundingPrecision,
75 Format,
76 MonetaryNature,
77 MarketTier,
78 Version,
79 ModifiedBy,
80 RecordedAt,
81 ColumnCount // Must be last - represents total number of columns
82 };
83
89 static constexpr std::size_t kColumnCount = std::size_t(ColumnCount);
90 static constexpr std::array<ColumnMetadata, kColumnCount> kColumns = {{
91 {
92 .column = IsoCode,
93 .header = std::string_view("Code"),
95 .hidden_by_default = false,
96 .default_width = kColumnWidthAuto
97 },
98 {
99 .column = CurrencyName,
100 .header = std::string_view("Currency Name"),
102 .hidden_by_default = false,
103 .default_width = kColumnWidthAuto},
104 {
105 .column = NumericCode,
106 .header = std::string_view("Numeric Code"),
108 .hidden_by_default = false,
109 .default_width = 70
110 },
111 {
112 .column = Symbol,
113 .header = std::string_view("Symbol"),
115 .hidden_by_default = false,
116 .default_width = 60
117 },
118 {
119 .column = FractionSymbol,
120 .header = std::string_view("Fraction"),
122 .hidden_by_default = true,
123 .default_width = 60
124 },
125 {
126 .column = FractionsPerUnit,
127 .header = std::string_view("Per Unit"),
129 .hidden_by_default = true,
130 .default_width = 70
131 },
132 {
133 .column = RoundingType,
134 .header = std::string_view("Rounding Type"),
136 .hidden_by_default = true,
137 .default_width = kColumnWidthAuto
138 },
139 {
140 .column = RoundingPrecision,
141 .header = std::string_view("Precision"),
143 .hidden_by_default = true,
144 .default_width = 70
145 },
146 {
147 .column = Format,
148 .header = std::string_view("Format"),
150 .hidden_by_default = true,
151 .default_width = kColumnWidthAuto
152 },
153 {
154 .column = MonetaryNature,
155 .header = std::string_view("Monetary Nature"),
157 .hidden_by_default = true,
158 .default_width = kColumnWidthAuto
159 },
160 {
161 .column = MarketTier,
162 .header = std::string_view("Market Tier"),
164 .hidden_by_default = true,
165 .default_width = kColumnWidthAuto
166 },
167 {
168 .column = Version,
169 .header = std::string_view("Version"),
171 .hidden_by_default = false,
172 .default_width = 70
173 },
174 {
175 .column = ModifiedBy,
176 .header = std::string_view("Modified By"),
178 .hidden_by_default = false,
179 .default_width = kColumnWidthAuto
180 },
181 {
182 .column = RecordedAt,
183 .header = std::string_view("Recorded At"),
185 .hidden_by_default = false,
186 .default_width = kColumnWidthAuto
187 },
188 }};
189
193 inline static const QSize kDefaultWindowSize = {1000, 600};
194
198 static constexpr std::string_view kSettingsGroup = "CurrencyListWindow";
199
203 static std::vector<column_style> const& columnStyles() {
204 static std::vector<column_style> const kStylesVector = []() {
205 std::vector<column_style> result;
206 result.reserve(kColumnCount);
207 for (std::size_t i = 0; i < kColumnCount; ++i)
208 result.push_back(kColumns[i].style);
209 return result;
210 }();
211 return kStylesVector;
212 }
213
217 static QVector<int> defaultHiddenColumns() {
218 static QVector<int> const result =
219 ::ores::qt::defaultHiddenColumns<kColumnCount>(kColumns);
220 return result;
221 }
222
223 explicit ClientCurrencyModel(ClientManager* clientManager,
224 ImageCache* imageCache,
225 QObject* parent = nullptr);
226 ~ClientCurrencyModel() override = default;
227
228 // QAbstractTableModel interface
229 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
230 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
231 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
232 QVariant headerData(int section, Qt::Orientation orientation,
233 int role = Qt::DisplayRole) const override;
234
241 void refresh(bool replace = true);
242
252 void load_page(std::uint32_t offset, std::uint32_t limit);
253
260 const refdata::domain::currency* getCurrency(int row) const;
261
267 std::vector<refdata::domain::currency> getCurrencies() const;
268
274 std::uint32_t page_size() const { return page_size_; }
275
281 void set_page_size(std::uint32_t size);
282
288 std::uint32_t total_available_count() const { return total_available_count_; }
289
298 void add_synthetic_currencies(std::vector<refdata::domain::currency> currencies);
299
306 bool is_synthetic(const std::string& iso_code) const;
307
315 void mark_as_saved(const std::string& iso_code);
316
323
324signals:
333private slots:
334 void onCurrenciesLoaded();
335 void onPulseStateChanged(bool isOn);
336 void onPulsingComplete();
337
338private:
350 QVariant foreground_color(const std::string& iso_code) const;
351
352 struct FetchResult {
353 bool success;
354 std::vector<refdata::domain::currency> currencies;
355 std::uint32_t total_available_count;
356 QString error_message;
357 QString error_details;
358 };
359
360 using FutureWatcherResult = FetchResult;
361
362 ClientManager* clientManager_;
363 ImageCache* imageCache_;
364 std::vector<refdata::domain::currency> currencies_;
365 QFutureWatcher<FutureWatcherResult>* watcher_;
366 std::uint32_t page_size_{100};
367 std::uint32_t total_available_count_{0};
368 bool is_fetching_{false};
369
370 // Recency highlighting
371 using CurrencyKeyExtractor = std::string(*)(const refdata::domain::currency&);
372 RecencyTracker<refdata::domain::currency, CurrencyKeyExtractor> recencyTracker_;
373 RecencyPulseManager* pulseManager_;
374
378 void fetch_currencies(std::uint32_t offset, std::uint32_t limit);
379
380 // Synthetic currency tracking (generated but not yet saved)
381 std::unordered_set<std::string> synthetic_iso_codes_;
382};
383
384}
385
386#endif
Implements logging infrastructure for ORE Studio.
Definition boost_severity.hpp:28
Qt-based graphical user interface for ORE Studio.
Definition AboutDialog.hpp:29
constexpr int kColumnWidthAuto
Sentinel value for column default width meaning "auto-size to contents".
Definition ColumnMetadata.hpp:37
@ mono_center
Monospace, centered.
@ text_left
Proportional font, left-aligned (default).
@ mono_bold_left
Monospace bold, left-aligned.
@ mono_right
Monospace, right-aligned.
@ mono_left
Monospace, left-aligned.
Base class for all client-side entity models.
Definition AbstractClientModel.hpp:36
Model for displaying currencies fetched from the server via client.
Definition ClientCurrencyModel.hpp:46
static constexpr std::string_view kSettingsGroup
Settings group name for persisting window and column state.
Definition ClientCurrencyModel.hpp:198
void set_page_size(std::uint32_t size)
Set the page size for pagination.
Definition ClientCurrencyModel.cpp:310
void clear_synthetic_markers()
Clear all synthetic currency markers.
Definition ClientCurrencyModel.cpp:384
static constexpr std::size_t kColumnCount
Column metadata: header text, style, visibility, and width.
Definition ClientCurrencyModel.hpp:89
void add_synthetic_currencies(std::vector< refdata::domain::currency > currencies)
Add synthetic (generated) currencies to the model.
Definition ClientCurrencyModel.cpp:337
static const QSize kDefaultWindowSize
Default window size for the currency list window.
Definition ClientCurrencyModel.hpp:193
static std::vector< column_style > const & columnStyles()
Returns a static vector of column styles (built once per process).
Definition ClientCurrencyModel.hpp:203
void mark_as_saved(const std::string &iso_code)
Mark a synthetic currency as saved (no longer synthetic).
Definition ClientCurrencyModel.cpp:364
std::uint32_t total_available_count() const
Get the total number of records available on the server.
Definition ClientCurrencyModel.hpp:288
static QVector< int > defaultHiddenColumns()
Returns a static QVector of hidden column indices (built once per process).
Definition ClientCurrencyModel.hpp:217
const refdata::domain::currency * getCurrency(int row) const
Get currency at the specified row.
Definition ClientCurrencyModel.cpp:299
std::vector< refdata::domain::currency > getCurrencies() const
Get all currencies.
Definition ClientCurrencyModel.cpp:306
void refresh(bool replace=true)
Refresh currency data from server asynchronously.
Definition ClientCurrencyModel.cpp:166
void load_page(std::uint32_t offset, std::uint32_t limit)
Load a specific page of currency data.
Definition ClientCurrencyModel.cpp:192
std::uint32_t page_size() const
Get the page size used for pagination.
Definition ClientCurrencyModel.hpp:274
Column
Enumeration of table columns for type-safe column access.
Definition ClientCurrencyModel.hpp:66
bool is_synthetic(const std::string &iso_code) const
Check if a currency is synthetic (generated but not saved).
Definition ClientCurrencyModel.cpp:360
Manages the lifecycle of the NATS client and login state.
Definition ClientManager.hpp:109
Cache for dynamically loaded images (flags, icons) from the server.
Definition ImageCache.hpp:53
Represents a currency with its metadata and formatting rules.
Definition currency.hpp:34