performance: Improve the wallet loading time
+ small bug fixes
This commit is contained in:
parent
a6abdbeeef
commit
a55dcf299e
|
@ -26,6 +26,9 @@ QtObject:
|
|||
extradata: ExtraData
|
||||
traits: TraitModel
|
||||
ownership: OwnershipModel
|
||||
generatedId: string
|
||||
generatedCollectionId: string
|
||||
|
||||
|
||||
proc setup(self: CollectiblesEntry) =
|
||||
self.QObject.setup
|
||||
|
@ -45,32 +48,6 @@ QtObject:
|
|||
self.ownership.setItems(ownership)
|
||||
self.setup()
|
||||
|
||||
proc newCollectibleDetailsFullEntry*(data: backend.Collectible, extradata: ExtraData): CollectiblesEntry =
|
||||
new(result, delete)
|
||||
result.id = data.id
|
||||
result.setData(data)
|
||||
result.extradata = extradata
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsBasicEntry*(id: backend.CollectibleUniqueID, extradata: ExtraData): CollectiblesEntry =
|
||||
new(result, delete)
|
||||
result.id = id
|
||||
result.extradata = extradata
|
||||
result.traits = newTraitModel()
|
||||
result.ownership = newOwnershipModel()
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsEmptyEntry*(): CollectiblesEntry =
|
||||
let id = backend.CollectibleUniqueID(
|
||||
contractID: backend.ContractID(
|
||||
chainID: 0,
|
||||
address: ""
|
||||
),
|
||||
tokenID: stint.u256(0)
|
||||
)
|
||||
let extradata = ExtraData()
|
||||
return newCollectibleDetailsBasicEntry(id, extradata)
|
||||
|
||||
proc `$`*(self: CollectiblesEntry): string =
|
||||
return fmt"""CollectiblesEntry(
|
||||
id:{self.id},
|
||||
|
@ -78,6 +55,8 @@ QtObject:
|
|||
extradata:{self.extradata},
|
||||
traits:{self.traits},
|
||||
ownership:{self.ownership},
|
||||
generatedId:{self.generatedId},
|
||||
generatedCollectionId:{self.generatedCollectionId}
|
||||
)"""
|
||||
|
||||
proc getCollectibleUniqueID*(self: CollectiblesEntry): backend.CollectibleUniqueID =
|
||||
|
@ -130,10 +109,16 @@ QtObject:
|
|||
|
||||
# Unique ID to identify collectible, generated by us
|
||||
proc getID*(self: CollectiblesEntry): string =
|
||||
return self.generatedId
|
||||
|
||||
proc generateId*(self: CollectiblesEntry): string =
|
||||
return fmt"{self.getChainId}+{self.getContractAddress}+{self.getTokenID}"
|
||||
|
||||
# Unique ID to identify collection, generated by us
|
||||
proc getCollectionID*(self: CollectiblesEntry): string =
|
||||
return self.generatedCollectionId
|
||||
|
||||
proc generateCollectionId*(self: CollectiblesEntry): string =
|
||||
return fmt"{self.getChainId}+{self.getContractAddress}"
|
||||
|
||||
proc nameChanged*(self: CollectiblesEntry) {.signal.}
|
||||
|
@ -360,3 +345,33 @@ QtObject:
|
|||
self.communityPrivilegesLevelChanged()
|
||||
self.communityImageChanged()
|
||||
return true
|
||||
|
||||
proc newCollectibleDetailsFullEntry*(data: backend.Collectible, extradata: ExtraData): CollectiblesEntry =
|
||||
new(result, delete)
|
||||
result.id = data.id
|
||||
result.setData(data)
|
||||
result.extradata = extradata
|
||||
result.generatedId = result.generateId()
|
||||
result.generatedCollectionId = result.generateCollectionId()
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsBasicEntry*(id: backend.CollectibleUniqueID, extradata: ExtraData): CollectiblesEntry =
|
||||
new(result, delete)
|
||||
result.id = id
|
||||
result.extradata = extradata
|
||||
result.traits = newTraitModel()
|
||||
result.ownership = newOwnershipModel()
|
||||
result.generatedId = result.generateId()
|
||||
result.generatedCollectionId = result.generateCollectionId()
|
||||
result.setup()
|
||||
|
||||
proc newCollectibleDetailsEmptyEntry*(): CollectiblesEntry =
|
||||
let id = backend.CollectibleUniqueID(
|
||||
contractID: backend.ContractID(
|
||||
chainID: 0,
|
||||
address: ""
|
||||
),
|
||||
tokenID: stint.u256(0)
|
||||
)
|
||||
let extradata = ExtraData()
|
||||
return newCollectibleDetailsBasicEntry(id, extradata)
|
|
@ -5,6 +5,8 @@
|
|||
#include <QQmlContext>
|
||||
#include <QQmlExpression>
|
||||
#include <QQmlScriptString>
|
||||
#include <QSet>
|
||||
#include <QQmlPropertyMap>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -14,9 +16,10 @@ class FastExpressionSorter : public qqsfpm::Sorter
|
|||
Q_PROPERTY(QQmlScriptString expression READ expression
|
||||
WRITE setExpression NOTIFY expressionChanged)
|
||||
|
||||
Q_PROPERTY(QStringList expectedRoles READ expectedRoles
|
||||
Q_PROPERTY(QSet<QByteArray> expectedRoles READ expectedRoles
|
||||
WRITE setExpectedRoles NOTIFY expectedRolesChanged)
|
||||
public:
|
||||
|
||||
using qqsfpm::Sorter::Sorter;
|
||||
|
||||
const QQmlScriptString& expression() const;
|
||||
|
@ -24,16 +27,18 @@ public:
|
|||
|
||||
void proxyModelCompleted(const qqsfpm::QQmlSortFilterProxyModel& proxyModel) override;
|
||||
|
||||
void setExpectedRoles(const QStringList& expectedRoles);
|
||||
const QStringList& expectedRoles() const;
|
||||
void setExpectedRoles(const QSet<QByteArray>& expectedRoles);
|
||||
const QSet<QByteArray>& expectedRoles() const;
|
||||
|
||||
void queueInvalidate();
|
||||
void onInvalidate();
|
||||
|
||||
Q_SIGNALS:
|
||||
void expressionChanged();
|
||||
void expectedRolesChanged();
|
||||
|
||||
protected:
|
||||
int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight,
|
||||
const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const override;
|
||||
int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const override;
|
||||
|
||||
private:
|
||||
void updateContext(const qqsfpm::QQmlSortFilterProxyModel& proxyModel);
|
||||
|
@ -44,5 +49,10 @@ private:
|
|||
std::unique_ptr<QQmlExpression> m_expression;
|
||||
std::unique_ptr<QQmlContext> m_context;
|
||||
|
||||
QStringList m_expectedRoles;
|
||||
QSet<QByteArray> m_expectedRoles;
|
||||
|
||||
bool m_queuedInvalidate { false };
|
||||
|
||||
mutable QQmlPropertyMap m_modelLeftMap;
|
||||
mutable QQmlPropertyMap m_modelRightMap;
|
||||
};
|
||||
|
|
|
@ -50,12 +50,28 @@ void FastExpressionSorter::setExpression(const QQmlScriptString& scriptString)
|
|||
updateExpression();
|
||||
|
||||
emit expressionChanged();
|
||||
invalidate();
|
||||
queueInvalidate();
|
||||
}
|
||||
|
||||
void FastExpressionSorter::queueInvalidate()
|
||||
{
|
||||
if (m_queuedInvalidate)
|
||||
return;
|
||||
|
||||
m_queuedInvalidate = true;
|
||||
QMetaObject::invokeMethod(this, &FastExpressionSorter::invalidate, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void FastExpressionSorter::onInvalidate()
|
||||
{
|
||||
m_queuedInvalidate = false;
|
||||
Sorter::invalidate();
|
||||
}
|
||||
|
||||
void FastExpressionSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel)
|
||||
{
|
||||
updateContext(proxyModel);
|
||||
Sorter::proxyModelCompleted(proxyModel);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -63,7 +79,7 @@ void FastExpressionSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& p
|
|||
|
||||
List of role names intended to be available in the expression's context.
|
||||
*/
|
||||
void FastExpressionSorter::setExpectedRoles(const QStringList& expectedRoles)
|
||||
void FastExpressionSorter::setExpectedRoles(const QSet<QByteArray>& expectedRoles)
|
||||
{
|
||||
if (m_expectedRoles == expectedRoles)
|
||||
return;
|
||||
|
@ -71,44 +87,45 @@ void FastExpressionSorter::setExpectedRoles(const QStringList& expectedRoles)
|
|||
m_expectedRoles = expectedRoles;
|
||||
emit expectedRolesChanged();
|
||||
|
||||
invalidate();
|
||||
queueInvalidate();
|
||||
}
|
||||
|
||||
const QStringList &FastExpressionSorter::expectedRoles() const
|
||||
const QSet<QByteArray> &FastExpressionSorter::expectedRoles() const
|
||||
{
|
||||
return m_expectedRoles;
|
||||
}
|
||||
|
||||
bool evaluateBoolExpression(QQmlExpression& expression)
|
||||
int evaluateIntExpression(QQmlExpression& expression)
|
||||
{
|
||||
QVariant variantResult = expression.evaluate();
|
||||
if (expression.hasError()) {
|
||||
qWarning() << expression.error();
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (variantResult.canConvert<bool>())
|
||||
return variantResult.toBool();
|
||||
if (variantResult.canConvert<int>())
|
||||
return variantResult.toInt();
|
||||
|
||||
qWarning("%s:%i:%i : Can't convert result to bool",
|
||||
qWarning("%s:%i:%i : Can't convert result to int",
|
||||
expression.sourceFile().toUtf8().data(),
|
||||
expression.lineNumber(),
|
||||
expression.columnNumber());
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int FastExpressionSorter::compare(const QModelIndex& sourceLeft,
|
||||
const QModelIndex& sourceRight,
|
||||
const QQmlSortFilterProxyModel& proxyModel) const
|
||||
{
|
||||
if (m_scriptString.isEmpty())
|
||||
return 0;
|
||||
|
||||
QVariantMap modelLeftMap, modelRightMap;
|
||||
if (m_scriptString.isEmpty() || !m_context || !m_expression)
|
||||
return false;
|
||||
|
||||
m_expression->setNotifyOnValueChanged(false);
|
||||
|
||||
QHash<int, QByteArray> roles = proxyModel.roleNames();
|
||||
|
||||
QQmlContext context(qmlContext(this));
|
||||
|
||||
for (auto it = roles.cbegin(); it != roles.cend(); ++it) {
|
||||
auto role = it.key();
|
||||
auto name = it.value();
|
||||
|
@ -116,50 +133,42 @@ int FastExpressionSorter::compare(const QModelIndex& sourceLeft,
|
|||
if (!m_expectedRoles.contains(name))
|
||||
continue;
|
||||
|
||||
modelLeftMap.insert(name, proxyModel.sourceData(sourceLeft, role));
|
||||
modelRightMap.insert(name, proxyModel.sourceData(sourceRight, role));
|
||||
m_modelLeftMap.insert(name, proxyModel.sourceData(sourceLeft, role));
|
||||
m_modelRightMap.insert(name, proxyModel.sourceData(sourceRight, role));
|
||||
}
|
||||
modelLeftMap.insert(QStringLiteral("index"), sourceLeft.row());
|
||||
modelRightMap.insert(QStringLiteral("index"), sourceRight.row());
|
||||
m_modelLeftMap.insert(QStringLiteral("index"), sourceLeft.row());
|
||||
m_modelRightMap.insert(QStringLiteral("index"), sourceRight.row());
|
||||
|
||||
QQmlExpression expression(m_scriptString, &context);
|
||||
m_expression->setNotifyOnValueChanged(true);
|
||||
|
||||
context.setContextProperty(QStringLiteral("modelLeft"), modelLeftMap);
|
||||
context.setContextProperty(QStringLiteral("modelRight"), modelRightMap);
|
||||
|
||||
if (evaluateBoolExpression(expression))
|
||||
return -1;
|
||||
|
||||
context.setContextProperty(QStringLiteral("modelLeft"), modelRightMap);
|
||||
context.setContextProperty(QStringLiteral("modelRight"), modelLeftMap);
|
||||
|
||||
if (evaluateBoolExpression(expression))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return evaluateIntExpression(*m_expression);
|
||||
}
|
||||
|
||||
void FastExpressionSorter::updateContext(const QQmlSortFilterProxyModel& proxyModel)
|
||||
{
|
||||
m_context = std::make_unique<QQmlContext>(qmlContext(this));
|
||||
updateExpression();
|
||||
|
||||
QVariantMap modelLeftMap, modelRightMap;
|
||||
if (!m_expression)
|
||||
return;
|
||||
|
||||
m_expression->setNotifyOnValueChanged(false);
|
||||
|
||||
const auto roleNames = proxyModel.roleNames();
|
||||
for (const QByteArray& name : roleNames) {
|
||||
if (!m_expectedRoles.contains(name))
|
||||
continue;
|
||||
|
||||
modelLeftMap.insert(name, {});
|
||||
modelRightMap.insert(name, {});
|
||||
m_modelLeftMap.insert(name, {});
|
||||
m_modelRightMap.insert(name, {});
|
||||
}
|
||||
modelLeftMap.insert(QStringLiteral("index"), -1);
|
||||
modelRightMap.insert(QStringLiteral("index"), -1);
|
||||
m_modelLeftMap.insert(QStringLiteral("index"), -1);
|
||||
m_modelRightMap.insert(QStringLiteral("index"), -1);
|
||||
|
||||
m_context->setContextProperty(QStringLiteral("modelLeft"), modelLeftMap);
|
||||
m_context->setContextProperty(QStringLiteral("modelRight"), modelRightMap);
|
||||
m_context->setContextProperty(QStringLiteral("modelLeft"), &m_modelLeftMap);
|
||||
m_context->setContextProperty(QStringLiteral("modelRight"), &m_modelRightMap);
|
||||
|
||||
updateExpression();
|
||||
m_expression->setNotifyOnValueChanged(true);
|
||||
}
|
||||
|
||||
void FastExpressionSorter::updateExpression()
|
||||
|
@ -171,7 +180,7 @@ void FastExpressionSorter::updateExpression()
|
|||
m_context.get());
|
||||
|
||||
connect(m_expression.get(), &QQmlExpression::valueChanged, this,
|
||||
&FastExpressionSorter::invalidate);
|
||||
&FastExpressionSorter::queueInvalidate);
|
||||
m_expression->setNotifyOnValueChanged(true);
|
||||
m_expression->evaluate();
|
||||
}
|
||||
|
|
|
@ -239,8 +239,7 @@ void ManageTokensController::loadSettings()
|
|||
{
|
||||
Q_ASSERT(!m_settingsKey.isEmpty());
|
||||
|
||||
setSettingsDirty(true);
|
||||
m_settingsData.clear();
|
||||
SerializedTokenData result;
|
||||
|
||||
// load from QSettings
|
||||
m_settings.beginGroup(settingsGroupName());
|
||||
|
@ -256,7 +255,7 @@ void ManageTokensController::loadSettings()
|
|||
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();
|
||||
m_settingsData.insert(symbol, {pos, visible, groupId});
|
||||
result.insert(symbol, {pos, visible, groupId});
|
||||
}
|
||||
m_settings.endArray();
|
||||
|
||||
|
@ -277,7 +276,11 @@ void ManageTokensController::loadSettings()
|
|||
setArrangeByCollection(m_settings.value(QStringLiteral("ArrangeByCollection"), false).toBool());
|
||||
|
||||
m_settings.endGroup();
|
||||
setSettingsDirty(false);
|
||||
|
||||
if (result != m_settingsData) {
|
||||
m_settingsData = result;
|
||||
setSettingsDirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ManageTokensController::setSettingsDirty(bool dirty)
|
||||
|
@ -353,7 +356,7 @@ void ManageTokensController::settingsHideGroupTokens(const QString& groupId, con
|
|||
saveSettings(true);
|
||||
}
|
||||
|
||||
bool ManageTokensController::lessThan(const QString& lhsSymbol, const QString& rhsSymbol) const
|
||||
int ManageTokensController::compareTokens(const QString& lhsSymbol, const QString& rhsSymbol) const
|
||||
{
|
||||
int leftPos, rightPos;
|
||||
bool leftVisible, rightVisible;
|
||||
|
@ -365,7 +368,11 @@ bool ManageTokensController::lessThan(const QString& lhsSymbol, const QString& r
|
|||
leftPos = leftVisible ? leftPos : INT_MAX;
|
||||
rightPos = rightVisible ? rightPos : INT_MAX;
|
||||
|
||||
return leftPos <= rightPos;
|
||||
if (leftPos < rightPos)
|
||||
return -1;
|
||||
if (leftPos > rightPos)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ManageTokensController::filterAcceptsSymbol(const QString& symbol) const
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
Q_INVOKABLE void settingsHideToken(const QString& symbol);
|
||||
Q_INVOKABLE void settingsHideGroupTokens(const QString& groupId, const QStringList& symbols);
|
||||
|
||||
Q_INVOKABLE bool lessThan(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;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -17,17 +17,21 @@ Item {
|
|||
property int d: 1
|
||||
|
||||
property alias sorterEnabled: sorter.enabled
|
||||
property alias sortingAscending: sorter.ascendingOrder
|
||||
property alias sorters: testModel.sorters
|
||||
|
||||
readonly property ListModel source: ListModel {
|
||||
id: listModel
|
||||
|
||||
ListElement { a: 1; b: 11; c: 101 }
|
||||
ListElement { a: 2; b: 12; c: 102 }
|
||||
ListElement { a: 1; b: 11; c: 100 }
|
||||
ListElement { a: 2; b: 11; c: 101 }
|
||||
ListElement { a: 3; b: 13; c: 103 }
|
||||
ListElement { a: 4; b: 14; c: 104 }
|
||||
ListElement { a: 5; b: 15; c: 105 }
|
||||
ListElement { a: 6; b: 16; c: 106 }
|
||||
ListElement { a: 2; b: 12; c: 101 }
|
||||
ListElement { a: 7; b: 17; c: 107 }
|
||||
ListElement { a: 7; b: 17; c: 108 }
|
||||
}
|
||||
|
||||
readonly property ModelAccessObserverProxy observer: ModelAccessObserverProxy {
|
||||
|
@ -44,28 +48,71 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
readonly property SortFilterProxyModel model: SortFilterProxyModel {
|
||||
property SortFilterProxyModel model: SortFilterProxyModel {
|
||||
id: testModel
|
||||
|
||||
sourceModel: observerProxy
|
||||
|
||||
sorters: FastExpressionSorter {
|
||||
sorters: [sorter]
|
||||
}
|
||||
|
||||
readonly property Component modelWithPriorityComponent: Component {
|
||||
SortFilterProxyModel {
|
||||
id: testModelWithPriority
|
||||
|
||||
sourceModel: observerProxy
|
||||
|
||||
sorters: [sorter, otherSorter, roleSorter]
|
||||
}
|
||||
}
|
||||
|
||||
readonly property FastExpressionSorter sorter: FastExpressionSorter {
|
||||
id: sorter
|
||||
|
||||
expression: {
|
||||
return d ? modelLeft.a < modelRight.a
|
||||
: modelLeft.a > modelRight.a
|
||||
if (modelLeft.a < modelRight.a)
|
||||
return d ? -1 : 1
|
||||
else if (modelLeft.a > modelRight.a)
|
||||
return d ? 1 : -1
|
||||
else
|
||||
return 0
|
||||
}
|
||||
|
||||
expectedRoles: ["a"]
|
||||
|
||||
}
|
||||
|
||||
readonly property FastExpressionSorter otherSorter: FastExpressionSorter {
|
||||
id: otherSorter
|
||||
|
||||
expression: {
|
||||
if (modelLeft.b > modelRight.b)
|
||||
return -1
|
||||
else if (modelLeft.b < modelRight.b)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
}
|
||||
|
||||
expectedRoles: ["b"]
|
||||
}
|
||||
|
||||
readonly property RoleSorter roleSorter: RoleSorter {
|
||||
id: roleSorter
|
||||
|
||||
roleName: "c"
|
||||
ascendingOrder: false
|
||||
}
|
||||
|
||||
readonly property SignalSpy rowsRemovedSpy: SignalSpy {
|
||||
target: testModel
|
||||
signalName: "rowsRemoved"
|
||||
}
|
||||
|
||||
readonly property SignalSpy layoutChangedSpy: SignalSpy {
|
||||
id: layoutChangedSpy
|
||||
target: testModel
|
||||
signalName: "layoutChanged"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,17 +123,17 @@ Item {
|
|||
const obj = createTemporaryObject(testComponent, root)
|
||||
const count = obj.model.count
|
||||
|
||||
compare(count, 7)
|
||||
compare(count, 9)
|
||||
verify(obj.observer.accessCounter
|
||||
< count * Math.ceil(Math.log2(count)) * 3)
|
||||
compare(obj.observer.accessedRoles.size, 1)
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(6).a, 7)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
}
|
||||
|
||||
function test_filteringAfterContextChange() {
|
||||
function test_sortingAfterContextChange() {
|
||||
const obj = createTemporaryObject(testComponent, root)
|
||||
const count = obj.model.count
|
||||
|
||||
|
@ -98,9 +145,9 @@ Item {
|
|||
< count * Math.ceil(Math.log2(count)) * 3)
|
||||
compare(obj.observer.accessedRoles.size, 1)
|
||||
|
||||
compare(obj.model.get(0).a, 7)
|
||||
compare(obj.model.get(1).a, 6)
|
||||
compare(obj.model.get(6).a, 1)
|
||||
tryVerify(() => obj.model.get(0).a, 7)
|
||||
tryVerify(() => obj.model.get(1).a, 6)
|
||||
tryVerify(() => obj.model.get(6).a, 1)
|
||||
}
|
||||
|
||||
function test_enabled() {
|
||||
|
@ -110,7 +157,7 @@ Item {
|
|||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(6).a, 7)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
|
||||
obj.observer.accessedRoles.clear()
|
||||
obj.observer.accessCounter = 0
|
||||
|
@ -123,8 +170,236 @@ Item {
|
|||
compare(obj.observer.accessedRoles.size, 1)
|
||||
|
||||
compare(obj.model.get(0).a, 7)
|
||||
compare(obj.model.get(1).a, 6)
|
||||
compare(obj.model.get(6).a, 1)
|
||||
compare(obj.model.get(1).a, 7)
|
||||
compare(obj.model.get(7).a, 2)
|
||||
compare(obj.model.get(8).a, 1)
|
||||
}
|
||||
|
||||
function test_sortingDescending() {
|
||||
const obj = createTemporaryObject(testComponent, root)
|
||||
|
||||
const count = obj.model.count
|
||||
|
||||
verify(obj.observer.accessCounter
|
||||
< count * Math.ceil(Math.log2(count)) * 3)
|
||||
compare(obj.observer.accessedRoles.size, 1)
|
||||
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
|
||||
obj.observer.accessCounter = 0
|
||||
|
||||
obj.sortingAscending = false
|
||||
|
||||
tryVerify(() => obj.observer.accessCounter
|
||||
< count * Math.ceil(Math.log2(count)) * 3)
|
||||
|
||||
tryVerify(() => obj.model.get(0).a, 7)
|
||||
tryVerify(() => obj.model.get(1).a, 6)
|
||||
tryVerify(() => obj.model.get(7).a, 1)
|
||||
}
|
||||
|
||||
function test_sortingDescendingAfterEnablingSorting() {
|
||||
const obj = createTemporaryObject(testComponent, root, { sorterEnabled: false, sortingAscending: false })
|
||||
|
||||
compare(obj.observer.accessCounter, 0)
|
||||
compare(obj.observer.accessedRoles.size, 0)
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
|
||||
obj.observer.accessedRoles.clear()
|
||||
obj.observer.accessCounter = 0
|
||||
|
||||
obj.sorterEnabled = true
|
||||
|
||||
const count = obj.model.count
|
||||
|
||||
verify(obj.observer.accessCounter
|
||||
< count * Math.ceil(Math.log2(count)) * 3)
|
||||
|
||||
compare(obj.observer.accessedRoles.size, 1)
|
||||
|
||||
compare(obj.model.get(0).a, 7)
|
||||
compare(obj.model.get(1).a, 7)
|
||||
compare(obj.model.get(8).a, 1)
|
||||
|
||||
obj.observer.accessedRoles.clear()
|
||||
obj.observer.accessCounter = 0
|
||||
|
||||
obj.sorterEnabled = false
|
||||
|
||||
verify(obj.observer.accessCounter == 0)
|
||||
|
||||
compare(obj.observer.accessedRoles.size, 0)
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
}
|
||||
|
||||
function test_stableSorting() {
|
||||
const obj = createTemporaryObject(testComponent, root)
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
|
||||
obj.sortingAscending = false
|
||||
|
||||
compare(obj.model.get(8).a, 1)
|
||||
compare(obj.model.get(7).a, 2)
|
||||
compare(obj.model.get(6).a, 2)
|
||||
compare(obj.model.get(8).b, 11)
|
||||
compare(obj.model.get(7).b, 12)
|
||||
compare(obj.model.get(6).b, 11)
|
||||
compare(obj.model.get(8).c, 100)
|
||||
compare(obj.model.get(7).c, 101)
|
||||
compare(obj.model.get(6).c, 101)
|
||||
|
||||
|
||||
obj.sortingAscending = true
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
|
||||
obj.source.append({a: 2, b: 13, c: 101})
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(3).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(3).b, 13)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
compare(obj.model.get(3).c, 101)
|
||||
|
||||
obj.sortingAscending = false
|
||||
|
||||
compare(obj.model.get(9).a, 1)
|
||||
compare(obj.model.get(8).a, 2)
|
||||
compare(obj.model.get(7).a, 2)
|
||||
compare(obj.model.get(6).a, 2)
|
||||
compare(obj.model.get(9).b, 11)
|
||||
compare(obj.model.get(8).b, 13)
|
||||
compare(obj.model.get(7).b, 12)
|
||||
compare(obj.model.get(6).b, 11)
|
||||
compare(obj.model.get(9).c, 100)
|
||||
compare(obj.model.get(8).c, 101)
|
||||
compare(obj.model.get(7).c, 101)
|
||||
compare(obj.model.get(6).c, 101)
|
||||
}
|
||||
|
||||
function test_default_stableSorting() {
|
||||
const obj = createTemporaryObject(testComponent, root, { sorters: [] })
|
||||
|
||||
obj.model.sortRoleName = "a"
|
||||
obj.model.ascendingSortOrder = true
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
|
||||
obj.model.ascendingSortOrder = false
|
||||
|
||||
compare(obj.model.get(8).a, 1)
|
||||
compare(obj.model.get(7).a, 2)
|
||||
compare(obj.model.get(6).a, 2)
|
||||
compare(obj.model.get(8).b, 11)
|
||||
compare(obj.model.get(7).b, 12)
|
||||
compare(obj.model.get(6).b, 11)
|
||||
compare(obj.model.get(8).c, 100)
|
||||
compare(obj.model.get(7).c, 101)
|
||||
compare(obj.model.get(6).c, 101)
|
||||
|
||||
|
||||
obj.model.ascendingSortOrder = true
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
|
||||
obj.source.append({a: 2, b: 13, c: 101})
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(3).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 11)
|
||||
compare(obj.model.get(2).b, 12)
|
||||
compare(obj.model.get(3).b, 13)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
compare(obj.model.get(3).c, 101)
|
||||
|
||||
obj.model.ascendingSortOrder = false
|
||||
|
||||
compare(obj.model.get(9).a, 1)
|
||||
compare(obj.model.get(8).a, 2)
|
||||
compare(obj.model.get(7).a, 2)
|
||||
compare(obj.model.get(6).a, 2)
|
||||
compare(obj.model.get(9).b, 11)
|
||||
compare(obj.model.get(8).b, 13)
|
||||
compare(obj.model.get(7).b, 12)
|
||||
compare(obj.model.get(6).b, 11)
|
||||
compare(obj.model.get(9).c, 100)
|
||||
compare(obj.model.get(8).c, 101)
|
||||
compare(obj.model.get(7).c, 101)
|
||||
compare(obj.model.get(6).c, 101)
|
||||
}
|
||||
|
||||
function test_sortWithPriority() {
|
||||
const obj = createTemporaryObject(testComponent, root)
|
||||
|
||||
obj.model = createTemporaryObject(obj.modelWithPriorityComponent, obj)
|
||||
|
||||
compare(obj.model.get(0).a, 1)
|
||||
compare(obj.model.get(1).a, 2)
|
||||
compare(obj.model.get(2).a, 2)
|
||||
compare(obj.model.get(0).b, 11)
|
||||
compare(obj.model.get(1).b, 12) // descending "b"
|
||||
compare(obj.model.get(2).b, 11)
|
||||
compare(obj.model.get(0).c, 100)
|
||||
compare(obj.model.get(1).c, 101)
|
||||
compare(obj.model.get(2).c, 101)
|
||||
compare(obj.model.get(7).a, 7)
|
||||
compare(obj.model.get(8).a, 7)
|
||||
compare(obj.model.get(7).c, 108) // descending "c"
|
||||
compare(obj.model.get(8).c, 107)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,12 @@ StatusListView {
|
|||
}
|
||||
sorters: FastExpressionSorter {
|
||||
expression: {
|
||||
return modelLeft.enabledNetworkBalance > modelRight.enabledNetworkBalance // descending, biggest first
|
||||
if (modelLeft.enabledNetworkBalance > modelRight.enabledNetworkBalance)
|
||||
return -1 // descending, biggest first
|
||||
else if (modelLeft.enabledNetworkBalance < modelRight.enabledNetworkBalance)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
}
|
||||
expectedRoles: ["enabledNetworkBalance"]
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ ColumnLayout {
|
|||
FastExpressionSorter {
|
||||
expression: {
|
||||
d.controller.settingsDirty
|
||||
return d.controller.lessThan(modelLeft.symbol, modelRight.symbol)
|
||||
return d.controller.compareTokens(modelLeft.symbol, modelRight.symbol)
|
||||
}
|
||||
enabled: d.isCustomView
|
||||
expectedRoles: ["symbol"]
|
||||
|
|
|
@ -131,7 +131,6 @@ RightTabBaseView {
|
|||
case 2: return historyView
|
||||
}
|
||||
}
|
||||
active: visible
|
||||
|
||||
Component {
|
||||
id: assetsView
|
||||
|
|
|
@ -140,7 +140,7 @@ ColumnLayout {
|
|||
FastExpressionSorter {
|
||||
expression: {
|
||||
d.controller.settingsDirty
|
||||
return d.controller.lessThan(modelLeft.symbol, modelRight.symbol)
|
||||
return d.controller.compareTokens(modelLeft.symbol, modelRight.symbol)
|
||||
}
|
||||
enabled: d.isCustomView
|
||||
expectedRoles: ["symbol"]
|
||||
|
@ -175,6 +175,7 @@ ColumnLayout {
|
|||
Layout.preferredHeight: root.filterVisible ? implicitHeight : 0
|
||||
spacing: 20
|
||||
opacity: root.filterVisible ? 1 : 0
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on Layout.preferredHeight { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
|
||||
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
|
||||
|
|
Loading…
Reference in New Issue