-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: re-ordering list of filters to put Masternode between "Mined" and "Platform transfer" #7612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dc08f2f
75df77a
2bcb6c4
e5d1c57
5809821
bb24dc8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -118,16 +118,16 @@ class TransactionTypeSettingRestorer | |
| { | ||
| public: | ||
| TransactionTypeSettingRestorer() : | ||
| m_had_value(m_settings.contains("transactionType")), | ||
| m_value(m_settings.value("transactionType")) | ||
| m_had_value(m_settings.contains("transactionTypeFilter")), | ||
| m_value(m_settings.value("transactionTypeFilter")) | ||
| { | ||
| } | ||
| ~TransactionTypeSettingRestorer() | ||
| { | ||
| if (m_had_value) { | ||
| m_settings.setValue("transactionType", m_value); | ||
| m_settings.setValue("transactionTypeFilter", m_value); | ||
| } else { | ||
| m_settings.remove("transactionType"); | ||
| m_settings.remove("transactionTypeFilter"); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -158,55 +158,38 @@ void CheckProviderRecords(const TransactionTableModel& model, const std::vector< | |
| QVERIFY(tooltip.contains(record.label)); | ||
| QVERIFY(tooltip.contains(record.tooltip_text)); | ||
| QVERIFY(!tooltip.contains("Payment to yourself")); | ||
|
|
||
| const QString plain_text{base.data(TransactionTableModel::TxPlainTextRole).toString()}; | ||
| QVERIFY(plain_text.contains(record.label)); | ||
| QVERIFY(!plain_text.contains("Payment to yourself")); | ||
|
|
||
| const QString description{base.data(TransactionTableModel::LongDescriptionRole).toString()}; | ||
| QVERIFY(description.contains(record.label)); | ||
| QVERIFY(description.contains(QString::fromStdString(record.txid.ToString()))); | ||
| QVERIFY(description.contains("Net amount")); | ||
| QVERIFY(description.contains("Transaction total size")); | ||
| const QString summary{description.section("<hr>", 0, 0)}; | ||
| QVERIFY(!summary.contains("From:")); | ||
| QVERIFY(!summary.contains("To:")); | ||
| QVERIFY(!summary.contains("<b>Debit:</b>")); | ||
| QVERIFY(!summary.contains("<b>Credit:</b>")); | ||
| QVERIFY(!summary.contains("Output index")); | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| void ProviderTransactionTests::transactionTypeSettingCompatibility_data() | ||
| void ProviderTransactionTests::transactionTypeSettingPersistence_data() | ||
| { | ||
| QTest::addColumn<int>("saved_index"); | ||
| QTest::addColumn<quint32>("saved_filter"); | ||
| QTest::addColumn<QString>("expected_text"); | ||
| QTest::addColumn<quint32>("expected_filter"); | ||
|
|
||
| QTest::newRow("data") << 12 << QString{"Data Transaction"} | ||
| << TransactionFilterProxy::TYPE(TransactionRecord::DataTransaction); | ||
| QTest::newRow("dust") << 13 << QString{"Dust Receive"} << TransactionFilterProxy::TYPE(TransactionRecord::DustReceive); | ||
| QTest::newRow("other") << 14 << QString{"Other"} << TransactionFilterProxy::TYPE(TransactionRecord::Other); | ||
| QTest::newRow("masternode") << (TransactionFilterProxy::TYPE(TransactionRecord::MasternodeRegistration) | | ||
| TransactionFilterProxy::TYPE(TransactionRecord::MasternodeUpdate)) | ||
| << QString{"Masternode"}; | ||
| QTest::newRow("data") << TransactionFilterProxy::TYPE(TransactionRecord::DataTransaction) | ||
| << QString{"Data Transaction"}; | ||
| // An unknown stored filter selects nothing instead of an arbitrary entry. | ||
| QTest::newRow("unknown") << quint32{0} << QString{}; | ||
| } | ||
|
|
||
| void ProviderTransactionTests::transactionTypeSettingCompatibility() | ||
| void ProviderTransactionTests::transactionTypeSettingPersistence() | ||
| { | ||
| QFETCH(int, saved_index); | ||
| QFETCH(quint32, saved_filter); | ||
| QFETCH(QString, expected_text); | ||
| QFETCH(quint32, expected_filter); | ||
|
|
||
| TransactionTypeSettingRestorer setting_restorer; | ||
| QSettings{}.setValue("transactionType", saved_index); | ||
| QSettings{}.setValue("transactionTypeFilter", saved_filter); | ||
|
|
||
| TransactionView transaction_view; | ||
| QComboBox* const type_widget{FindTransactionTypeWidget(transaction_view)}; | ||
| QVERIFY(type_widget != nullptr); | ||
| QCOMPARE(type_widget->currentIndex(), saved_index); | ||
| QCOMPARE(type_widget->currentText(), expected_text); | ||
| QCOMPARE(type_widget->currentData().toUInt(), expected_filter); | ||
| QCOMPARE(type_widget->findText("Masternode"), 15); | ||
| QCOMPARE(type_widget->currentData().toUInt(), saved_filter); | ||
| } | ||
|
|
||
| void ProviderTransactionTests::providerTransactionHistory() | ||
|
|
@@ -301,13 +284,6 @@ void ProviderTransactionTests::providerTransactionHistory() | |
|
|
||
| // Transactions loaded before the model is constructed exercise the wallet-restart path. | ||
| CheckProviderRecords(*model, expected); | ||
| const std::vector<int> registrar_rows{FindTransactionRows(*model, update_registrar->GetHash())}; | ||
| QCOMPARE(registrar_rows.size(), size_t{1}); | ||
| const QString registrar_description{ | ||
| model->index(registrar_rows.front(), 0).data(TransactionTableModel::LongDescriptionRole).toString()}; | ||
| const QString registrar_summary{registrar_description.section("<hr>", 0, 0)}; | ||
| const QString external_address{QString::fromStdString(EncodeDestination(PKHash(external_key.GetPubKey())))}; | ||
| QVERIFY(!registrar_summary.contains(external_address)); | ||
|
|
||
| const std::vector<int> other_rows{FindTransactionRows(*model, other_special_tx->GetHash())}; | ||
| QCOMPARE(other_rows.size(), size_t{1}); | ||
|
|
@@ -355,20 +331,22 @@ void ProviderTransactionTests::providerTransactionHistory() | |
|
|
||
| QListView* const type_list{qobject_cast<QListView*>(type_widget->view())}; | ||
| QVERIFY(type_list != nullptr); | ||
| for (const quint32 coinjoin_filter : | ||
| {TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinSend), | ||
| TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinMakeCollaterals), | ||
| TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinCreateDenominations), | ||
| TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinMixing), | ||
| TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinCollateralPayment)}) { | ||
| const int row{type_widget->findData(coinjoin_filter)}; | ||
| QVERIFY(row >= 0); | ||
| QVERIFY(type_list->isRowHidden(row)); | ||
| // Match CoinJoin entries by title so filters added later are covered without | ||
| // duplicating the implementation's filter list. | ||
| int hidden_coinjoin_rows{0}; | ||
| for (int row{0}; row < type_widget->count(); ++row) { | ||
| const QString title{type_widget->itemText(row)}; | ||
| if (title.contains("coinjoin", Qt::CaseInsensitive) || title.contains("coin join", Qt::CaseInsensitive)) { | ||
| QVERIFY(type_list->isRowHidden(row)); | ||
| ++hidden_coinjoin_rows; | ||
| } | ||
| } | ||
| QVERIFY(hidden_coinjoin_rows > 0); | ||
| QVERIFY(!type_list->isRowHidden(masternode_row)); | ||
|
|
||
| type_widget->setCurrentIndex(masternode_row); | ||
| transaction_view.chooseType(masternode_row); | ||
| QCOMPARE(QSettings{}.value("transactionTypeFilter").toUInt(), masternode_filter); | ||
|
Comment on lines
345
to
+349
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Keep coverage for CoinJoin row visibility.
As per coding guidelines, choose targeted C++ unit tests for changed behavior. 🤖 Prompt for AI AgentsSource: Coding guidelines There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current head restores disabled-state coverage with a title-based loop, so that part of the comment is now addressed. The enabled-state and selection-transition assertions are still missing: the test should verify that enabling unhides the CoinJoin rows, visible selections survive either transition, and a selected CoinJoin row falls back only when disabling hides it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== TransactionView structure =='
ast-grep outline src/qt/transactionview.cpp --items all --match 'updateCoinJoinVisibility|chooseType|setModel' --view expanded || true
echo '== Implementation and call sites =='
rg -n -A35 -B12 --glob 'src/qt/transactionview.{cpp,h}' \
'\b(updateCoinJoinVisibility|chooseType|setModel)\s*\(' src/qt
echo '== CoinJoin visibility test coverage =='
rg -n -A30 -B12 --glob 'src/qt/test/*.{cpp,h}' \
'(CoinJoin|coinjoin|transactionTypeFilter|chooseType)\s*\(' src/qt/test
echo '== Current branch and relevant diff =='
git status --short
git diff -- src/qt/transactionview.cpp src/qt/test/providertransactiontests.cppLength of output: 30488
The title-based loop covers the disabled state. The test does not cover the enabled state.
The finding remains open. ✏️ Learnings added
You are interacting with an AI system.
Comment on lines
332
to
+349
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Suggestion: Restore CoinJoin visibility and selection coverage This PR changes source: ['codex', 'coderabbit'] |
||
| QTableView* const table{transaction_view.findChild<QTableView*>("transactionView")}; | ||
| QVERIFY(table != nullptr); | ||
| QCOMPARE(table->model()->rowCount(), static_cast<int>(expected.size())); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -95,13 +95,13 @@ TransactionView::TransactionView(QWidget* parent) : | |
| typeWidget->addItem(tr("%1 Collateral Payment").arg(strCoinJoinName), TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinCollateralPayment)); | ||
| typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf)); | ||
| typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated)); | ||
| typeWidget->addItem(tr("Masternode"), TransactionFilterProxy::TYPE(TransactionRecord::MasternodeRegistration) | | ||
| TransactionFilterProxy::TYPE(TransactionRecord::MasternodeUpdate)); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| typeWidget->addItem(tr("Platform Transfer"), TransactionFilterProxy::TYPE(TransactionRecord::PlatformTransfer)); | ||
| typeWidget->addItem(tr("Data Transaction"), TransactionFilterProxy::TYPE(TransactionRecord::DataTransaction)); | ||
| typeWidget->addItem(tr("Dust Receive"), TransactionFilterProxy::TYPE(TransactionRecord::DustReceive)); | ||
| typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other)); | ||
|
Comment on lines
+98
to
103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Reordering changes persisted transaction filter meanings
source: ['codex'] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved in this update — Reordering changes persisted transaction filter meanings no longer present. Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread. |
||
| typeWidget->addItem(tr("Masternode"), TransactionFilterProxy::TYPE(TransactionRecord::MasternodeRegistration) | | ||
| TransactionFilterProxy::TYPE(TransactionRecord::MasternodeUpdate)); | ||
| typeWidget->setCurrentIndex(settings.value("transactionType").toInt()); | ||
| typeWidget->setCurrentIndex(typeWidget->findData(settings.value("transactionTypeFilter").toUInt())); | ||
|
|
||
| hlayout->addWidget(typeWidget); | ||
|
|
||
|
|
@@ -261,7 +261,6 @@ void TransactionView::setModel(WalletModel *_model) | |
| connect(_model, &WalletModel::notifyWatchonlyChanged, this, &TransactionView::updateWatchOnlyColumn); | ||
|
|
||
| // Update transaction list with persisted settings | ||
| chooseType(settings.value("transactionType").toInt()); | ||
| chooseDate(settings.value("transactionDate").toInt()); | ||
|
|
||
| updateCoinJoinVisibility(); | ||
|
|
@@ -331,7 +330,7 @@ void TransactionView::chooseType(int idx) | |
| typeWidget->itemData(idx).toUInt()); | ||
| // Persist settings | ||
| QSettings settings; | ||
| settings.setValue("transactionType", idx); | ||
| settings.setValue("transactionTypeFilter", typeWidget->itemData(idx).toUInt()); | ||
| } | ||
|
|
||
| void TransactionView::chooseWatchonly(int idx) | ||
|
|
@@ -788,10 +787,6 @@ void TransactionView::updateCoinJoinVisibility() | |
| return; | ||
| } | ||
| bool fEnabled = model->node().coinJoinOptions().isEnabled(); | ||
| // If CoinJoin gets enabled use "All" else "Most common" | ||
| int idx = fEnabled ? 0 : 1; | ||
| chooseType(idx); | ||
| typeWidget->setCurrentIndex(idx); | ||
| // Hide all CoinJoin related filters by value so this stays correct when entries are reordered. | ||
| QListView* typeList = qobject_cast<QListView*>(typeWidget->view()); | ||
| for (const quint32 type_filter : {TransactionFilterProxy::TYPE(TransactionRecord::CoinJoinSend), | ||
|
|
@@ -802,4 +797,11 @@ void TransactionView::updateCoinJoinVisibility() | |
| const int row = typeWidget->findData(type_filter); | ||
| if (row >= 0) typeList->setRowHidden(row, !fEnabled); | ||
| } | ||
|
|
||
| int idx = typeWidget->currentIndex(); | ||
| if (idx < 0 || typeList->isRowHidden(idx)) { | ||
| idx = typeWidget->findData(fEnabled ? TransactionFilterProxy::ALL_TYPES : TransactionFilterProxy::COMMON_TYPES); | ||
| typeWidget->setCurrentIndex(idx); | ||
| } | ||
| chooseType(idx); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟡 Suggestion: Retain provider transaction detail-summary coverage
CheckProviderRecords()now stops after checking the tooltip, removing all coverage ofLongDescriptionRole. The remaining type, amount, and tooltip checks do not exercise the separate transaction-description rendering path atTransactionTableModel::LongDescriptionRole, and the removed assertions guarded the recently added behavior that provider summaries omit misleading From, To, Debit, Credit, output-index, and external-destination details. No other Qt test requestsLongDescriptionRole, so regressions in that user-facing summary would now pass. Restore focused assertions for those behavioral guarantees while avoiding checks for incidental wording or markup where possible.source: ['codex']