1 // This file is part of Qt Bitcoin Trader
2 // https://github.com/JulyIGHOR/QtBitcoinTrader
3 // Copyright (C) 2013-2021 July Ighor <julyighor@gmail.com>
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // In addition, as a special exception, the copyright holders give
11 // permission to link the code of portions of this program with the
12 // OpenSSL library under certain conditions as described in each
13 // individual source file, and distribute linked combinations including
14 // the two.
15 //
16 // You must obey the GNU General Public License in all respects for all
17 // of the code used other than OpenSSL. If you modify file(s) with this
18 // exception, you may extend this exception to your version of the
19 // file(s), but you are not obligated to do so. If you do not wish to do
20 // so, delete this exception statement from your version. If you delete
21 // this exception statement from all source files in the program, then
22 // also delete it here.
23 //
24 // This program is distributed in the hope that it will be useful,
25 // but WITHOUT ANY WARRANTY; without even the implied warranty of
26 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 // GNU General Public License for more details.
28 //
29 // You should have received a copy of the GNU General Public License
30 // along with this program. If not, see <http://www.gnu.org/licenses/>.
31
32 #include "historymodel.h"
33 #include "main.h"
34
HistoryModel()35 HistoryModel::HistoryModel()
36 : QAbstractItemModel()
37 {
38 typeWidth = 75;
39 columnsCount = 7;
40 lastDate = 0;
41 typesLabels << "" << "Bought" << "Sell" << "Buy" << "Fee" << "Deposit" <<
42 "Withdraw"; //0=General, 1=Sell, 2=Buy, 3=Fee, 4=Deposit, 5=Withdraw
43 }
44
~HistoryModel()45 HistoryModel::~HistoryModel()
46 {
47
48 }
49
clear()50 void HistoryModel::clear()
51 {
52 if (itemsList.isEmpty())
53 return;
54
55 beginResetModel();
56 lastDate = 0;
57 itemsList.clear();
58 endResetModel();
59 }
60
loadLastPrice()61 void HistoryModel::loadLastPrice()
62 {
63 bool haveLastBuy = false;
64 bool haveLastSell = false;
65
66 for (int n = 0; n < itemsList.size(); n++)
67 if (itemsList.at(n).symbol == baseValues.currentPair.symbol)
68 {
69 if (!haveLastSell && itemsList.at(n).type == 1)
70 {
71 emit accLastSellChanged(itemsList.at(n).symbol.right(3), itemsList.at(n).price);
72 haveLastSell = true;
73 }
74
75 if (!haveLastBuy && itemsList.at(n).type == 2)
76 {
77 emit accLastBuyChanged(itemsList.at(n).symbol.right(3), itemsList.at(n).price);
78 haveLastBuy = true;
79 }
80
81 if (haveLastSell && haveLastBuy)
82 break;
83 }
84 }
85
historyChanged(QList<HistoryItem> * histList)86 void HistoryModel::historyChanged(QList<HistoryItem>* histList)
87 {
88 bool haveLastBuy = false;
89 bool haveLastSell = false;
90
91 for (int n = 0; n < histList->size(); n++)
92 if (histList->at(n).symbol == baseValues.currentPair.symbol)
93 {
94 if (!haveLastSell && histList->at(n).type == 1)
95 {
96 emit accLastSellChanged(histList->at(n).symbol.right(3), histList->at(n).price);
97 haveLastSell = true;
98 }
99
100 if (!haveLastBuy && histList->at(n).type == 2)
101 {
102 emit accLastBuyChanged(histList->at(n).symbol.right(3), histList->at(n).price);
103 haveLastBuy = true;
104 }
105
106 if (haveLastSell && haveLastBuy)
107 break;
108 }
109
110 while (!histList->empty() && histList->last().dateTimeInt <= lastDate)
111 histList->removeLast();
112
113 if (histList->empty())
114 {
115 delete histList;
116 return;
117 }
118
119 beginInsertRows(QModelIndex(), 0, histList->size() - 1);
120
121 if (!histList->empty() && !itemsList.empty())
122 {
123 (*histList)[histList->size() - 1].displayFullDate = histList->at(histList->size() - 1).dateInt !=
124 itemsList.last().dateInt;
125 }
126
127 if (itemsList.isEmpty() && !histList->empty())
128 (*histList)[histList->size() - 1].displayFullDate = true;
129
130 qint64 maxListDate = 0;
131
132 for (int n = histList->size() - 1; n >= 0; n--)
133 {
134 if (maxListDate < histList->at(n).dateTimeInt)
135 maxListDate = histList->at(n).dateTimeInt;
136
137 if (n != histList->size() - 1)
138 (*histList)[n].displayFullDate = histList->at(n).dateInt != histList->at(n + 1).dateInt;
139
140 itemsList << histList->at(n);
141
142 static QMap<QString, quint32> lastDateMap;
143
144 if (lastDateMap.value(itemsList.last().symbol, 0UL) <= itemsList.last().dateInt)
145 {
146 lastDateMap[itemsList.last().symbol] = itemsList.last().dateInt;
147 mainWindow.sendIndicatorEvent(itemsList.last().symbol + itemsList.last().currRequestSecond,
148 QLatin1String("MyLastTrade"), itemsList.last().volume);
149 }
150 }
151
152 delete histList;
153
154 if (maxListDate > lastDate)
155 lastDate = maxListDate;
156
157 endInsertRows();
158 }
159
getRowPrice(int row)160 double HistoryModel::getRowPrice(int row)
161 {
162 row = itemsList.size() - row - 1;
163
164 if (row < 0 || row >= itemsList.size())
165 return 0.0;
166
167 return itemsList.at(row).price;
168 }
169
getRowVolume(int row)170 double HistoryModel::getRowVolume(int row)
171 {
172 row = itemsList.size() - row - 1;
173
174 if (row < 0 || row >= itemsList.size())
175 return 0.0;
176
177 return itemsList.at(row).volume;
178 }
179
getRowType(int row)180 int HistoryModel::getRowType(int row)
181 {
182 row = itemsList.size() - row - 1;
183
184 if (row < 0 || row >= itemsList.size())
185 return 0.0;
186
187 return itemsList.at(row).type;
188 }
189
rowCount(const QModelIndex &) const190 int HistoryModel::rowCount(const QModelIndex& /*parent*/) const
191 {
192 return itemsList.size();
193 }
194
columnCount(const QModelIndex &) const195 int HistoryModel::columnCount(const QModelIndex& /*parent*/) const
196 {
197 return columnsCount;
198 }
199
data(const QModelIndex & index,int role) const200 QVariant HistoryModel::data(const QModelIndex& index, int role) const
201 {
202 int currentRow = itemsList.size() - index.row() - 1;
203
204 if (currentRow < 0 || currentRow >= itemsList.size())
205 return QVariant();
206
207 if (role == Qt::WhatsThisRole)
208 {
209 return itemsList.at(currentRow).dateTimeStr + " " + typesLabels.at(itemsList.at(currentRow).type) + " " + itemsList.at(
210 currentRow).priceStr + " " + itemsList.at(currentRow).totalStr;
211 }
212
213 if (role == Qt::StatusTipRole)
214 {
215 return itemsList.at(currentRow).dateTimeStr + "\t" + itemsList.at(currentRow).volumeStr + "\t" + typesLabels.at(
216 itemsList.at(currentRow).type) + "\t" + itemsList.at(currentRow).priceStr + "\t" + itemsList.at(currentRow).totalStr;
217 }
218
219 if (role != Qt::DisplayRole && role != Qt::ToolTipRole && role != Qt::ForegroundRole && role != Qt::TextAlignmentRole)
220 return QVariant();
221
222 int indexColumn = index.column();
223
224 if (role == Qt::TextAlignmentRole)
225 {
226 if (indexColumn == 1)
227 return 0x0082;
228
229 if (indexColumn == 2)
230 return 0x0082;
231
232 if (indexColumn == 4)
233 return 0x0081;
234
235 if (indexColumn == 5)
236 return 0x0082;
237
238 if (indexColumn == 6)
239 return 0x0081;
240
241 return 0x0084;
242 }
243
244 if (role == Qt::ForegroundRole)
245 {
246 switch (indexColumn)
247 {
248 case 1:
249 return baseValues.appTheme.gray;
250 break;
251
252 case 3:
253 switch (itemsList.at(currentRow).type)
254 {
255 case 1:
256 return baseValues.appTheme.red;
257
258 case 2:
259 return baseValues.appTheme.blue;
260
261 case 3:
262 return baseValues.appTheme.darkGreen;
263
264 case 4:
265 return baseValues.appTheme.darkRed;
266
267 case 5:
268 return baseValues.appTheme.darkRedBlue;
269
270 default:
271 break;
272 }
273
274 break;
275
276 case 6:
277 return baseValues.appTheme.gray;
278 break;
279
280 default:
281 break;
282 }
283
284 return baseValues.appTheme.black;
285 }
286
287 switch (indexColumn)
288 {
289 case 1:
290 {
291 //Date
292 if (role == Qt::ToolTipRole || itemsList.at(currentRow).displayFullDate)
293 return itemsList.at(currentRow).dateTimeStr;//DateTime
294
295 return itemsList.at(currentRow).timeStr;//Time
296 }
297
298 case 2:
299 return itemsList.at(currentRow).volumeStr;//Volume
300
301 case 3:
302 return typesLabels.at(itemsList.at(currentRow).type);//Type
303
304 case 4:
305 return itemsList.at(currentRow).priceStr;//Price
306
307 case 5:
308 return itemsList.at(currentRow).totalStr;//Total
309
310 case 6:
311 return itemsList.at(currentRow).description;//Description
312
313 default:
314 break;
315 }
316
317 return QVariant();
318 }
319
headerData(int section,Qt::Orientation orientation,int role) const320 QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
321 {
322 if (orientation != Qt::Horizontal)
323 return QVariant();
324
325 if (role == Qt::TextAlignmentRole)
326 {
327 if (section == 2)
328 return 0x0082;
329
330 if (section == 4)
331 return 0x0081;
332
333 return 0x0084;
334 }
335
336 if (role == Qt::SizeHintRole)
337 {
338 switch (section)
339 {
340 case 1:
341 return QSize(dateWidth, defaultHeightForRow); //Date
342
343 case 3:
344 return QSize(typeWidth, defaultHeightForRow); //Type
345 }
346
347 return QVariant();
348 }
349
350 if (role != Qt::DisplayRole)
351 return QVariant();
352
353 if (headerLabels.size() != columnsCount)
354 return QVariant();
355
356 return headerLabels.at(section);
357 }
358
359
flags(const QModelIndex &) const360 Qt::ItemFlags HistoryModel::flags(const QModelIndex& /*index*/) const
361 {
362 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
363 }
364
setHorizontalHeaderLabels(QStringList list)365 void HistoryModel::setHorizontalHeaderLabels(QStringList list)
366 {
367 if (list.size() != columnsCount)
368 return;
369
370 typesLabels[1] = julyTr("LOG_SOLD", "sold");
371 typesLabels[2] = julyTr("LOG_BOUGHT", "bought");
372 typesLabels[3] = julyTr("LOG_FEE", "fee");
373 typesLabels[4] = julyTr("LOG_DEPOSIT", "deposit");
374 typesLabels[5] = julyTr("LOG_WITHDRAW", "withdraw");
375
376 typeWidth = 0;
377
378 for (int n = 1; n < typesLabels.size(); n++)
379 typeWidth = qMax(typeWidth, textFontWidth(typesLabels.at(n)));
380
381 typeWidth = qMax(typeWidth, textFontWidth(list.at(2)));
382 typeWidth += 10;
383
384 dateWidth = qMax(qMax(textFontWidth(QDateTime(QDate(2000, 12, 30), QTime(23, 59, 59,
385 999)).toString(baseValues.dateTimeFormat)), textFontWidth(QDateTime(QDate(2000, 12, 30), QTime(12, 59, 59,
386 999)).toString(baseValues.dateTimeFormat))), textFontWidth(list.at(0))) + 10;
387
388 headerLabels = list;
389 emit headerDataChanged(Qt::Horizontal, 0, columnsCount - 1);
390 }
391
index(int row,int column,const QModelIndex & parent) const392 QModelIndex HistoryModel::index(int row, int column, const QModelIndex& parent) const
393 {
394 if (!hasIndex(row, column, parent))
395 return QModelIndex();
396
397 return createIndex(row, column);
398 }
399
parent(const QModelIndex &) const400 QModelIndex HistoryModel::parent(const QModelIndex& /*child*/) const
401 {
402 return QModelIndex();
403 }
404