From 49c3a72516c6403d259cb11da541fac9c2d47a86 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Thu, 19 Feb 2026 19:05:16 +0300 Subject: [PATCH] fix(qt): stable sort for equal items in Coin Control dialog CCoinControlWidgetItem::operator< had no tiebreaker for equal numeric values (amount, date, confirmations, CoinJoin rounds), causing Qt's unstable sort to produce a different ordering on each updateView() call whenever coins with identical values were present. Add a secondary sort by outpoint (txid:vout), which is unique and stable across view rebuilds. Co-Authored-By: Claude Sonnet 4.6 --- src/qt/coincontroldialog.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index 7f2d077bc11b..57f80de67c28 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -39,8 +39,17 @@ bool CoinControlDialog::fSubtractFeeFromAmount = false; bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const { int column = treeWidget()->sortColumn(); - if (column == CoinControlDialog::COLUMN_AMOUNT || column == CoinControlDialog::COLUMN_DATE || column == CoinControlDialog::COLUMN_CONFIRMATIONS || column == CoinControlDialog::COLUMN_COINJOIN_ROUNDS) - return data(column, Qt::UserRole).toLongLong() < other.data(column, Qt::UserRole).toLongLong(); + if (column == CoinControlDialog::COLUMN_AMOUNT || column == CoinControlDialog::COLUMN_DATE || column == CoinControlDialog::COLUMN_CONFIRMATIONS || column == CoinControlDialog::COLUMN_COINJOIN_ROUNDS) { + long long a = data(column, Qt::UserRole).toLongLong(); + long long b = other.data(column, Qt::UserRole).toLongLong(); + if (a != b) return a < b; + // Stable tiebreaker: sort by outpoint (txid:vout) to ensure consistent ordering of equal items + int cmp = data(CoinControlDialog::COLUMN_ADDRESS, CoinControlDialog::TxHashRole).toString() + .compare(other.data(CoinControlDialog::COLUMN_ADDRESS, CoinControlDialog::TxHashRole).toString()); + if (cmp != 0) return cmp < 0; + return data(CoinControlDialog::COLUMN_ADDRESS, CoinControlDialog::VOutRole).toUInt() < + other.data(CoinControlDialog::COLUMN_ADDRESS, CoinControlDialog::VOutRole).toUInt(); + } return QTreeWidgetItem::operator<(other); }