189 lines
5.4 KiB
C++
189 lines
5.4 KiB
C++
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
|
//SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include "assets.h"
|
|
|
|
#include "utils/helpers.h"
|
|
|
|
const QHash<int, QByteArray> Models::Assets::roles({
|
|
{Title, "title"}, {Icon, "icon"}, {Balance, "balance"}, {Archived, "archived"}, {Color, "color"}, {Currency, "currency"}, {CurrencyID, "currencyID"}, {ID, "assetID"}
|
|
});
|
|
|
|
Models::Assets::Assets (Currencies& currencies, QObject* parent):
|
|
QAbstractListModel(parent),
|
|
records(),
|
|
state(State::initial),
|
|
currencies(currencies)
|
|
{}
|
|
|
|
void Models::Assets::clear () {
|
|
beginResetModel();
|
|
records.clear();
|
|
endResetModel();
|
|
}
|
|
|
|
void Models::Assets::add (const Asset& asset) {
|
|
int index = getIndexByID(asset.id);
|
|
if (index != -1)
|
|
throw std::runtime_error("An attempt to insert a duplicating Asset to an asset model");
|
|
|
|
beginInsertRows(QModelIndex(), records.size(), records.size());
|
|
records.push_back(asset);
|
|
endInsertRows();
|
|
}
|
|
|
|
void Models::Assets::add (const std::deque<Asset>& assets) {
|
|
if (assets.empty())
|
|
return;
|
|
|
|
for (const Asset& asset : assets)
|
|
if (getIndexByID(asset.id) != -1)
|
|
throw std::runtime_error("An attempt to insert a duplicating Asset to an asset model (bulk)");
|
|
|
|
beginInsertRows(QModelIndex(), records.size(), records.size() + assets.size() - 1);
|
|
for (const Asset& asset : assets)
|
|
records.push_back(asset);
|
|
|
|
endInsertRows();
|
|
}
|
|
|
|
void Models::Assets::remove (Asset::ID id) {
|
|
int index = getIndexByID(id);
|
|
if (index == -1)
|
|
throw std::runtime_error("An attempt to delete non existing Asset from asset model");
|
|
|
|
beginRemoveRows(QModelIndex(), index, index);
|
|
records.erase(records.begin() + index);
|
|
endRemoveRows();
|
|
}
|
|
|
|
void Models::Assets::change (const Asset& asset) {
|
|
int index = getIndexByID(asset.id);
|
|
if (index == -1)
|
|
throw std::runtime_error("An attempt to change non existing Asset in asset model");
|
|
|
|
records[index] = asset;
|
|
emit dataChanged(createIndex(index, 0, &records[index]), createIndex(index, 0, &records[index]));
|
|
}
|
|
|
|
void Models::Assets::change (const std::deque<Asset>& assets) {
|
|
for (const Asset& asset : assets)
|
|
change(asset);
|
|
}
|
|
|
|
Models::Asset Models::Assets::get (Asset::ID id) const {
|
|
int index = getIndexByID(id);
|
|
if (index == -1)
|
|
throw std::runtime_error("An attempt to access non existing Asset from asset model");
|
|
|
|
return records[index];
|
|
}
|
|
|
|
int Models::Assets::rowCount (const QModelIndex& parent) const {
|
|
//For list models only the root node (an invalid parent) should return the
|
|
//list's size. For all other (valid) parents, rowCount() should return 0 so
|
|
//that it does not become a tree model.
|
|
if (parent.isValid())
|
|
return 0;
|
|
|
|
return records.size();
|
|
}
|
|
|
|
QHash<int, QByteArray> Models::Assets::roleNames () const {
|
|
return roles;
|
|
}
|
|
|
|
bool Models::Assets::canFetchMore (const QModelIndex& parent) const {
|
|
return state == State::initial;
|
|
}
|
|
|
|
void Models::Assets::fetchMore (const QModelIndex& parent) {
|
|
if (state != State::initial)
|
|
return;
|
|
|
|
state = State::requesting;
|
|
emit requestAssets();
|
|
}
|
|
|
|
QVariant Models::Assets::data (const QModelIndex& index, int role) const {
|
|
if (!index.isValid())
|
|
return QVariant();
|
|
|
|
int row = index.row();
|
|
if (row >= 0 && row < records.size()) {
|
|
switch (role) {
|
|
case Qt::DisplayRole:
|
|
case Title:
|
|
return records[row].title;
|
|
case Icon:
|
|
return records[row].icon;
|
|
case Balance:
|
|
return records[row].balance;
|
|
case Archived:
|
|
return records[row].archived;
|
|
case Color:
|
|
return records[row].color;
|
|
case Currency:
|
|
return currencies.getCode(records[row].currency);
|
|
case CurrencyID:
|
|
return records[row].currency;
|
|
case ID:
|
|
return records[row].id;
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
bool Models::Assets::deserialize (const QVariantList& from, std::deque<Asset>& out) {
|
|
for (const QVariant& item : from) {
|
|
if (!item.canConvert<QVariantMap>())
|
|
return false;
|
|
|
|
const QVariantMap& ser = qast<QVariantMap>(item);
|
|
Asset& asset = out.emplace_back();
|
|
asset.title = ser.value("title").toString();
|
|
asset.icon = ser.value("icon").toString();
|
|
asset.archived = ser.value("archived").toBool();
|
|
asset.id = ser.value("id").toUInt();
|
|
asset.currency = ser.value("currency").toUInt();
|
|
|
|
uint32_t color = ser.value("color").toUInt();
|
|
asset.color = QColor::fromRgba(color);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void Models::Assets::receivedAssets (const std::deque<Asset>& assets) {
|
|
beginResetModel();
|
|
records = assets;
|
|
state = State::syncronized;
|
|
endResetModel();
|
|
}
|
|
|
|
int Models::Assets::getIndexByID (Asset::ID id) const {
|
|
for (std::size_t i = 0; i < records.size(); ++i) {
|
|
if (records[i].id == id)
|
|
return i;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
QVariantMap Models::Assets::getAssetByIndex (int index) const {
|
|
QVariantMap result;
|
|
if (index < 0 || index >= records.size())
|
|
return result;
|
|
|
|
QModelIndex idx = createIndex(index, 0, &records[index]);
|
|
for (int role = Roles::Title; role <= Roles::ID; ++role)
|
|
result[roles[role]] = data(idx, role);
|
|
|
|
return result;
|
|
}
|
|
|
|
QVariantMap Models::Assets::getAssetByID (Asset::ID id) const {
|
|
return getAssetByIndex(getIndexByID(id));
|
|
}
|