feat(wallet) save/load collectibles user handled state in DB
Add a separation layer for save/load/clear to ManageTokensModel so that we can save/load from external sources. The separate layer is composed of JSON as protocol, a set of signals and slots for interface. The implementation forwards data to current QSettings for storybook and nim controllers for the app. Updates #13313, #13312
This commit is contained in:
parent
f45a39bfcf
commit
26542970ee
|
@ -32,6 +32,10 @@ QtObject:
|
||||||
proc updateCollectiblePreferences*(self: View, collectiblePreferencesJson: string) {.slot.} =
|
proc updateCollectiblePreferences*(self: View, collectiblePreferencesJson: string) {.slot.} =
|
||||||
self.delegate.updateCollectiblePreferences(collectiblePreferencesJson)
|
self.delegate.updateCollectiblePreferences(collectiblePreferencesJson)
|
||||||
|
|
||||||
|
proc clearCollectiblePreferences*(self: View) {.slot.} =
|
||||||
|
# There is no requirements of clearing the preferences yet but controller is expected to expose it
|
||||||
|
discard
|
||||||
|
|
||||||
proc getCollectiblePreferencesJson(self: View): QVariant {.slot.} =
|
proc getCollectiblePreferencesJson(self: View): QVariant {.slot.} =
|
||||||
let preferences = self.delegate.getCollectiblePreferencesJson()
|
let preferences = self.delegate.getCollectiblePreferencesJson()
|
||||||
return newQVariant(preferences)
|
return newQVariant(preferences)
|
||||||
|
|
|
@ -87,14 +87,14 @@ type
|
||||||
contractAddress*: string
|
contractAddress*: string
|
||||||
owners*: seq[CollectibleOwner]
|
owners*: seq[CollectibleOwner]
|
||||||
|
|
||||||
# see status-go/services/wallet/collectibles/service.go CollectibleDataType
|
# Mirrors status-go/multiaccounts/settings_wallet/database.go CollectiblePreferencesType
|
||||||
CollectiblePreferencesItemType* {.pure.} = enum
|
CollectiblePreferencesItemType* {.pure.} = enum
|
||||||
NonCommunityCollectible = 1,
|
NonCommunityCollectible = 1,
|
||||||
CommunityCollectible,
|
CommunityCollectible,
|
||||||
Collection,
|
Collection,
|
||||||
Community
|
Community
|
||||||
|
|
||||||
# Mirrors services/wallet/thirdparty/collectible_types.go CollectibleContractOwnership
|
# Mirrors status-go/multiaccounts/settings_wallet/database.go CollectiblePreferences
|
||||||
CollectiblePreferences* = ref object of RootObj
|
CollectiblePreferences* = ref object of RootObj
|
||||||
itemType* {.serializedFieldName("type").}: CollectiblePreferencesItemType
|
itemType* {.serializedFieldName("type").}: CollectiblePreferencesItemType
|
||||||
key* {.serializedFieldName("key").}: string
|
key* {.serializedFieldName("key").}: string
|
||||||
|
|
|
@ -97,6 +97,12 @@ SplitView {
|
||||||
controller: ManageTokensController {
|
controller: ManageTokensController {
|
||||||
sourceModel: d.walletAssetStore.groupedAccountAssetsModel
|
sourceModel: d.walletAssetStore.groupedAccountAssetsModel
|
||||||
settingsKey: "WalletAssets"
|
settingsKey: "WalletAssets"
|
||||||
|
serializeAsCollectibles: false
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
|
|
||||||
onTokenHidden: (symbol, name) => Global.displayToastMessage(
|
onTokenHidden: (symbol, name) => Global.displayToastMessage(
|
||||||
qsTr("%1 (%2) was successfully hidden").arg(name).arg(symbol), "", "checkmark-circle",
|
qsTr("%1 (%2) was successfully hidden").arg(name).arg(symbol), "", "checkmark-circle",
|
||||||
false, Constants.ephemeralNotificationType.success, "")
|
false, Constants.ephemeralNotificationType.success, "")
|
||||||
|
|
|
@ -82,6 +82,12 @@ SplitView {
|
||||||
controller: ManageTokensController {
|
controller: ManageTokensController {
|
||||||
sourceModel: renamedModel
|
sourceModel: renamedModel
|
||||||
settingsKey: "WalletCollectibles"
|
settingsKey: "WalletCollectibles"
|
||||||
|
serializeAsCollectibles: true
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
|
|
||||||
onTokenHidden: (symbol, name) => Global.displayToastMessage(
|
onTokenHidden: (symbol, name) => Global.displayToastMessage(
|
||||||
qsTr("%1 was successfully hidden").arg(name), "", "checkmark-circle",
|
qsTr("%1 was successfully hidden").arg(name), "", "checkmark-circle",
|
||||||
false, Constants.ephemeralNotificationType.success, "")
|
false, Constants.ephemeralNotificationType.success, "")
|
||||||
|
|
|
@ -50,6 +50,11 @@ SplitView {
|
||||||
controller: ManageTokensController {
|
controller: ManageTokensController {
|
||||||
sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel
|
sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel
|
||||||
settingsKey: "WalletAssets"
|
settingsKey: "WalletAssets"
|
||||||
|
serializeAsCollectibles: false
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ SplitView {
|
||||||
controller: ManageTokensController {
|
controller: ManageTokensController {
|
||||||
sourceModel: renamedModel
|
sourceModel: renamedModel
|
||||||
settingsKey: "WalletCollectibles"
|
settingsKey: "WalletCollectibles"
|
||||||
|
serializeAsCollectibles: true
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,12 +44,22 @@ SplitView {
|
||||||
id: assetsController
|
id: assetsController
|
||||||
sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel
|
sourceModel: ctrlEmptyModel.checked ? null : walletAssetStore.groupedAccountAssetsModel
|
||||||
settingsKey: "WalletAssets"
|
settingsKey: "WalletAssets"
|
||||||
|
serializeAsCollectibles: false
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
ManageTokensController {
|
ManageTokensController {
|
||||||
id: collectiblesController
|
id: collectiblesController
|
||||||
sourceModel: ctrlEmptyModel.checked ? null : renamedModel
|
sourceModel: ctrlEmptyModel.checked ? null : renamedModel
|
||||||
settingsKey: "WalletCollectibles"
|
settingsKey: "WalletCollectibles"
|
||||||
|
serializeAsCollectibles: true
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
ManageHiddenPanel {
|
ManageHiddenPanel {
|
||||||
|
|
|
@ -37,10 +37,20 @@ Item {
|
||||||
controller: ManageTokensController {
|
controller: ManageTokensController {
|
||||||
sourceModel: renamedModel
|
sourceModel: renamedModel
|
||||||
settingsKey: "WalletCollectibles"
|
settingsKey: "WalletCollectibles"
|
||||||
|
serializeAsCollectibles: true
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => saveToQSettings(jsonData)
|
||||||
|
onRequestLoadSettings: loadFromQSettings()
|
||||||
|
onRequestClearSettings: clearQSettings()
|
||||||
|
|
||||||
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
||||||
qsTr("%1 community collectibles successfully hidden").arg(communityName), "", "checkmark-circle",
|
qsTr("%1 community collectibles successfully hidden").arg(communityName), "", "checkmark-circle",
|
||||||
false, Constants.ephemeralNotificationType.success, "")
|
false, Constants.ephemeralNotificationType.success, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearSettings() {
|
||||||
|
controller.clearQSettings()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,8 @@ add_library(StatusQ SHARED
|
||||||
src/wallet/managetokenscontroller.h
|
src/wallet/managetokenscontroller.h
|
||||||
src/wallet/managetokensmodel.cpp
|
src/wallet/managetokensmodel.cpp
|
||||||
src/wallet/managetokensmodel.h
|
src/wallet/managetokensmodel.h
|
||||||
|
src/wallet/tokendata.cpp
|
||||||
|
src/wallet/tokendata.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_features(StatusQ PRIVATE cxx_std_17)
|
target_compile_features(StatusQ PRIVATE cxx_std_17)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "managetokenscontroller.h"
|
#include "managetokenscontroller.h"
|
||||||
|
|
||||||
#include <tuple>
|
#include "tokendata.h"
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#include <QMutableHashIterator>
|
#include <QMutableHashIterator>
|
||||||
|
@ -26,30 +26,38 @@ ManageTokensController::ManageTokensController(QObject* parent)
|
||||||
}
|
}
|
||||||
if (m_modelConnectionsInitialized)
|
if (m_modelConnectionsInitialized)
|
||||||
return;
|
return;
|
||||||
connect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, [this](const QModelIndex &parent, int first, int last) {
|
connect(m_sourceModel,
|
||||||
|
&QAbstractItemModel::rowsInserted,
|
||||||
|
this,
|
||||||
|
[this](const QModelIndex& parent, int first, int last) {
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
t.start();
|
t.start();
|
||||||
qCDebug(manageTokens) << "!!! ADDING" << last-first+1 << "NEW TOKENS";
|
qCDebug(manageTokens) << "!!! ADDING" << last - first + 1 << "NEW TOKENS";
|
||||||
#endif
|
#endif
|
||||||
for (int i = first; i <= last; i++)
|
for (int i = first; i <= last; i++)
|
||||||
addItem(i);
|
addItem(i);
|
||||||
|
|
||||||
rebuildCommunityTokenGroupsModel();
|
rebuildCommunityTokenGroupsModel();
|
||||||
rebuildHiddenCommunityTokenGroupsModel();
|
rebuildHiddenCommunityTokenGroupsModel();
|
||||||
rebuildCollectionGroupsModel();
|
rebuildCollectionGroupsModel();
|
||||||
rebuildHiddenCollectionGroupsModel();
|
rebuildHiddenCollectionGroupsModel();
|
||||||
|
|
||||||
for (auto model: m_allModels) {
|
for (auto model : m_allModels) {
|
||||||
model->applySort();
|
model->applySort();
|
||||||
model->saveCustomSortOrder();
|
model->saveCustomSortOrder();
|
||||||
}
|
}
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
qCDebug(manageTokens) << "!!! ADDING NEW SOURCE DATA TOOK" << t.nsecsElapsed()/1'000'000.f << "ms";
|
qCDebug(manageTokens)
|
||||||
|
<< "!!! ADDING NEW SOURCE DATA TOOK" << t.nsecsElapsed() / 1'000'000.f << "ms";
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
connect(m_sourceModel, &QAbstractItemModel::rowsRemoved, this, &ManageTokensController::parseSourceModel);
|
connect(m_sourceModel, &QAbstractItemModel::rowsRemoved, this, &ManageTokensController::requestLoadSettings);
|
||||||
connect(m_sourceModel, &QAbstractItemModel::dataChanged, this, &ManageTokensController::parseSourceModel); // NB at this point we don't know in which submodel the item is
|
connect(m_sourceModel,
|
||||||
|
&QAbstractItemModel::dataChanged,
|
||||||
|
this,
|
||||||
|
&ManageTokensController::requestLoadSettings); // NB at this point we don't know in
|
||||||
|
// which submodel the item is
|
||||||
m_modelConnectionsInitialized = true;
|
m_modelConnectionsInitialized = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -69,7 +77,7 @@ void ManageTokensController::showHideRegularToken(const QString& symbol, bool fl
|
||||||
emit tokenHidden(shownItem->symbol, shownItem->name);
|
emit tokenHidden(shownItem->symbol, shownItem->name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveSettings();
|
requestSaveSettings(serializeSettingsAsJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::showHideCommunityToken(const QString& symbol, bool flag)
|
void ManageTokensController::showHideCommunityToken(const QString& symbol, bool flag)
|
||||||
|
@ -90,7 +98,7 @@ void ManageTokensController::showHideCommunityToken(const QString& symbol, bool
|
||||||
m_communityTokensModel->saveCustomSortOrder();
|
m_communityTokensModel->saveCustomSortOrder();
|
||||||
rebuildCommunityTokenGroupsModel();
|
rebuildCommunityTokenGroupsModel();
|
||||||
rebuildHiddenCommunityTokenGroupsModel();
|
rebuildHiddenCommunityTokenGroupsModel();
|
||||||
saveSettings();
|
requestSaveSettings(serializeSettingsAsJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::showHideGroup(const QString& groupId, bool flag)
|
void ManageTokensController::showHideGroup(const QString& groupId, bool flag)
|
||||||
|
@ -98,7 +106,7 @@ void ManageTokensController::showHideGroup(const QString& groupId, bool flag)
|
||||||
if (flag) { // show
|
if (flag) { // show
|
||||||
const auto tokens = m_hiddenTokensModel->takeAllItems(groupId);
|
const auto tokens = m_hiddenTokensModel->takeAllItems(groupId);
|
||||||
if (!tokens.isEmpty()) {
|
if (!tokens.isEmpty()) {
|
||||||
for (const auto& token: tokens) {
|
for (const auto& token : tokens) {
|
||||||
m_communityTokensModel->addItem(token);
|
m_communityTokensModel->addItem(token);
|
||||||
}
|
}
|
||||||
emit communityTokenGroupShown(tokens.constFirst().communityName);
|
emit communityTokenGroupShown(tokens.constFirst().communityName);
|
||||||
|
@ -109,7 +117,7 @@ void ManageTokensController::showHideGroup(const QString& groupId, bool flag)
|
||||||
} else { // hide
|
} else { // hide
|
||||||
const auto tokens = m_communityTokensModel->takeAllItems(groupId);
|
const auto tokens = m_communityTokensModel->takeAllItems(groupId);
|
||||||
if (!tokens.isEmpty()) {
|
if (!tokens.isEmpty()) {
|
||||||
for (const auto& token: tokens) {
|
for (const auto& token : tokens) {
|
||||||
m_hiddenTokensModel->addItem(token, false /*prepend*/);
|
m_hiddenTokensModel->addItem(token, false /*prepend*/);
|
||||||
}
|
}
|
||||||
emit communityTokenGroupHidden(tokens.constFirst().communityName);
|
emit communityTokenGroupHidden(tokens.constFirst().communityName);
|
||||||
|
@ -122,7 +130,7 @@ void ManageTokensController::showHideGroup(const QString& groupId, bool flag)
|
||||||
rebuildCommunityTokenGroupsModel();
|
rebuildCommunityTokenGroupsModel();
|
||||||
m_communityTokenGroupsModel->applySort();
|
m_communityTokenGroupsModel->applySort();
|
||||||
rebuildHiddenCommunityTokenGroupsModel();
|
rebuildHiddenCommunityTokenGroupsModel();
|
||||||
saveSettings();
|
requestSaveSettings(serializeSettingsAsJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::showHideCollectionGroup(const QString& groupId, bool flag)
|
void ManageTokensController::showHideCollectionGroup(const QString& groupId, bool flag)
|
||||||
|
@ -130,7 +138,7 @@ void ManageTokensController::showHideCollectionGroup(const QString& groupId, boo
|
||||||
if (flag) { // show
|
if (flag) { // show
|
||||||
const auto tokens = m_hiddenTokensModel->takeAllItems(groupId);
|
const auto tokens = m_hiddenTokensModel->takeAllItems(groupId);
|
||||||
if (!tokens.isEmpty()) {
|
if (!tokens.isEmpty()) {
|
||||||
for (const auto& token: tokens) {
|
for (const auto& token : tokens) {
|
||||||
m_regularTokensModel->addItem(token);
|
m_regularTokensModel->addItem(token);
|
||||||
}
|
}
|
||||||
emit collectionTokenGroupShown(tokens.constFirst().collectionName);
|
emit collectionTokenGroupShown(tokens.constFirst().collectionName);
|
||||||
|
@ -141,7 +149,7 @@ void ManageTokensController::showHideCollectionGroup(const QString& groupId, boo
|
||||||
} else { // hide
|
} else { // hide
|
||||||
const auto tokens = m_regularTokensModel->takeAllItems(groupId);
|
const auto tokens = m_regularTokensModel->takeAllItems(groupId);
|
||||||
if (!tokens.isEmpty()) {
|
if (!tokens.isEmpty()) {
|
||||||
for (const auto& token: tokens) {
|
for (const auto& token : tokens) {
|
||||||
m_hiddenTokensModel->addItem(token, false /*prepend*/);
|
m_hiddenTokensModel->addItem(token, false /*prepend*/);
|
||||||
}
|
}
|
||||||
emit collectionTokenGroupHidden(tokens.constFirst().collectionName);
|
emit collectionTokenGroupHidden(tokens.constFirst().collectionName);
|
||||||
|
@ -154,71 +162,28 @@ void ManageTokensController::showHideCollectionGroup(const QString& groupId, boo
|
||||||
rebuildCollectionGroupsModel();
|
rebuildCollectionGroupsModel();
|
||||||
m_collectionGroupsModel->applySort();
|
m_collectionGroupsModel->applySort();
|
||||||
rebuildHiddenCollectionGroupsModel();
|
rebuildHiddenCollectionGroupsModel();
|
||||||
saveSettings();
|
requestSaveSettings(serializeSettingsAsJson());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::saveSettings()
|
void ManageTokensController::saveToQSettings(const QString& json)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_settingsKey.isEmpty());
|
Q_ASSERT(!m_settingsKey.isEmpty());
|
||||||
|
|
||||||
setSettingsDirty(true);
|
savingStarted();
|
||||||
|
|
||||||
// gather the data to save
|
|
||||||
SerializedTokenData result;
|
|
||||||
const auto resultCount = m_regularTokensModel->rowCount() + m_communityTokensModel->rowCount() + m_hiddenTokensModel->rowCount() +
|
|
||||||
(m_arrangeByCommunity ? m_communityTokenGroupsModel->rowCount() : 0) +
|
|
||||||
(m_arrangeByCollection ? m_collectionGroupsModel->rowCount() : 0);
|
|
||||||
result.reserve(resultCount);
|
|
||||||
|
|
||||||
for(auto model : {m_regularTokensModel, m_communityTokensModel})
|
|
||||||
result.insert(model->save());
|
|
||||||
if (m_arrangeByCommunity)
|
|
||||||
result.insert(m_communityTokenGroupsModel->save());
|
|
||||||
if (m_arrangeByCollection)
|
|
||||||
result.insert(m_collectionGroupsModel->save());
|
|
||||||
result.insert(m_hiddenTokensModel->save(false));
|
|
||||||
|
|
||||||
// save to QSettings
|
// save to QSettings
|
||||||
m_settings.beginGroup(settingsGroupName());
|
m_settings.beginGroup(settingsGroupName());
|
||||||
|
|
||||||
// arrange by
|
|
||||||
m_settings.setValue(QStringLiteral("ArrangeByCommunity"), m_arrangeByCommunity);
|
|
||||||
m_settings.setValue(QStringLiteral("ArrangeByCollection"), m_arrangeByCollection);
|
|
||||||
|
|
||||||
// data
|
// data
|
||||||
m_settings.beginWriteArray(m_settingsKey);
|
m_settings.setValue(m_settingsKey, json);
|
||||||
SerializedTokenData::const_key_value_iterator it = result.constKeyValueBegin();
|
|
||||||
for (auto i = 0; it != result.constKeyValueEnd() && i < result.size(); it++, i++) {
|
|
||||||
m_settings.setArrayIndex(i);
|
|
||||||
const auto& [pos, visible, groupId, isCommunityGroup, isCollectionGroup] = it->second;
|
|
||||||
m_settings.setValue(QStringLiteral("symbol"), it->first);
|
|
||||||
m_settings.setValue(QStringLiteral("pos"), pos);
|
|
||||||
m_settings.setValue(QStringLiteral("visible"), visible);
|
|
||||||
m_settings.setValue(QStringLiteral("groupId"), groupId);
|
|
||||||
m_settings.setValue(QStringLiteral("isCommunityGroup"), isCommunityGroup);
|
|
||||||
m_settings.setValue(QStringLiteral("isCollectionGroup"), isCollectionGroup);
|
|
||||||
}
|
|
||||||
m_settings.endArray();
|
|
||||||
|
|
||||||
// hidden groups
|
|
||||||
m_settings.setValue(QStringLiteral("HiddenCommunityGroups"), hiddenCommunityGroups());
|
|
||||||
m_settings.setValue(QStringLiteral("HiddenCollectionGroups"), hiddenCollectionGroups());
|
|
||||||
|
|
||||||
m_settings.endGroup();
|
m_settings.endGroup();
|
||||||
m_settings.sync();
|
m_settings.sync();
|
||||||
|
|
||||||
// unset dirty
|
savingFinished();
|
||||||
for (auto model: m_allModels)
|
|
||||||
model->setDirty(false);
|
|
||||||
|
|
||||||
loadSettingsData(true); // reload positions and visibility
|
|
||||||
|
|
||||||
incRevision();
|
|
||||||
|
|
||||||
setSettingsDirty(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::clearSettings()
|
void ManageTokensController::clearQSettings()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_settingsKey.isEmpty());
|
Q_ASSERT(!m_settingsKey.isEmpty());
|
||||||
|
|
||||||
|
@ -231,73 +196,24 @@ void ManageTokensController::clearSettings()
|
||||||
emit settingsDirtyChanged(false);
|
emit settingsDirtyChanged(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::loadSettingsData(bool withGroup)
|
void ManageTokensController::loadFromQSettings()
|
||||||
{
|
|
||||||
SerializedTokenData result;
|
|
||||||
|
|
||||||
if (withGroup)
|
|
||||||
m_settings.beginGroup(settingsGroupName());
|
|
||||||
|
|
||||||
const auto size = m_settings.beginReadArray(m_settingsKey);
|
|
||||||
for (auto i = 0; i < size; i++) {
|
|
||||||
m_settings.setArrayIndex(i);
|
|
||||||
const auto symbol = m_settings.value(QStringLiteral("symbol")).toString();
|
|
||||||
if (symbol.isEmpty()) {
|
|
||||||
qCDebug(manageTokens) << Q_FUNC_INFO << "Missing symbol while reading tokens settings";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto pos = m_settings.value(QStringLiteral("pos"), INT_MAX).toInt();
|
|
||||||
const auto visible = m_settings.value(QStringLiteral("visible"), true).toBool();
|
|
||||||
const auto groupId = m_settings.value(QStringLiteral("groupId")).toString();
|
|
||||||
const auto isCommunityGroup = m_settings.value(QStringLiteral("isCommunityGroup"), false).toBool();
|
|
||||||
const auto isCollectionGroup = m_settings.value(QStringLiteral("isCollectionGroup"), false).toBool();
|
|
||||||
result.insert(symbol, {pos, visible, groupId, isCommunityGroup, isCollectionGroup});
|
|
||||||
}
|
|
||||||
m_settings.endArray();
|
|
||||||
|
|
||||||
if (withGroup)
|
|
||||||
m_settings.endGroup();
|
|
||||||
|
|
||||||
if (result != m_settingsData)
|
|
||||||
m_settingsData = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensController::loadSettings()
|
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_settingsKey.isEmpty());
|
Q_ASSERT(!m_settingsKey.isEmpty());
|
||||||
|
|
||||||
setSettingsDirty(true);
|
loadingStarted();
|
||||||
m_settingsData.clear();
|
|
||||||
|
|
||||||
// load from QSettings
|
// load from QSettings
|
||||||
m_settings.beginGroup(settingsGroupName());
|
m_settings.beginGroup(settingsGroupName());
|
||||||
|
const auto jsonData = m_settings.value(m_settingsKey).toString();
|
||||||
loadSettingsData();
|
|
||||||
|
|
||||||
// hidden groups
|
|
||||||
const auto groups = m_settings.value(QStringLiteral("HiddenCommunityGroups")).toStringList();
|
|
||||||
if (!groups.isEmpty()) {
|
|
||||||
m_hiddenCommunityGroups = {groups.constBegin(), groups.constEnd()};
|
|
||||||
emit hiddenCommunityGroupsChanged();
|
|
||||||
}
|
|
||||||
const auto collections = m_settings.value(QStringLiteral("HiddenCollectionGroups")).toStringList();
|
|
||||||
if (!collections.isEmpty()) {
|
|
||||||
m_hiddenCollectionGroups = {collections.constBegin(), collections.constEnd()};
|
|
||||||
emit hiddenCollectionGroupsChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
// arrange by
|
|
||||||
setArrangeByCommunity(m_settings.value(QStringLiteral("ArrangeByCommunity"), false).toBool());
|
|
||||||
setArrangeByCollection(m_settings.value(QStringLiteral("ArrangeByCollection"), false).toBool());
|
|
||||||
|
|
||||||
m_settings.endGroup();
|
m_settings.endGroup();
|
||||||
|
|
||||||
setSettingsDirty(false);
|
loadingFinished(jsonData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::setSettingsDirty(bool dirty)
|
void ManageTokensController::setSettingsDirty(bool dirty)
|
||||||
{
|
{
|
||||||
if (m_settingsDirty == dirty) return;
|
if (m_settingsDirty == dirty)
|
||||||
|
return;
|
||||||
m_settingsDirty = dirty;
|
m_settingsDirty = dirty;
|
||||||
emit settingsDirtyChanged(m_settingsDirty);
|
emit settingsDirtyChanged(m_settingsDirty);
|
||||||
}
|
}
|
||||||
|
@ -318,9 +234,81 @@ QStringList ManageTokensController::hiddenCollectionGroups() const
|
||||||
return {m_hiddenCollectionGroups.constBegin(), m_hiddenCollectionGroups.constEnd()};
|
return {m_hiddenCollectionGroups.constBegin(), m_hiddenCollectionGroups.constEnd()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::revert()
|
void ManageTokensController::revert() { requestLoadSettings(); }
|
||||||
|
|
||||||
|
void ManageTokensController::savingStarted()
|
||||||
{
|
{
|
||||||
|
setSettingsDirty(true); // save to QSettings
|
||||||
|
m_settings.beginGroup(settingsGroupName());
|
||||||
|
|
||||||
|
m_settings.setValue(QStringLiteral("ArrangeByCommunity"), m_arrangeByCommunity);
|
||||||
|
m_settings.setValue(QStringLiteral("ArrangeByCollection"), m_arrangeByCollection);
|
||||||
|
|
||||||
|
m_settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManageTokensController::savingFinished()
|
||||||
|
{
|
||||||
|
// unset dirty
|
||||||
|
for (auto model : m_allModels)
|
||||||
|
model->setDirty(false);
|
||||||
|
|
||||||
|
incRevision();
|
||||||
|
|
||||||
|
setSettingsDirty(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManageTokensController::loadingStarted()
|
||||||
|
{
|
||||||
|
setSettingsDirty(true);
|
||||||
|
m_settingsData.clear();
|
||||||
|
|
||||||
|
m_settings.beginGroup(settingsGroupName());
|
||||||
|
|
||||||
|
// hidden groups
|
||||||
|
const auto groups = m_settings.value(QStringLiteral("HiddenCommunityGroups")).toStringList();
|
||||||
|
if (!groups.isEmpty()) {
|
||||||
|
m_hiddenCommunityGroups = {groups.constBegin(), groups.constEnd()};
|
||||||
|
emit hiddenCommunityGroupsChanged();
|
||||||
|
}
|
||||||
|
const auto collections = m_settings.value(QStringLiteral("HiddenCollectionGroups")).toStringList();
|
||||||
|
if (!collections.isEmpty()) {
|
||||||
|
m_hiddenCollectionGroups = {collections.constBegin(), collections.constEnd()};
|
||||||
|
emit hiddenCollectionGroupsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrange by
|
||||||
|
setArrangeByCommunity(m_settings.value(QStringLiteral("ArrangeByCommunity"), false).toBool());
|
||||||
|
setArrangeByCollection(m_settings.value(QStringLiteral("ArrangeByCollection"), false).toBool());
|
||||||
|
|
||||||
|
m_settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ManageTokensController::loadingFinished(const QString& jsonData)
|
||||||
|
{
|
||||||
|
if (!jsonData.isEmpty()) {
|
||||||
|
auto result = tokenOrdersFromJson(jsonData, m_serializeAsCollectibles);
|
||||||
|
if (result != m_settingsData) {
|
||||||
|
m_settingsData = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parseSourceModel();
|
parseSourceModel();
|
||||||
|
setSettingsDirty(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ManageTokensController::serializeSettingsAsJson()
|
||||||
|
{
|
||||||
|
SerializedTokenData result;
|
||||||
|
for (auto model : {m_regularTokensModel, m_communityTokensModel})
|
||||||
|
result.insert(model->save());
|
||||||
|
if (m_arrangeByCommunity)
|
||||||
|
result.insert(m_communityTokenGroupsModel->save(true /* visible */, true /* itemsAreGroups */));
|
||||||
|
if (m_arrangeByCollection)
|
||||||
|
result.insert(m_collectionGroupsModel->save(true /* visible */, true /* itemsAreGroups */));
|
||||||
|
result.insert(m_hiddenTokensModel->save(false));
|
||||||
|
auto json = tokenOrdersToJson(result, m_serializeAsCollectibles);
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ManageTokensController::settingsGroupName() const
|
QString ManageTokensController::settingsGroupName() const
|
||||||
|
@ -337,26 +325,12 @@ bool ManageTokensController::hasSettings() const
|
||||||
|
|
||||||
int ManageTokensController::compareTokens(const QString& lhsSymbol, const QString& rhsSymbol) const
|
int ManageTokensController::compareTokens(const QString& lhsSymbol, const QString& rhsSymbol) const
|
||||||
{
|
{
|
||||||
constexpr auto defaultVal = std::make_tuple(INT_MAX, false, QLatin1String(), false, false);
|
const auto left = m_settingsData.value(lhsSymbol, TokenOrder());
|
||||||
|
const auto right = m_settingsData.value(rhsSymbol, TokenOrder());
|
||||||
int leftPos, rightPos;
|
|
||||||
bool leftVisible, rightVisible;
|
|
||||||
QString leftGroup, rightGroup;
|
|
||||||
bool leftIsCommunityGroup, rightIsCommunityGroup, leftIsCollectionGroup, rightIsCollectionGroup;
|
|
||||||
|
|
||||||
std::tie(leftPos, leftVisible, leftGroup, leftIsCommunityGroup, leftIsCollectionGroup) = m_settingsData.value(lhsSymbol, defaultVal);
|
|
||||||
std::tie(rightPos, rightVisible, rightGroup, rightIsCommunityGroup, rightIsCollectionGroup) = m_settingsData.value(rhsSymbol, defaultVal);
|
|
||||||
|
|
||||||
// check grouped position
|
|
||||||
if (((m_arrangeByCommunity && leftIsCommunityGroup && rightIsCommunityGroup)
|
|
||||||
|| (m_arrangeByCollection && leftIsCollectionGroup && rightIsCollectionGroup))) {
|
|
||||||
leftPos = std::get<0>(m_settingsData.value(leftGroup, defaultVal));
|
|
||||||
rightPos = std::get<0>(m_settingsData.value(rightGroup, defaultVal));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if visible
|
// check if visible
|
||||||
leftPos = leftVisible ? leftPos : INT_MAX;
|
auto leftPos = left.visible ? left.sortOrder : undefinedTokenOrder;
|
||||||
rightPos = rightVisible ? rightPos : INT_MAX;
|
auto rightPos = right.visible ? right.sortOrder : undefinedTokenOrder;
|
||||||
|
|
||||||
if (leftPos < rightPos)
|
if (leftPos < rightPos)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -367,9 +341,13 @@ int ManageTokensController::compareTokens(const QString& lhsSymbol, const QStrin
|
||||||
|
|
||||||
bool ManageTokensController::filterAcceptsSymbol(const QString& symbol) const
|
bool ManageTokensController::filterAcceptsSymbol(const QString& symbol) const
|
||||||
{
|
{
|
||||||
if (symbol.isEmpty()) return true;
|
if (symbol.isEmpty())
|
||||||
|
return true;
|
||||||
|
|
||||||
return std::get<1>(m_settingsData.value(symbol, {INT_MAX, true, QString(), false, false}));
|
if (!m_settingsData.contains(symbol)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return m_settingsData.value(symbol).visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::classBegin()
|
void ManageTokensController::classBegin()
|
||||||
|
@ -377,19 +355,17 @@ void ManageTokensController::classBegin()
|
||||||
// empty on purpose
|
// empty on purpose
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManageTokensController::componentComplete()
|
void ManageTokensController::componentComplete() { requestLoadSettings(); }
|
||||||
{
|
|
||||||
loadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensController::setSourceModel(QAbstractItemModel* newSourceModel)
|
void ManageTokensController::setSourceModel(QAbstractItemModel* newSourceModel)
|
||||||
{
|
{
|
||||||
if(m_sourceModel == newSourceModel) return;
|
if (m_sourceModel == newSourceModel)
|
||||||
|
return;
|
||||||
|
|
||||||
if(!newSourceModel) {
|
if (!newSourceModel) {
|
||||||
disconnect(sourceModel());
|
disconnect(sourceModel());
|
||||||
// clear all the models
|
// clear all the models
|
||||||
for (auto model: m_allModels)
|
for (auto model : m_allModels)
|
||||||
model->clear();
|
model->clear();
|
||||||
m_settingsData.clear();
|
m_settingsData.clear();
|
||||||
m_hiddenCommunityGroups.clear();
|
m_hiddenCommunityGroups.clear();
|
||||||
|
@ -402,14 +378,15 @@ void ManageTokensController::setSourceModel(QAbstractItemModel* newSourceModel)
|
||||||
|
|
||||||
m_sourceModel = newSourceModel;
|
m_sourceModel = newSourceModel;
|
||||||
|
|
||||||
connect(m_sourceModel, &QAbstractItemModel::modelReset, this, &ManageTokensController::parseSourceModel);
|
connect(m_sourceModel, &QAbstractItemModel::modelReset, this, &ManageTokensController::requestLoadSettings);
|
||||||
|
|
||||||
if (m_sourceModel && m_sourceModel->roleNames().isEmpty()) { // workaround for when a model has no roles and roles are added when the model is populated (ListModel)
|
if (m_sourceModel && m_sourceModel->roleNames().isEmpty()) { // workaround for when a model has no roles and roles
|
||||||
|
// are added when the model is populated (ListModel)
|
||||||
// QTBUG-57971
|
// QTBUG-57971
|
||||||
connect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ManageTokensController::parseSourceModel);
|
connect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ManageTokensController::requestLoadSettings);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
parseSourceModel();
|
requestLoadSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +395,7 @@ void ManageTokensController::parseSourceModel()
|
||||||
if (!m_sourceModel)
|
if (!m_sourceModel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disconnect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ManageTokensController::parseSourceModel);
|
disconnect(m_sourceModel, &QAbstractItemModel::rowsInserted, this, &ManageTokensController::requestLoadSettings);
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
QElapsedTimer t;
|
QElapsedTimer t;
|
||||||
|
@ -426,12 +403,9 @@ void ManageTokensController::parseSourceModel()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// clear all the models
|
// clear all the models
|
||||||
for (auto model: m_allModels)
|
for (auto model : m_allModels)
|
||||||
model->clear();
|
model->clear();
|
||||||
|
|
||||||
// load settings
|
|
||||||
loadSettings();
|
|
||||||
|
|
||||||
// read and transform the original data
|
// read and transform the original data
|
||||||
const auto newSize = m_sourceModel->rowCount();
|
const auto newSize = m_sourceModel->rowCount();
|
||||||
qCDebug(manageTokens) << "!!! PARSING" << newSize << "TOKENS";
|
qCDebug(manageTokens) << "!!! PARSING" << newSize << "TOKENS";
|
||||||
|
@ -448,13 +422,13 @@ void ManageTokensController::parseSourceModel()
|
||||||
rebuildHiddenCollectionGroupsModel();
|
rebuildHiddenCollectionGroupsModel();
|
||||||
|
|
||||||
// (pre)sort
|
// (pre)sort
|
||||||
for (auto model: m_allModels) {
|
for (auto model : m_allModels) {
|
||||||
model->applySort();
|
model->applySort();
|
||||||
model->setDirty(false);
|
model->setDirty(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
qCDebug(manageTokens) << "!!! PARSING SOURCE DATA TOOK" << t.nsecsElapsed()/1'000'000.f << "ms";
|
qCDebug(manageTokens) << "!!! PARSING SOURCE DATA TOOK" << t.nsecsElapsed() / 1'000'000.f << "ms";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
emit sourceModelChanged();
|
emit sourceModelChanged();
|
||||||
|
@ -464,7 +438,7 @@ void ManageTokensController::addItem(int index)
|
||||||
{
|
{
|
||||||
const auto sourceRoleNames = m_sourceModel->roleNames();
|
const auto sourceRoleNames = m_sourceModel->roleNames();
|
||||||
|
|
||||||
const auto dataForIndex = [&](const QModelIndex &idx, const QByteArray& rolename) -> QVariant {
|
const auto dataForIndex = [&](const QModelIndex& idx, const QByteArray& rolename) -> QVariant {
|
||||||
const auto key = sourceRoleNames.key(rolename, -1);
|
const auto key = sourceRoleNames.key(rolename, -1);
|
||||||
if (key == -1)
|
if (key == -1)
|
||||||
return {};
|
return {};
|
||||||
|
@ -475,7 +449,7 @@ void ManageTokensController::addItem(int index)
|
||||||
const auto symbol = dataForIndex(srcIndex, kSymbolRoleName).toString();
|
const auto symbol = dataForIndex(srcIndex, kSymbolRoleName).toString();
|
||||||
const auto communityId = dataForIndex(srcIndex, kCommunityIdRoleName).toString();
|
const auto communityId = dataForIndex(srcIndex, kCommunityIdRoleName).toString();
|
||||||
const auto communityName = dataForIndex(srcIndex, kCommunityNameRoleName).toString();
|
const auto communityName = dataForIndex(srcIndex, kCommunityNameRoleName).toString();
|
||||||
const auto visible = m_settingsData.contains(symbol) ? std::get<1>(m_settingsData.value(symbol)) : true;
|
const auto visible = m_settingsData.contains(symbol) ? m_settingsData.value(symbol).visible : true;
|
||||||
const auto bgColor = dataForIndex(srcIndex, kBackgroundColorRoleName).value<QColor>();
|
const auto bgColor = dataForIndex(srcIndex, kBackgroundColorRoleName).value<QColor>();
|
||||||
const auto collectionUid = dataForIndex(srcIndex, kCollectionUidRoleName).toString();
|
const auto collectionUid = dataForIndex(srcIndex, kCollectionUidRoleName).toString();
|
||||||
|
|
||||||
|
@ -497,8 +471,8 @@ void ManageTokensController::addItem(int index)
|
||||||
token.decimals = dataForIndex(srcIndex, kDecimalsRoleName);
|
token.decimals = dataForIndex(srcIndex, kDecimalsRoleName);
|
||||||
token.marketDetails = dataForIndex(srcIndex, kMarketDetailsRoleName);
|
token.marketDetails = dataForIndex(srcIndex, kMarketDetailsRoleName);
|
||||||
|
|
||||||
token.customSortOrderNo = m_settingsData.contains(symbol) ? std::get<0>(m_settingsData.value(symbol))
|
token.customSortOrderNo = m_settingsData.contains(symbol) ? m_settingsData.value(symbol).sortOrder
|
||||||
: (visible ? INT_MAX : 0); // append/prepend
|
: (visible ? undefinedTokenOrder : 0); // append/prepend
|
||||||
|
|
||||||
if (!visible)
|
if (!visible)
|
||||||
m_hiddenTokensModel->addItem(token, /*append*/ false);
|
m_hiddenTokensModel->addItem(token, /*append*/ false);
|
||||||
|
@ -510,19 +484,15 @@ void ManageTokensController::addItem(int index)
|
||||||
|
|
||||||
bool ManageTokensController::dirty() const
|
bool ManageTokensController::dirty() const
|
||||||
{
|
{
|
||||||
return std::any_of(m_allModels.cbegin(), m_allModels.cend(), [](auto model) {
|
return std::any_of(m_allModels.cbegin(), m_allModels.cend(), [](auto model) { return model->dirty(); });
|
||||||
return model->dirty();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManageTokensController::arrangeByCommunity() const
|
bool ManageTokensController::arrangeByCommunity() const { return m_arrangeByCommunity; }
|
||||||
{
|
|
||||||
return m_arrangeByCommunity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensController::setArrangeByCommunity(bool newArrangeByCommunity)
|
void ManageTokensController::setArrangeByCommunity(bool newArrangeByCommunity)
|
||||||
{
|
{
|
||||||
if(m_arrangeByCommunity == newArrangeByCommunity) return;
|
if (m_arrangeByCommunity == newArrangeByCommunity)
|
||||||
|
return;
|
||||||
m_arrangeByCommunity = newArrangeByCommunity;
|
m_arrangeByCommunity = newArrangeByCommunity;
|
||||||
if (m_arrangeByCommunity) {
|
if (m_arrangeByCommunity) {
|
||||||
rebuildCommunityTokenGroupsModel();
|
rebuildCommunityTokenGroupsModel();
|
||||||
|
@ -532,14 +502,12 @@ void ManageTokensController::setArrangeByCommunity(bool newArrangeByCommunity)
|
||||||
emit arrangeByCommunityChanged();
|
emit arrangeByCommunityChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManageTokensController::arrangeByCollection() const
|
bool ManageTokensController::arrangeByCollection() const { return m_arrangeByCollection; }
|
||||||
{
|
|
||||||
return m_arrangeByCollection;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensController::setArrangeByCollection(bool newArrangeByCollection)
|
void ManageTokensController::setArrangeByCollection(bool newArrangeByCollection)
|
||||||
{
|
{
|
||||||
if(m_arrangeByCollection == newArrangeByCollection) return;
|
if (m_arrangeByCollection == newArrangeByCollection)
|
||||||
|
return;
|
||||||
m_arrangeByCollection = newArrangeByCollection;
|
m_arrangeByCollection = newArrangeByCollection;
|
||||||
if (m_arrangeByCollection) {
|
if (m_arrangeByCollection) {
|
||||||
rebuildCollectionGroupsModel();
|
rebuildCollectionGroupsModel();
|
||||||
|
@ -570,7 +538,7 @@ void ManageTokensController::rebuildCommunityTokenGroupsModel()
|
||||||
tokenGroup.balance = 1;
|
tokenGroup.balance = 1;
|
||||||
|
|
||||||
if (m_settingsData.contains(communityId)) {
|
if (m_settingsData.contains(communityId)) {
|
||||||
tokenGroup.customSortOrderNo = std::get<0>(m_settingsData.value(communityId));
|
tokenGroup.customSortOrderNo = m_settingsData.value(communityId).sortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(tokenGroup);
|
result.append(tokenGroup);
|
||||||
|
@ -587,7 +555,7 @@ void ManageTokensController::rebuildCommunityTokenGroupsModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_communityTokenGroupsModel->clear();
|
m_communityTokenGroupsModel->clear();
|
||||||
for (const auto& group: std::as_const(result))
|
for (const auto& group : std::as_const(result))
|
||||||
m_communityTokenGroupsModel->addItem(group);
|
m_communityTokenGroupsModel->addItem(group);
|
||||||
|
|
||||||
qCDebug(manageTokens) << "!!! GROUPS MODEL REBUILT WITH GROUPS:" << communityIds;
|
qCDebug(manageTokens) << "!!! GROUPS MODEL REBUILT WITH GROUPS:" << communityIds;
|
||||||
|
@ -604,7 +572,8 @@ void ManageTokensController::rebuildHiddenCommunityTokenGroupsModel()
|
||||||
const auto communityId = communityToken.communityId;
|
const auto communityId = communityToken.communityId;
|
||||||
if (communityId.isEmpty())
|
if (communityId.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
if (!communityIds.contains(communityId) && m_hiddenCommunityGroups.contains(communityId)) { // insert into groups
|
if (!communityIds.contains(communityId) &&
|
||||||
|
m_hiddenCommunityGroups.contains(communityId)) { // insert into groups
|
||||||
communityIds.append(communityId);
|
communityIds.append(communityId);
|
||||||
|
|
||||||
TokenData tokenGroup;
|
TokenData tokenGroup;
|
||||||
|
@ -628,7 +597,7 @@ void ManageTokensController::rebuildHiddenCommunityTokenGroupsModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_hiddenCommunityTokenGroupsModel->clear();
|
m_hiddenCommunityTokenGroupsModel->clear();
|
||||||
for (const auto& group: std::as_const(result))
|
for (const auto& group : std::as_const(result))
|
||||||
m_hiddenCommunityTokenGroupsModel->addItem(group);
|
m_hiddenCommunityTokenGroupsModel->addItem(group);
|
||||||
|
|
||||||
qCDebug(manageTokens) << "!!! HIDDEN GROUPS MODEL REBUILT WITH GROUPS:" << communityIds;
|
qCDebug(manageTokens) << "!!! HIDDEN GROUPS MODEL REBUILT WITH GROUPS:" << communityIds;
|
||||||
|
@ -647,7 +616,8 @@ void ManageTokensController::rebuildCollectionGroupsModel()
|
||||||
if (!collectionIds.contains(collectionId)) { // insert into groups
|
if (!collectionIds.contains(collectionId)) { // insert into groups
|
||||||
collectionIds.append(collectionId);
|
collectionIds.append(collectionId);
|
||||||
|
|
||||||
const auto collectionName = !collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name;
|
const auto collectionName =
|
||||||
|
!collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name;
|
||||||
|
|
||||||
TokenData tokenGroup;
|
TokenData tokenGroup;
|
||||||
tokenGroup.symbol = collectionId;
|
tokenGroup.symbol = collectionId;
|
||||||
|
@ -659,7 +629,7 @@ void ManageTokensController::rebuildCollectionGroupsModel()
|
||||||
tokenGroup.balance = 1;
|
tokenGroup.balance = 1;
|
||||||
|
|
||||||
if (m_settingsData.contains(collectionId)) {
|
if (m_settingsData.contains(collectionId)) {
|
||||||
tokenGroup.customSortOrderNo = std::get<0>(m_settingsData.value(collectionId));
|
tokenGroup.customSortOrderNo = m_settingsData.value(collectionId).sortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.append(tokenGroup);
|
result.append(tokenGroup);
|
||||||
|
@ -676,7 +646,7 @@ void ManageTokensController::rebuildCollectionGroupsModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_collectionGroupsModel->clear();
|
m_collectionGroupsModel->clear();
|
||||||
for (const auto& group: std::as_const(result))
|
for (const auto& group : std::as_const(result))
|
||||||
m_collectionGroupsModel->addItem(group);
|
m_collectionGroupsModel->addItem(group);
|
||||||
|
|
||||||
qCDebug(manageTokens) << "!!! COLLECTION MODEL REBUILT WITH GROUPS:" << collectionIds;
|
qCDebug(manageTokens) << "!!! COLLECTION MODEL REBUILT WITH GROUPS:" << collectionIds;
|
||||||
|
@ -692,10 +662,12 @@ void ManageTokensController::rebuildHiddenCollectionGroupsModel()
|
||||||
const auto& collectionToken = m_hiddenTokensModel->itemAt(i);
|
const auto& collectionToken = m_hiddenTokensModel->itemAt(i);
|
||||||
const auto collectionId = collectionToken.collectionUid;
|
const auto collectionId = collectionToken.collectionUid;
|
||||||
const auto isSelfCollection = collectionToken.isSelfCollection;
|
const auto isSelfCollection = collectionToken.isSelfCollection;
|
||||||
if (!collectionIds.contains(collectionId) && m_hiddenCollectionGroups.contains(collectionId)) { // insert into groups
|
if (!collectionIds.contains(collectionId) &&
|
||||||
|
m_hiddenCollectionGroups.contains(collectionId)) { // insert into groups
|
||||||
collectionIds.append(collectionId);
|
collectionIds.append(collectionId);
|
||||||
|
|
||||||
const auto collectionName = !collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name;
|
const auto collectionName =
|
||||||
|
!collectionToken.collectionName.isEmpty() ? collectionToken.collectionName : collectionToken.name;
|
||||||
|
|
||||||
TokenData tokenGroup;
|
TokenData tokenGroup;
|
||||||
tokenGroup.symbol = collectionId;
|
tokenGroup.symbol = collectionId;
|
||||||
|
@ -719,16 +691,13 @@ void ManageTokensController::rebuildHiddenCollectionGroupsModel()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_hiddenCollectionGroupsModel->clear();
|
m_hiddenCollectionGroupsModel->clear();
|
||||||
for (const auto& group: std::as_const(result))
|
for (const auto& group : std::as_const(result))
|
||||||
m_hiddenCollectionGroupsModel->addItem(group);
|
m_hiddenCollectionGroupsModel->addItem(group);
|
||||||
|
|
||||||
qCDebug(manageTokens) << "!!! HIDDEN COLLECTION GROUPS MODEL REBUILT WITH GROUPS:" << collectionIds;
|
qCDebug(manageTokens) << "!!! HIDDEN COLLECTION GROUPS MODEL REBUILT WITH GROUPS:" << collectionIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ManageTokensController::settingsKey() const
|
QString ManageTokensController::settingsKey() const { return m_settingsKey; }
|
||||||
{
|
|
||||||
return m_settingsKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensController::setSettingsKey(const QString& newSettingsKey)
|
void ManageTokensController::setSettingsKey(const QString& newSettingsKey)
|
||||||
{
|
{
|
||||||
|
@ -737,3 +706,13 @@ void ManageTokensController::setSettingsKey(const QString& newSettingsKey)
|
||||||
m_settingsKey = newSettingsKey;
|
m_settingsKey = newSettingsKey;
|
||||||
emit settingsKeyChanged();
|
emit settingsKeyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ManageTokensController::serializeAsCollectibles() const { return m_serializeAsCollectibles; }
|
||||||
|
|
||||||
|
void ManageTokensController::setSerializeAsCollectibles(const bool newSerializeAsCollectibles)
|
||||||
|
{
|
||||||
|
if (m_serializeAsCollectibles == newSerializeAsCollectibles)
|
||||||
|
return;
|
||||||
|
m_serializeAsCollectibles = newSerializeAsCollectibles;
|
||||||
|
emit serializeAsCollectiblesChanged();
|
||||||
|
}
|
|
@ -8,6 +8,12 @@
|
||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
/// @brief Controller for managing visibility and order for all kind of tokens and groups.
|
||||||
|
///
|
||||||
|
/// There is an "abstraction" layer for saving data to different mediums and is controlled form QML.
|
||||||
|
/// The QML implementation forwards data to current QSettings for storybook and nim controllers for the app.
|
||||||
|
/// @see request* signals for triggering actions and start/finish methods for notifying about the process.
|
||||||
|
/// @see *QSettings related methods for saving and loading data in user profile settings.
|
||||||
class ManageTokensController : public QObject, public QQmlParserStatus
|
class ManageTokensController : public QObject, public QQmlParserStatus
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -16,6 +22,7 @@ class ManageTokensController : public QObject, public QQmlParserStatus
|
||||||
// input properties
|
// input properties
|
||||||
Q_PROPERTY(QAbstractItemModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged FINAL)
|
Q_PROPERTY(QAbstractItemModel* sourceModel READ sourceModel WRITE setSourceModel NOTIFY sourceModelChanged FINAL)
|
||||||
Q_PROPERTY(QString settingsKey READ settingsKey WRITE setSettingsKey NOTIFY settingsKeyChanged FINAL REQUIRED)
|
Q_PROPERTY(QString settingsKey READ settingsKey WRITE setSettingsKey NOTIFY settingsKeyChanged FINAL REQUIRED)
|
||||||
|
Q_PROPERTY(bool serializeAsCollectibles READ serializeAsCollectibles WRITE setSerializeAsCollectibles NOTIFY serializeAsCollectiblesChanged FINAL REQUIRED)
|
||||||
|
|
||||||
Q_PROPERTY(bool arrangeByCommunity READ arrangeByCommunity WRITE setArrangeByCommunity NOTIFY arrangeByCommunityChanged FINAL)
|
Q_PROPERTY(bool arrangeByCommunity READ arrangeByCommunity WRITE setArrangeByCommunity NOTIFY arrangeByCommunityChanged FINAL)
|
||||||
Q_PROPERTY(bool arrangeByCollection READ arrangeByCollection WRITE setArrangeByCollection NOTIFY arrangeByCollectionChanged FINAL)
|
Q_PROPERTY(bool arrangeByCollection READ arrangeByCollection WRITE setArrangeByCollection NOTIFY arrangeByCollectionChanged FINAL)
|
||||||
|
@ -45,11 +52,19 @@ public:
|
||||||
Q_INVOKABLE void showHideGroup(const QString& groupId, bool flag);
|
Q_INVOKABLE void showHideGroup(const QString& groupId, bool flag);
|
||||||
Q_INVOKABLE void showHideCollectionGroup(const QString& groupId, bool flag);
|
Q_INVOKABLE void showHideCollectionGroup(const QString& groupId, bool flag);
|
||||||
|
|
||||||
Q_INVOKABLE void loadSettings();
|
Q_INVOKABLE void loadFromQSettings();
|
||||||
Q_INVOKABLE void saveSettings();
|
Q_INVOKABLE void saveToQSettings(const QString& json);
|
||||||
Q_INVOKABLE void clearSettings();
|
Q_INVOKABLE void clearQSettings();
|
||||||
Q_INVOKABLE void revert();
|
Q_INVOKABLE void revert();
|
||||||
|
|
||||||
|
/// required to be called before the saving is started
|
||||||
|
Q_INVOKABLE void savingStarted();
|
||||||
|
Q_INVOKABLE void savingFinished();
|
||||||
|
Q_INVOKABLE void loadingStarted();
|
||||||
|
Q_INVOKABLE void loadingFinished(const QString& jsonData);
|
||||||
|
|
||||||
|
Q_INVOKABLE QString serializeSettingsAsJson();
|
||||||
|
|
||||||
Q_INVOKABLE int compareTokens(const QString& lhsSymbol, const QString& rhsSymbol) const;
|
Q_INVOKABLE int compareTokens(const QString& lhsSymbol, const QString& rhsSymbol) const;
|
||||||
Q_INVOKABLE bool filterAcceptsSymbol(const QString& symbol) const;
|
Q_INVOKABLE bool filterAcceptsSymbol(const QString& symbol) const;
|
||||||
|
|
||||||
|
@ -64,6 +79,7 @@ signals:
|
||||||
void arrangeByCollectionChanged();
|
void arrangeByCollectionChanged();
|
||||||
void settingsKeyChanged();
|
void settingsKeyChanged();
|
||||||
void settingsDirtyChanged(bool dirty);
|
void settingsDirtyChanged(bool dirty);
|
||||||
|
void serializeAsCollectiblesChanged();
|
||||||
|
|
||||||
void tokenHidden(const QString& symbol, const QString& name);
|
void tokenHidden(const QString& symbol, const QString& name);
|
||||||
void tokenShown(const QString& symbol, const QString& name);
|
void tokenShown(const QString& symbol, const QString& name);
|
||||||
|
@ -77,6 +93,17 @@ signals:
|
||||||
|
|
||||||
void revisionChanged();
|
void revisionChanged();
|
||||||
|
|
||||||
|
/// Emitted when the settings are requested to be saved.
|
||||||
|
/// Receiver requires to call savingStarted and savingFinished to notify about the saving process.
|
||||||
|
/// @param jsonData serialized json data
|
||||||
|
void requestSaveSettings(const QString& jsonData);
|
||||||
|
/// Emitted when the settings are requested to be loaded. Client should call loadSettings as a response.
|
||||||
|
/// Receiver requires to call loadingStarted and loadingFinished to notify about the loading process.
|
||||||
|
void requestLoadSettings();
|
||||||
|
/// @brief Emitted when the settings are requested to be cleared.
|
||||||
|
/// Receiver requires to call loadingStarted and loadingFinished to notify about the loading process.
|
||||||
|
void requestClearSettings();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QAbstractItemModel* m_sourceModel{nullptr};
|
QAbstractItemModel* m_sourceModel{nullptr};
|
||||||
QAbstractItemModel* sourceModel() const { return m_sourceModel; }
|
QAbstractItemModel* sourceModel() const { return m_sourceModel; }
|
||||||
|
@ -128,6 +155,11 @@ private:
|
||||||
QString settingsKey() const;
|
QString settingsKey() const;
|
||||||
QString settingsGroupName() const;
|
QString settingsGroupName() const;
|
||||||
void setSettingsKey(const QString& newSettingsKey);
|
void setSettingsKey(const QString& newSettingsKey);
|
||||||
|
|
||||||
|
bool m_serializeAsCollectibles{false};
|
||||||
|
bool serializeAsCollectibles() const;
|
||||||
|
void setSerializeAsCollectibles(const bool newSerializeAsCollectibles);
|
||||||
|
|
||||||
QSettings m_settings;
|
QSettings m_settings;
|
||||||
SerializedTokenData m_settingsData; // symbol -> {sortOrder, visible, groupId, isCommunityGroup, isCollectionGroup}
|
SerializedTokenData m_settingsData; // symbol -> {sortOrder, visible, groupId, isCommunityGroup, isCollectionGroup}
|
||||||
bool hasSettings() const;
|
bool hasSettings() const;
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(manageTokens, "status.models.manageTokens", QtInfoMsg)
|
Q_LOGGING_CATEGORY(manageTokens, "status.models.manageTokens", QtInfoMsg)
|
||||||
|
|
||||||
ManageTokensModel::ManageTokensModel(QObject* parent)
|
ManageTokensModel::ManageTokensModel(QObject* parent) : QAbstractListModel(parent)
|
||||||
: QAbstractListModel(parent)
|
|
||||||
{
|
{
|
||||||
connect(this, &QAbstractItemModel::rowsInserted, this, &ManageTokensModel::countChanged);
|
connect(this, &QAbstractItemModel::rowsInserted, this, &ManageTokensModel::countChanged);
|
||||||
connect(this, &QAbstractItemModel::rowsRemoved, this, &ManageTokensModel::countChanged);
|
connect(this, &QAbstractItemModel::rowsRemoved, this, &ManageTokensModel::countChanged);
|
||||||
|
@ -40,9 +39,8 @@ void ManageTokensModel::addItem(const TokenData& item, bool append)
|
||||||
|
|
||||||
std::optional<TokenData> ManageTokensModel::takeItem(const QString& symbol)
|
std::optional<TokenData> ManageTokensModel::takeItem(const QString& symbol)
|
||||||
{
|
{
|
||||||
const auto token = std::find_if(m_data.cbegin(), m_data.cend(), [symbol](const auto& item) {
|
const auto token =
|
||||||
return symbol == item.symbol;
|
std::find_if(m_data.cbegin(), m_data.cend(), [symbol](const auto& item) { return symbol == item.symbol; });
|
||||||
});
|
|
||||||
const auto row = std::distance(m_data.cbegin(), token);
|
const auto row = std::distance(m_data.cbegin(), token);
|
||||||
|
|
||||||
if (row < 0 || row >= rowCount())
|
if (row < 0 || row >= rowCount())
|
||||||
|
@ -60,7 +58,7 @@ QList<TokenData> ManageTokensModel::takeAllItems(const QString& groupId)
|
||||||
QList<int> indexesToRemove;
|
QList<int> indexesToRemove;
|
||||||
|
|
||||||
for (int i = 0; i < m_data.count(); i++) {
|
for (int i = 0; i < m_data.count(); i++) {
|
||||||
const auto &token = m_data.at(i);
|
const auto& token = m_data.at(i);
|
||||||
if (token.communityId == groupId || token.collectionUid == groupId) {
|
if (token.communityId == groupId || token.collectionUid == groupId) {
|
||||||
result.append(token);
|
result.append(token);
|
||||||
indexesToRemove.append(i);
|
indexesToRemove.append(i);
|
||||||
|
@ -68,7 +66,7 @@ QList<TokenData> ManageTokensModel::takeAllItems(const QString& groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<int>::reverse_iterator its;
|
QList<int>::reverse_iterator its;
|
||||||
for(its = indexesToRemove.rbegin(); its != indexesToRemove.rend(); ++its) {
|
for (its = indexesToRemove.rbegin(); its != indexesToRemove.rend(); ++its) {
|
||||||
const auto row = *its;
|
const auto row = *its;
|
||||||
beginRemoveRows({}, row, row);
|
beginRemoveRows({}, row, row);
|
||||||
m_data.removeAt(row);
|
m_data.removeAt(row);
|
||||||
|
@ -86,7 +84,7 @@ void ManageTokensModel::clear()
|
||||||
setDirty(false);
|
setDirty(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializedTokenData ManageTokensModel::save(bool isVisible)
|
SerializedTokenData ManageTokensModel::save(bool isVisible, bool itemsAreGroups)
|
||||||
{
|
{
|
||||||
saveCustomSortOrder();
|
saveCustomSortOrder();
|
||||||
const auto size = rowCount();
|
const auto size = rowCount();
|
||||||
|
@ -96,21 +94,25 @@ SerializedTokenData ManageTokensModel::save(bool isVisible)
|
||||||
const auto& token = itemAt(i);
|
const auto& token = itemAt(i);
|
||||||
const auto isCommunityGroup = !token.communityId.isEmpty();
|
const auto isCommunityGroup = !token.communityId.isEmpty();
|
||||||
const auto isCollectionGroup = !token.collectionUid.isEmpty();
|
const auto isCollectionGroup = !token.collectionUid.isEmpty();
|
||||||
const auto groupId = isCommunityGroup ? token.communityId : isCollectionGroup ? token.collectionUid : QString();
|
result.insert(token.symbol,
|
||||||
result.insert(token.symbol, {i, isVisible, groupId, isCommunityGroup, isCollectionGroup});
|
TokenOrder{token.symbol,
|
||||||
|
i,
|
||||||
|
isVisible,
|
||||||
|
isCommunityGroup,
|
||||||
|
token.communityId,
|
||||||
|
isCollectionGroup,
|
||||||
|
token.collectionUid,
|
||||||
|
tokenDataToCollectiblePreferencesItemType(token, isCommunityGroup, itemsAreGroups)});
|
||||||
}
|
}
|
||||||
setDirty(false);
|
setDirty(false);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ManageTokensModel::rowCount(const QModelIndex& parent) const
|
int ManageTokensModel::rowCount(const QModelIndex& parent) const { return m_data.size(); }
|
||||||
{
|
|
||||||
return m_data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QByteArray> ManageTokensModel::roleNames() const
|
QHash<int, QByteArray> ManageTokensModel::roleNames() const
|
||||||
{
|
{
|
||||||
static const QHash<int, QByteArray> roles {
|
static const QHash<int, QByteArray> roles{
|
||||||
{SymbolRole, kSymbolRoleName},
|
{SymbolRole, kSymbolRoleName},
|
||||||
{NameRole, kNameRoleName},
|
{NameRole, kNameRoleName},
|
||||||
{CommunityIdRole, kCommunityIdRoleName},
|
{CommunityIdRole, kCommunityIdRoleName},
|
||||||
|
@ -134,42 +136,57 @@ QHash<int, QByteArray> ManageTokensModel::roleNames() const
|
||||||
|
|
||||||
QVariant ManageTokensModel::data(const QModelIndex& index, int role) const
|
QVariant ManageTokensModel::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid))
|
if (!checkIndex(index,
|
||||||
|
QAbstractItemModel::CheckIndexOption::IndexIsValid |
|
||||||
|
QAbstractItemModel::CheckIndexOption::ParentIsInvalid))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
const auto& token = m_data.at(index.row());
|
const auto& token = m_data.at(index.row());
|
||||||
|
|
||||||
switch(static_cast<TokenDataRoles>(role))
|
switch (static_cast<TokenDataRoles>(role)) {
|
||||||
{
|
case SymbolRole:
|
||||||
case SymbolRole: return token.symbol;
|
return token.symbol;
|
||||||
case NameRole: return token.name;
|
case NameRole:
|
||||||
case CommunityIdRole: return token.communityId;
|
return token.name;
|
||||||
case CommunityNameRole: return token.communityName;
|
case CommunityIdRole:
|
||||||
case CommunityImageRole: return token.communityImage;
|
return token.communityId;
|
||||||
case CollectionUidRole: return token.collectionUid;
|
case CommunityNameRole:
|
||||||
case CollectionNameRole: return token.collectionName;
|
return token.communityName;
|
||||||
case BalanceRole: return token.balance;
|
case CommunityImageRole:
|
||||||
case CurrencyBalanceRole: return token.currencyBalance;
|
return token.communityImage;
|
||||||
case CustomSortOrderNoRole: return token.customSortOrderNo;
|
case CollectionUidRole:
|
||||||
case TokenImageRole: return token.image;
|
return token.collectionUid;
|
||||||
case TokenBackgroundColorRole: return token.backgroundColor;
|
case CollectionNameRole:
|
||||||
case TokenBalancesRole: return token.balances;
|
return token.collectionName;
|
||||||
case TokenDecimalsRole: return token.decimals;
|
case BalanceRole:
|
||||||
case TokenMarketDetailsRole: return token.marketDetails;
|
return token.balance;
|
||||||
case IsSelfCollectionRole: return token.isSelfCollection;
|
case CurrencyBalanceRole:
|
||||||
|
return token.currencyBalance;
|
||||||
|
case CustomSortOrderNoRole:
|
||||||
|
return token.customSortOrderNo;
|
||||||
|
case TokenImageRole:
|
||||||
|
return token.image;
|
||||||
|
case TokenBackgroundColorRole:
|
||||||
|
return token.backgroundColor;
|
||||||
|
case TokenBalancesRole:
|
||||||
|
return token.balances;
|
||||||
|
case TokenDecimalsRole:
|
||||||
|
return token.decimals;
|
||||||
|
case TokenMarketDetailsRole:
|
||||||
|
return token.marketDetails;
|
||||||
|
case IsSelfCollectionRole:
|
||||||
|
return token.isSelfCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ManageTokensModel::dirty() const
|
bool ManageTokensModel::dirty() const { return m_dirty; }
|
||||||
{
|
|
||||||
return m_dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ManageTokensModel::setDirty(bool flag)
|
void ManageTokensModel::setDirty(bool flag)
|
||||||
{
|
{
|
||||||
if (m_dirty == flag) return;
|
if (m_dirty == flag)
|
||||||
|
return;
|
||||||
m_dirty = flag;
|
m_dirty = flag;
|
||||||
emit dirtyChanged();
|
emit dirtyChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "tokendata.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
@ -30,18 +32,6 @@ const auto kIsSelfCollectionRoleName = QByteArrayLiteral("isSelfCollection");
|
||||||
// TODO add communityPrivilegesLevel for collectibles
|
// TODO add communityPrivilegesLevel for collectibles
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
struct TokenData {
|
|
||||||
QString symbol, name, communityId, communityName, communityImage, collectionUid, collectionName, image;
|
|
||||||
QColor backgroundColor{Qt::transparent};
|
|
||||||
QVariant balance, currencyBalance;
|
|
||||||
QVariant balances, marketDetails, decimals;
|
|
||||||
int customSortOrderNo{INT_MAX};
|
|
||||||
bool isSelfCollection{false};
|
|
||||||
};
|
|
||||||
|
|
||||||
// symbol -> {sortOrder, visible, groupId, isCommunityGroup, isCollectionGroup}
|
|
||||||
using SerializedTokenData = QHash<QString, std::tuple<int, bool, QString, bool, bool>>;
|
|
||||||
|
|
||||||
class ManageTokensModel : public QAbstractListModel
|
class ManageTokensModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -78,7 +68,7 @@ public:
|
||||||
QList<TokenData> takeAllItems(const QString& groupId);
|
QList<TokenData> takeAllItems(const QString& groupId);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
SerializedTokenData save(bool isVisible = true);
|
SerializedTokenData save(bool isVisible = true, bool itemsAreGroups = false);
|
||||||
|
|
||||||
bool dirty() const;
|
bool dirty() const;
|
||||||
void setDirty(bool flag);
|
void setDirty(bool flag);
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
#include "tokendata.h"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(const TokenData& token, bool isCommunity, bool itemsAreGroups)
|
||||||
|
{
|
||||||
|
if (itemsAreGroups) {
|
||||||
|
if (isCommunity) {
|
||||||
|
return CollectiblePreferencesItemType::Community;
|
||||||
|
} else {
|
||||||
|
return CollectiblePreferencesItemType::Collection;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (isCommunity) {
|
||||||
|
return CollectiblePreferencesItemType::CommunityCollectible;
|
||||||
|
} else {
|
||||||
|
return CollectiblePreferencesItemType::NonCommunityCollectible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenOrder::TokenOrder() : sortOrder(undefinedTokenOrder) {}
|
||||||
|
|
||||||
|
TokenOrder::TokenOrder(const QString& symbol,
|
||||||
|
int sortOrder,
|
||||||
|
bool visible,
|
||||||
|
bool isCommunityGroup,
|
||||||
|
const QString& communityId,
|
||||||
|
bool isCollectionGroup,
|
||||||
|
const QString& collectionUid,
|
||||||
|
CollectiblePreferencesItemType type)
|
||||||
|
: symbol(symbol)
|
||||||
|
, sortOrder(sortOrder)
|
||||||
|
, visible(visible)
|
||||||
|
, isCommunityGroup(isCommunityGroup)
|
||||||
|
, communityId(communityId)
|
||||||
|
, isCollectionGroup(isCollectionGroup)
|
||||||
|
, collectionUid(collectionUid)
|
||||||
|
, type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// reverse of \c tokenOrdersFromJson
|
||||||
|
///
|
||||||
|
/// for protocol structure, see:
|
||||||
|
/// \see CollectiblePreferences in src/backend/collectibles_types.nim
|
||||||
|
/// \see TokenPreferences in src/backend/backend.nim
|
||||||
|
QString tokenOrdersToJson(const SerializedTokenData& dataList, bool areCollectible)
|
||||||
|
{
|
||||||
|
QJsonArray jsonArray;
|
||||||
|
for (const TokenOrder& data : dataList) {
|
||||||
|
QJsonObject obj;
|
||||||
|
obj["key"] = data.symbol;
|
||||||
|
obj["position"] = data.sortOrder;
|
||||||
|
obj["visible"] = data.visible;
|
||||||
|
if (data.isCommunityGroup) {
|
||||||
|
obj["isCommunityGroup"] = true;
|
||||||
|
obj["communityId"] = data.communityId;
|
||||||
|
}
|
||||||
|
if (data.isCollectionGroup) {
|
||||||
|
obj["isCollectionGroup"] = true;
|
||||||
|
obj["collectionUid"] = data.collectionUid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areCollectible) {
|
||||||
|
// see CollectiblePreferences in src/backend/collectibles_types.nim
|
||||||
|
// type cover separation of groups and collectibles
|
||||||
|
obj["type"] = static_cast<int>(data.type);
|
||||||
|
} else { // is asset
|
||||||
|
// see TokenPreferences in src/backend/backend.nim
|
||||||
|
// TODO #13312: handle "groupPosition" for asset
|
||||||
|
}
|
||||||
|
jsonArray.append(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument doc(jsonArray);
|
||||||
|
QString json_string = doc.toJson(QJsonDocument::Compact);
|
||||||
|
|
||||||
|
return json_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// reverse of \c tokenOrdersToJson
|
||||||
|
///
|
||||||
|
/// for protocol structure, see:
|
||||||
|
/// \see CollectiblePreferences in src/backend/collectibles_types.nim
|
||||||
|
/// \see TokenPreferences in src/backend/backend.nim
|
||||||
|
SerializedTokenData tokenOrdersFromJson(const QString& json_string, bool areCollectibles)
|
||||||
|
{
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(json_string.toUtf8());
|
||||||
|
QJsonArray jsonArray = doc.array();
|
||||||
|
|
||||||
|
SerializedTokenData dataList;
|
||||||
|
for (const QJsonValue& value : jsonArray) {
|
||||||
|
QJsonObject obj = value.toObject();
|
||||||
|
TokenOrder data;
|
||||||
|
|
||||||
|
data.symbol = obj["key"].toString();
|
||||||
|
data.sortOrder = obj["position"].toInt();
|
||||||
|
data.visible = obj["visible"].toBool();
|
||||||
|
if (obj.contains("isCommunityGroup")) {
|
||||||
|
data.isCommunityGroup = obj["isCommunityGroup"].toBool();
|
||||||
|
data.communityId = obj["communityId"].toString();
|
||||||
|
}
|
||||||
|
if (obj.contains("isCollectionGroup")) {
|
||||||
|
data.isCollectionGroup = obj["isCollectionGroup"].toBool();
|
||||||
|
data.collectionUid = obj["collectionUid"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areCollectibles) {
|
||||||
|
// see CollectiblePreferences in src/backend/collectibles_types.nim
|
||||||
|
data.type = static_cast<CollectiblePreferencesItemType>(obj["type"].toInt());
|
||||||
|
} else { // is asset
|
||||||
|
// see TokenPreferences in src/backend/backend.nim
|
||||||
|
// TODO #13312: handle "groupPosition" for assets
|
||||||
|
}
|
||||||
|
|
||||||
|
dataList.insert(data.symbol, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataList;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QColor>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
static const auto undefinedTokenOrder = INT_MAX;
|
||||||
|
|
||||||
|
// Generic structure representing an asset, collectible, collection or community token
|
||||||
|
struct TokenData {
|
||||||
|
QString symbol, name, communityId, communityName, communityImage, collectionUid, collectionName, image;
|
||||||
|
QColor backgroundColor{Qt::transparent};
|
||||||
|
QVariant balance, currencyBalance;
|
||||||
|
QVariant balances, marketDetails, decimals;
|
||||||
|
int customSortOrderNo{undefinedTokenOrder};
|
||||||
|
bool isSelfCollection{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
// mirrors CollectiblePreferencesItemType from src/backend/collectibles_types.nim
|
||||||
|
enum class CollectiblePreferencesItemType { NonCommunityCollectible = 1, CommunityCollectible, Collection, Community };
|
||||||
|
|
||||||
|
CollectiblePreferencesItemType tokenDataToCollectiblePreferencesItemType(const TokenData& tokenData, bool isCommunity, bool itemsAreGroups);
|
||||||
|
|
||||||
|
struct TokenOrder {
|
||||||
|
QString symbol;
|
||||||
|
int sortOrder;
|
||||||
|
bool visible;
|
||||||
|
bool isCommunityGroup;
|
||||||
|
QString communityId;
|
||||||
|
bool isCollectionGroup;
|
||||||
|
QString collectionUid;
|
||||||
|
/// covers separation of groups (collection or community) and collectibles (regular or community)
|
||||||
|
CollectiblePreferencesItemType type;
|
||||||
|
|
||||||
|
// Defines a default TokenOrder, order is not set (undefinedTokenOrder) and visible is false
|
||||||
|
TokenOrder();
|
||||||
|
TokenOrder(const QString& symbol,
|
||||||
|
int sortOrder,
|
||||||
|
bool visible,
|
||||||
|
bool isCommunityGroup,
|
||||||
|
const QString& communityId,
|
||||||
|
bool isCollectionGroup,
|
||||||
|
const QString& collectionUid,
|
||||||
|
CollectiblePreferencesItemType type);
|
||||||
|
|
||||||
|
bool operator==(const TokenOrder& rhs) const
|
||||||
|
{
|
||||||
|
return symbol == rhs.symbol && sortOrder == rhs.sortOrder && visible == rhs.visible &&
|
||||||
|
isCommunityGroup == rhs.isCommunityGroup && (!isCommunityGroup || communityId == rhs.communityId) &&
|
||||||
|
isCollectionGroup == rhs.isCollectionGroup && (!isCollectionGroup || collectionUid == rhs.collectionUid) && type == rhs.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString getGroupId() const { return !communityId.isEmpty() ? communityId : collectionUid; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using SerializedTokenData = QHash<QString, TokenOrder>;
|
||||||
|
|
||||||
|
QString tokenOrdersToJson(const SerializedTokenData& data, bool areCollectibles);
|
||||||
|
SerializedTokenData tokenOrdersFromJson(const QString& json_string, bool areCollectibles);
|
|
@ -22,7 +22,8 @@ DoubleFlickableWithFolding {
|
||||||
property var getCurrentCurrencyAmount: function(balance) {}
|
property var getCurrentCurrencyAmount: function(balance) {}
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
root.controller.saveSettings();
|
let jsonSettings = root.controller.serializeSettingsAsJson()
|
||||||
|
root.controller.requestSaveSettings(jsonSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert() {
|
function revert() {
|
||||||
|
@ -30,7 +31,7 @@ DoubleFlickableWithFolding {
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSettings() {
|
function clearSettings() {
|
||||||
root.controller.clearSettings();
|
root.controller.requestClearSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
|
|
|
@ -19,7 +19,8 @@ DoubleFlickableWithFolding {
|
||||||
readonly property bool hasSettings: root.controller.hasSettings
|
readonly property bool hasSettings: root.controller.hasSettings
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
root.controller.saveSettings();
|
let jsonSettings = root.controller.serializeSettingsAsJson()
|
||||||
|
root.controller.requestSaveSettings(jsonSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
function revert() {
|
function revert() {
|
||||||
|
@ -27,7 +28,7 @@ DoubleFlickableWithFolding {
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearSettings() {
|
function clearSettings() {
|
||||||
root.controller.clearSettings();
|
root.controller.requestClearSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
clip: true
|
clip: true
|
||||||
|
|
|
@ -31,8 +31,8 @@ Control {
|
||||||
background: null
|
background: null
|
||||||
|
|
||||||
function clearSettings() {
|
function clearSettings() {
|
||||||
root.assetsController.clearSettings();
|
root.assetsController.requestClearSettings();
|
||||||
root.collectiblesController.clearSettings();
|
root.collectiblesController.requestClearSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
|
|
|
@ -29,6 +29,24 @@ QtObject {
|
||||||
readonly property var collectiblesController: ManageTokensController {
|
readonly property var collectiblesController: ManageTokensController {
|
||||||
sourceModel: allCollectiblesModel
|
sourceModel: allCollectiblesModel
|
||||||
settingsKey: "WalletCollectibles"
|
settingsKey: "WalletCollectibles"
|
||||||
|
serializeAsCollectibles: true
|
||||||
|
|
||||||
|
onRequestSaveSettings: (jsonData) => {
|
||||||
|
savingStarted()
|
||||||
|
_allCollectiblesModule.updateCollectiblePreferences(jsonData)
|
||||||
|
savingFinished()
|
||||||
|
}
|
||||||
|
onRequestLoadSettings: {
|
||||||
|
loadingStarted()
|
||||||
|
let jsonData = _allCollectiblesModule.getCollectiblePreferencesJson()
|
||||||
|
loadingFinished(jsonData)
|
||||||
|
}
|
||||||
|
onRequestClearSettings: {
|
||||||
|
savingStarted()
|
||||||
|
_allCollectiblesModule.clearCollectiblePreferences()
|
||||||
|
savingFinished()
|
||||||
|
}
|
||||||
|
|
||||||
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
||||||
qsTr("%1 community collectibles successfully hidden").arg(communityName), "", "checkmark-circle",
|
qsTr("%1 community collectibles successfully hidden").arg(communityName), "", "checkmark-circle",
|
||||||
false, Constants.ephemeralNotificationType.success, "")
|
false, Constants.ephemeralNotificationType.success, "")
|
||||||
|
|
|
@ -18,6 +18,25 @@ QtObject {
|
||||||
readonly property var assetsController: ManageTokensController {
|
readonly property var assetsController: ManageTokensController {
|
||||||
sourceModel: groupedAccountAssetsModel
|
sourceModel: groupedAccountAssetsModel
|
||||||
settingsKey: "WalletAssets"
|
settingsKey: "WalletAssets"
|
||||||
|
serializeAsCollectibles: false
|
||||||
|
|
||||||
|
// TODO #13312: call the assets controller for all events
|
||||||
|
onRequestSaveSettings: (jsonData) => {
|
||||||
|
// savingStarted()
|
||||||
|
saveToQSettings(jsonData)
|
||||||
|
// savingFinished()
|
||||||
|
}
|
||||||
|
onRequestLoadSettings: {
|
||||||
|
// loadingStarted()
|
||||||
|
loadFromQSettings()
|
||||||
|
// loadingFinished()
|
||||||
|
}
|
||||||
|
onRequestClearSettings: {
|
||||||
|
// savingStarted()
|
||||||
|
clearQSettings()
|
||||||
|
// savingFinished()
|
||||||
|
}
|
||||||
|
|
||||||
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
onCommunityTokenGroupHidden: (communityName) => Global.displayToastMessage(
|
||||||
qsTr("%1 community assets successfully hidden").arg(communityName), "", "checkmark-circle",
|
qsTr("%1 community assets successfully hidden").arg(communityName), "", "checkmark-circle",
|
||||||
false, Constants.ephemeralNotificationType.success, "")
|
false, Constants.ephemeralNotificationType.success, "")
|
||||||
|
|
Loading…
Reference in New Issue