Skip to content

Commit ff4dc20

Browse files
promagfanquake
authored andcommitted
gui: Fix manual coin control with multiple wallets loaded
Github-Pull: #18894 Rebased-From: a8b5f1b
1 parent ed0afe8 commit ff4dc20

File tree

4 files changed

+45
-67
lines changed

4 files changed

+45
-67
lines changed

src/qt/coincontroldialog.cpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ bool CCoinControlWidgetItem::operator<(const QTreeWidgetItem &other) const {
4141
return QTreeWidgetItem::operator<(other);
4242
}
4343

44-
CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidget *parent) :
44+
CoinControlDialog::CoinControlDialog(CCoinControl& coin_control, WalletModel* _model, const PlatformStyle *_platformStyle, QWidget *parent) :
4545
QDialog(parent),
4646
ui(new Ui::CoinControlDialog),
47-
model(nullptr),
47+
m_coin_control(coin_control),
48+
model(_model),
4849
platformStyle(_platformStyle)
4950
{
5051
ui->setupUi(this);
@@ -134,6 +135,13 @@ CoinControlDialog::CoinControlDialog(const PlatformStyle *_platformStyle, QWidge
134135
ui->radioTreeMode->click();
135136
if (settings.contains("nCoinControlSortColumn") && settings.contains("nCoinControlSortOrder"))
136137
sortView(settings.value("nCoinControlSortColumn").toInt(), (static_cast<Qt::SortOrder>(settings.value("nCoinControlSortOrder").toInt())));
138+
139+
if(_model->getOptionsModel() && _model->getAddressTableModel())
140+
{
141+
updateView();
142+
updateLabelLocked();
143+
CoinControlDialog::updateLabels(m_coin_control, _model, this);
144+
}
137145
}
138146

139147
CoinControlDialog::~CoinControlDialog()
@@ -146,18 +154,6 @@ CoinControlDialog::~CoinControlDialog()
146154
delete ui;
147155
}
148156

149-
void CoinControlDialog::setModel(WalletModel *_model)
150-
{
151-
this->model = _model;
152-
153-
if(_model && _model->getOptionsModel() && _model->getAddressTableModel())
154-
{
155-
updateView();
156-
updateLabelLocked();
157-
CoinControlDialog::updateLabels(_model, this);
158-
}
159-
}
160-
161157
// ok button
162158
void CoinControlDialog::buttonBoxClicked(QAbstractButton* button)
163159
{
@@ -183,8 +179,8 @@ void CoinControlDialog::buttonSelectAllClicked()
183179
ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, state);
184180
ui->treeWidget->setEnabled(true);
185181
if (state == Qt::Unchecked)
186-
coinControl()->UnSelectAll(); // just to be sure
187-
CoinControlDialog::updateLabels(model, this);
182+
m_coin_control.UnSelectAll(); // just to be sure
183+
CoinControlDialog::updateLabels(m_coin_control, model, this);
188184
}
189185

190186
// context menu
@@ -369,15 +365,15 @@ void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column)
369365
COutPoint outpt(uint256S(item->data(COLUMN_ADDRESS, TxHashRole).toString().toStdString()), item->data(COLUMN_ADDRESS, VOutRole).toUInt());
370366

371367
if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked)
372-
coinControl()->UnSelect(outpt);
368+
m_coin_control.UnSelect(outpt);
373369
else if (item->isDisabled()) // locked (this happens if "check all" through parent node)
374370
item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked);
375371
else
376-
coinControl()->Select(outpt);
372+
m_coin_control.Select(outpt);
377373

378374
// selection changed -> update labels
379375
if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all
380-
CoinControlDialog::updateLabels(model, this);
376+
CoinControlDialog::updateLabels(m_coin_control, model, this);
381377
}
382378

383379
// TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used.
@@ -402,7 +398,7 @@ void CoinControlDialog::updateLabelLocked()
402398
else ui->labelLocked->setVisible(false);
403399
}
404400

405-
void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
401+
void CoinControlDialog::updateLabels(CCoinControl& m_coin_control, WalletModel *model, QDialog* dialog)
406402
{
407403
if (!model)
408404
return;
@@ -434,7 +430,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
434430
bool fWitness = false;
435431

436432
std::vector<COutPoint> vCoinControl;
437-
coinControl()->ListSelected(vCoinControl);
433+
m_coin_control.ListSelected(vCoinControl);
438434

439435
size_t i = 0;
440436
for (const auto& out : model->wallet().getCoins(vCoinControl)) {
@@ -445,7 +441,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
445441
const COutPoint& outpt = vCoinControl[i++];
446442
if (out.is_spent)
447443
{
448-
coinControl()->UnSelect(outpt);
444+
m_coin_control.UnSelect(outpt);
449445
continue;
450446
}
451447

@@ -498,7 +494,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
498494
nBytes -= 34;
499495

500496
// Fee
501-
nPayFee = model->wallet().getMinimumFee(nBytes, *coinControl(), nullptr /* returned_target */, nullptr /* reason */);
497+
nPayFee = model->wallet().getMinimumFee(nBytes, m_coin_control, nullptr /* returned_target */, nullptr /* reason */);
502498

503499
if (nPayAmount > 0)
504500
{
@@ -590,12 +586,6 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
590586
label->setVisible(nChange < 0);
591587
}
592588

593-
CCoinControl* CoinControlDialog::coinControl()
594-
{
595-
static CCoinControl coin_control;
596-
return &coin_control;
597-
}
598-
599589
void CoinControlDialog::updateView()
600590
{
601591
if (!model || !model->getOptionsModel() || !model->getAddressTableModel())
@@ -695,13 +685,13 @@ void CoinControlDialog::updateView()
695685
// disable locked coins
696686
if (model->wallet().isLockedCoin(output))
697687
{
698-
coinControl()->UnSelect(output); // just to be sure
688+
m_coin_control.UnSelect(output); // just to be sure
699689
itemOutput->setDisabled(true);
700690
itemOutput->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed"));
701691
}
702692

703693
// set checkbox
704-
if (coinControl()->IsSelected(output))
694+
if (m_coin_control.IsSelected(output))
705695
itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked);
706696
}
707697

src/qt/coincontroldialog.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,18 @@ class CoinControlDialog : public QDialog
4242
Q_OBJECT
4343

4444
public:
45-
explicit CoinControlDialog(const PlatformStyle *platformStyle, QWidget *parent = nullptr);
45+
explicit CoinControlDialog(CCoinControl& coin_control, WalletModel* model, const PlatformStyle *platformStyle, QWidget *parent = nullptr);
4646
~CoinControlDialog();
4747

48-
void setModel(WalletModel *model);
49-
5048
// static because also called from sendcoinsdialog
51-
static void updateLabels(WalletModel*, QDialog*);
49+
static void updateLabels(CCoinControl& m_coin_control, WalletModel*, QDialog*);
5250

5351
static QList<CAmount> payAmounts;
54-
static CCoinControl *coinControl();
5552
static bool fSubtractFeeFromAmount;
5653

5754
private:
5855
Ui::CoinControlDialog *ui;
56+
CCoinControl& m_coin_control;
5957
WalletModel *model;
6058
int sortColumn;
6159
Qt::SortOrder sortOrder;

src/qt/sendcoinsdialog.cpp

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p
5757
ui(new Ui::SendCoinsDialog),
5858
clientModel(nullptr),
5959
model(nullptr),
60+
m_coin_control(new CCoinControl),
6061
fNewRecipientAllowed(true),
6162
fFeeMinimized(true),
6263
platformStyle(_platformStyle)
@@ -262,14 +263,9 @@ void SendCoinsDialog::on_sendButton_clicked()
262263
WalletModelTransaction currentTransaction(recipients);
263264
WalletModel::SendCoinsReturn prepareStatus;
264265

265-
// Always use a CCoinControl instance, use the CoinControlDialog instance if CoinControl has been enabled
266-
CCoinControl ctrl;
267-
if (model->getOptionsModel()->getCoinControlFeatures())
268-
ctrl = *CoinControlDialog::coinControl();
266+
updateCoinControlState(*m_coin_control);
269267

270-
updateCoinControlState(ctrl);
271-
272-
prepareStatus = model->prepareTransaction(currentTransaction, ctrl);
268+
prepareStatus = model->prepareTransaction(currentTransaction, *m_coin_control);
273269

274270
// process prepareStatus and on error generate message shown to user
275271
processSendCoinsReturn(prepareStatus,
@@ -413,7 +409,7 @@ void SendCoinsDialog::on_sendButton_clicked()
413409
}
414410
if (!send_failure) {
415411
accept();
416-
CoinControlDialog::coinControl()->UnSelectAll();
412+
m_coin_control->UnSelectAll();
417413
coinControlUpdateLabels();
418414
}
419415
fNewRecipientAllowed = true;
@@ -422,7 +418,7 @@ void SendCoinsDialog::on_sendButton_clicked()
422418
void SendCoinsDialog::clear()
423419
{
424420
// Clear coin control settings
425-
CoinControlDialog::coinControl()->UnSelectAll();
421+
m_coin_control->UnSelectAll();
426422
ui->checkBoxCoinControlChange->setChecked(false);
427423
ui->lineEditCoinControlChange->clear();
428424
coinControlUpdateLabels();
@@ -645,17 +641,11 @@ void SendCoinsDialog::on_buttonMinimizeFee_clicked()
645641

646642
void SendCoinsDialog::useAvailableBalance(SendCoinsEntry* entry)
647643
{
648-
// Get CCoinControl instance if CoinControl is enabled or create a new one.
649-
CCoinControl coin_control;
650-
if (model->getOptionsModel()->getCoinControlFeatures()) {
651-
coin_control = *CoinControlDialog::coinControl();
652-
}
653-
654644
// Include watch-only for wallets without private key
655-
coin_control.fAllowWatchOnly = model->wallet().privateKeysDisabled();
645+
m_coin_control->fAllowWatchOnly = model->wallet().privateKeysDisabled();
656646

657647
// Calculate available amount to send.
658-
CAmount amount = model->wallet().getAvailableBalance(coin_control);
648+
CAmount amount = model->wallet().getAvailableBalance(*m_coin_control);
659649
for (int i = 0; i < ui->entries->count(); ++i) {
660650
SendCoinsEntry* e = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
661651
if (e && !e->isHidden() && e != entry) {
@@ -714,12 +704,11 @@ void SendCoinsDialog::updateSmartFeeLabel()
714704
{
715705
if(!model || !model->getOptionsModel())
716706
return;
717-
CCoinControl coin_control;
718-
updateCoinControlState(coin_control);
719-
coin_control.m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels
707+
updateCoinControlState(*m_coin_control);
708+
m_coin_control->m_feerate.reset(); // Explicitly use only fee estimation rate for smart fee labels
720709
int returned_target;
721710
FeeReason reason;
722-
CFeeRate feeRate = CFeeRate(model->wallet().getMinimumFee(1000, coin_control, &returned_target, &reason));
711+
CFeeRate feeRate = CFeeRate(model->wallet().getMinimumFee(1000, *m_coin_control, &returned_target, &reason));
723712

724713
ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), feeRate.GetFeePerK()) + "/kB");
725714

@@ -790,16 +779,15 @@ void SendCoinsDialog::coinControlFeatureChanged(bool checked)
790779
ui->frameCoinControl->setVisible(checked);
791780

792781
if (!checked && model) // coin control features disabled
793-
CoinControlDialog::coinControl()->SetNull();
782+
m_coin_control->SetNull();
794783

795784
coinControlUpdateLabels();
796785
}
797786

798787
// Coin Control: button inputs -> show actual coin control dialog
799788
void SendCoinsDialog::coinControlButtonClicked()
800789
{
801-
CoinControlDialog dlg(platformStyle);
802-
dlg.setModel(model);
790+
CoinControlDialog dlg(*m_coin_control, model, platformStyle);
803791
dlg.exec();
804792
coinControlUpdateLabels();
805793
}
@@ -809,7 +797,7 @@ void SendCoinsDialog::coinControlChangeChecked(int state)
809797
{
810798
if (state == Qt::Unchecked)
811799
{
812-
CoinControlDialog::coinControl()->destChange = CNoDestination();
800+
m_coin_control->destChange = CNoDestination();
813801
ui->labelCoinControlChangeLabel->clear();
814802
}
815803
else
@@ -825,7 +813,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
825813
if (model && model->getAddressTableModel())
826814
{
827815
// Default to no change address until verified
828-
CoinControlDialog::coinControl()->destChange = CNoDestination();
816+
m_coin_control->destChange = CNoDestination();
829817
ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
830818

831819
const CTxDestination dest = DecodeDestination(text.toStdString());
@@ -848,7 +836,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
848836
QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
849837

850838
if(btnRetVal == QMessageBox::Yes)
851-
CoinControlDialog::coinControl()->destChange = dest;
839+
m_coin_control->destChange = dest;
852840
else
853841
{
854842
ui->lineEditCoinControlChange->setText("");
@@ -867,7 +855,7 @@ void SendCoinsDialog::coinControlChangeEdited(const QString& text)
867855
else
868856
ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
869857

870-
CoinControlDialog::coinControl()->destChange = dest;
858+
m_coin_control->destChange = dest;
871859
}
872860
}
873861
}
@@ -879,7 +867,7 @@ void SendCoinsDialog::coinControlUpdateLabels()
879867
if (!model || !model->getOptionsModel())
880868
return;
881869

882-
updateCoinControlState(*CoinControlDialog::coinControl());
870+
updateCoinControlState(*m_coin_control);
883871

884872
// set pay amounts
885873
CoinControlDialog::payAmounts.clear();
@@ -897,10 +885,10 @@ void SendCoinsDialog::coinControlUpdateLabels()
897885
}
898886
}
899887

900-
if (CoinControlDialog::coinControl()->HasSelected())
888+
if (m_coin_control->HasSelected())
901889
{
902890
// actual coin control calculation
903-
CoinControlDialog::updateLabels(model, this);
891+
CoinControlDialog::updateLabels(*m_coin_control, model, this);
904892

905893
// show coin control stats
906894
ui->labelCoinControlAutomaticallySelected->hide();

src/qt/sendcoinsdialog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <QString>
1313
#include <QTimer>
1414

15+
class CCoinControl;
1516
class ClientModel;
1617
class PlatformStyle;
1718
class SendCoinsEntry;
@@ -60,6 +61,7 @@ public Q_SLOTS:
6061
Ui::SendCoinsDialog *ui;
6162
ClientModel *clientModel;
6263
WalletModel *model;
64+
std::unique_ptr<CCoinControl> m_coin_control;
6365
bool fNewRecipientAllowed;
6466
bool fFeeMinimized;
6567
const PlatformStyle *platformStyle;

0 commit comments

Comments
 (0)