From ee014e5b10f5f65820ff056311051ff49813b294 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Fri, 29 Jul 2011 14:36:35 +0200 Subject: [PATCH] Full support for other units, add configuration option for default unit (used when displaying amounts) --- bitcoin-qt.pro | 6 ++++-- src/qt/bitcoin.cpp | 6 ++++-- src/qt/bitcoinamountfield.cpp | 11 ++++++++--- src/qt/bitcoinamountfield.h | 8 +++++--- src/qt/bitcoingui.cpp | 2 +- src/qt/clientmodel.cpp | 6 ++---- src/qt/clientmodel.h | 4 +--- src/qt/optionsdialog.cpp | 14 +++++++++----- src/qt/optionsmodel.cpp | 20 ++++++++++++++++++- src/qt/optionsmodel.h | 4 ++++ src/qt/overviewpage.cpp | 21 +++++++++++++++++--- src/qt/overviewpage.h | 4 ++++ src/qt/qvaluecombobox.cpp | 27 ++++++++++++++++++++++++++ src/qt/qvaluecombobox.h | 33 ++++++++++++++++++++++++++++++++ src/qt/sendcoinsentry.cpp | 5 +++++ src/qt/transactiontablemodel.cpp | 3 ++- src/qt/transactionview.cpp | 3 ++- src/qt/walletmodel.cpp | 5 ++--- src/qt/walletmodel.h | 2 +- 19 files changed, 151 insertions(+), 33 deletions(-) create mode 100644 src/qt/qvaluecombobox.cpp create mode 100644 src/qt/qvaluecombobox.h diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 250aeff92..03cd592a1 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -89,7 +89,8 @@ HEADERS += src/qt/bitcoingui.h \ src/crypter.h \ src/qt/sendcoinsentry.h \ src/qt/qvalidatedlineedit.h \ - src/qt/bitcoinunits.h + src/qt/bitcoinunits.h \ + src/qt/qvaluecombobox.h SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/transactiontablemodel.cpp \ src/qt/addresstablemodel.cpp \ @@ -132,7 +133,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/crypter.cpp \ src/qt/sendcoinsentry.cpp \ src/qt/qvalidatedlineedit.cpp \ - src/qt/bitcoinunits.cpp + src/qt/bitcoinunits.cpp \ + src/qt/qvaluecombobox.cpp RESOURCES += \ src/qt/bitcoin.qrc diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 63d1d7067..bc652d31b 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -4,6 +4,7 @@ #include "bitcoingui.h" #include "clientmodel.h" #include "walletmodel.h" +#include "optionsmodel.h" #include "qtwin.h" #include "headers.h" @@ -118,8 +119,9 @@ int main(int argc, char *argv[]) // Put this in a block, so that BitcoinGUI is cleaned up properly before // calling shutdown. BitcoinGUI window; - ClientModel clientModel(pwalletMain); - WalletModel walletModel(pwalletMain); + OptionsModel optionsModel(pwalletMain); + ClientModel clientModel(&optionsModel); + WalletModel walletModel(pwalletMain, &optionsModel); guiref = &window; window.setClientModel(&clientModel); diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp index f1b4e9fdc..73498050a 100644 --- a/src/qt/bitcoinamountfield.cpp +++ b/src/qt/bitcoinamountfield.cpp @@ -1,5 +1,6 @@ #include "bitcoinamountfield.h" #include "qvalidatedlineedit.h" +#include "qvaluecombobox.h" #include "bitcoinunits.h" #include @@ -8,6 +9,7 @@ #include #include #include +#include BitcoinAmountField::BitcoinAmountField(QWidget *parent): QWidget(parent), amount(0), decimals(0), currentUnit(-1) @@ -27,7 +29,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent): layout->addWidget(amount); layout->addWidget(new QLabel(QString("."))); layout->addWidget(decimals); - unit = new QComboBox(this); + unit = new QValueComboBox(this); unit->setModel(new BitcoinUnits(this)); layout->addWidget(unit); layout->addStretch(1); @@ -78,7 +80,7 @@ bool BitcoinAmountField::validate() decimals->setValid(false); valid = false; } - if(!BitcoinUnits::parse(BitcoinUnits::BTC, text(), 0)) + if(!BitcoinUnits::parse(currentUnit, text(), 0)) { setValid(false); valid = false; @@ -169,6 +171,9 @@ void BitcoinAmountField::unitChanged(int idx) setText(""); } setValid(true); +} - +void BitcoinAmountField::setDisplayUnit(int newUnit) +{ + unit->setValue(newUnit); } diff --git a/src/qt/bitcoinamountfield.h b/src/qt/bitcoinamountfield.h index 6e724d06a..cc92159fe 100644 --- a/src/qt/bitcoinamountfield.h +++ b/src/qt/bitcoinamountfield.h @@ -5,7 +5,7 @@ QT_BEGIN_NAMESPACE class QValidatedLineEdit; -class QComboBox; +class QValueComboBox; QT_END_NAMESPACE // Coin amount entry widget with separate parts for whole @@ -13,7 +13,6 @@ QT_END_NAMESPACE class BitcoinAmountField: public QWidget { Q_OBJECT - //Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true); Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true); public: explicit BitcoinAmountField(QWidget *parent = 0); @@ -25,6 +24,9 @@ public: void setValid(bool valid); bool validate(); + // Change current unit + void setDisplayUnit(int unit); + // Make field empty and ready for new input void clear(); @@ -42,7 +44,7 @@ protected: private: QValidatedLineEdit *amount; QValidatedLineEdit *decimals; - QComboBox *unit; + QValueComboBox *unit; int currentUnit; void setText(const QString &text); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index d1e7bb94f..655ae5ca7 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -463,7 +463,7 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int trayIcon->showMessage((amount)<0 ? tr("Sent transaction") : tr("Incoming transaction"), tr("Date: ") + date + "\n" + - tr("Amount: ") + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, amount, true) + "\n" + + tr("Amount: ") + BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), amount, true) + "\n" + tr("Type: ") + type + "\n" + tr("Address: ") + address + "\n", QSystemTrayIcon::Information); diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index c147aa5a6..5cf02eac7 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -9,8 +9,8 @@ #include #include -ClientModel::ClientModel(CWallet *wallet, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(0), +ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : + QObject(parent), optionsModel(optionsModel), cachedNumConnections(0), cachedNumBlocks(0) { // Until signal notifications is built into the bitcoin core, @@ -18,8 +18,6 @@ ClientModel::ClientModel(CWallet *wallet, QObject *parent) : QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(MODEL_UPDATE_DELAY); - - optionsModel = new OptionsModel(wallet, this); } int ClientModel::getNumConnections() const diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index f7ad14c28..544334e47 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -19,7 +19,7 @@ class ClientModel : public QObject public: // The only reason that this constructor takes a wallet is because // the global client settings are stored in the main wallet. - explicit ClientModel(CWallet *wallet, QObject *parent = 0); + explicit ClientModel(OptionsModel *optionsModel, QObject *parent = 0); OptionsModel *getOptionsModel(); @@ -38,8 +38,6 @@ public: QString formatFullVersion() const; private: - CWallet *wallet; - OptionsModel *optionsModel; int cachedNumConnections; diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 94f7abacf..a923f3ead 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -3,6 +3,8 @@ #include "bitcoinamountfield.h" #include "monitoreddatamapper.h" #include "guiutil.h" +#include "bitcoinunits.h" +#include "qvaluecombobox.h" #include #include @@ -49,7 +51,7 @@ public: void setMapper(MonitoredDataMapper *mapper); private: - QLineEdit *unit; + QValueComboBox *unit; signals: public slots: @@ -72,7 +74,7 @@ OptionsDialog::OptionsDialog(QWidget *parent): pages_widget->addWidget(main_page); QListWidgetItem *item_display = new QListWidgetItem(tr("Display")); - //contents_widget->addItem(item_display); + contents_widget->addItem(item_display); display_page = new DisplayOptionsPage(this); pages_widget->addWidget(display_page); @@ -122,7 +124,6 @@ void OptionsDialog::setModel(OptionsModel *model) void OptionsDialog::changePage(int index) { - qDebug() << "page" << index; pages_widget->setCurrentIndex(index); } @@ -249,9 +250,11 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent): QVBoxLayout *layout = new QVBoxLayout(); QHBoxLayout *unit_hbox = new QHBoxLayout(); unit_hbox->addSpacing(18); - QLabel *unit_label = new QLabel(tr("&Unit: ")); + QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: ")); unit_hbox->addWidget(unit_label); - unit = new QLineEdit(); + unit = new QValueComboBox(this); + unit->setModel(new BitcoinUnits(this)); + unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins")); unit_label->setBuddy(unit); unit_hbox->addWidget(unit); @@ -264,4 +267,5 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent): void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper) { + mapper->addMapping(unit, OptionsModel::DisplayUnit); } diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 896170975..d72a0e9e9 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -1,4 +1,5 @@ #include "optionsmodel.h" +#include "bitcoinunits.h" #include "headers.h" @@ -6,8 +7,12 @@ OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) : QAbstractListModel(parent), - wallet(wallet) + wallet(wallet), + nDisplayUnit(BitcoinUnits::BTC) { + // Read our specific settings from the wallet db + CWalletDB walletdb(wallet->strWalletFile); + walletdb.ReadSetting("nDisplayUnit", nDisplayUnit); } int OptionsModel::rowCount(const QModelIndex & parent) const @@ -37,6 +42,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const return QVariant(QString::fromStdString(addrProxy.ToStringPort())); case Fee: return QVariant(nTransactionFee); + case DisplayUnit: + return QVariant(nDisplayUnit); default: return QVariant(); } @@ -108,6 +115,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in walletdb.WriteSetting("nTransactionFee", nTransactionFee); } break; + case DisplayUnit: { + int unit = value.toInt(); + nDisplayUnit = unit; + walletdb.WriteSetting("nDisplayUnit", nDisplayUnit); + emit displayUnitChanged(unit); + } default: break; } @@ -131,3 +144,8 @@ bool OptionsModel::getMinimizeOnClose() { return fMinimizeOnClose; } + +int OptionsModel::getDisplayUnit() +{ + return nDisplayUnit; +} diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 4ba44dc23..ed26f83d5 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -26,6 +26,7 @@ public: ProxyIP, // QString ProxyPort, // QString Fee, // qint64 + DisplayUnit, // BitcoinUnits::Unit OptionIDRowCount }; @@ -37,10 +38,13 @@ public: qint64 getTransactionFee(); bool getMinimizeToTray(); bool getMinimizeOnClose(); + int getDisplayUnit(); private: // Wallet stores persistent options CWallet *wallet; + int nDisplayUnit; signals: + void displayUnitChanged(int unit); public slots: diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 9515117c2..c04bbf600 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -3,10 +3,15 @@ #include "walletmodel.h" #include "bitcoinunits.h" +#include "optionsmodel.h" + +#include OverviewPage::OverviewPage(QWidget *parent) : QWidget(parent), - ui(new Ui::OverviewPage) + ui(new Ui::OverviewPage), + currentBalance(-1), + currentUnconfirmedBalance(-1) { ui->setupUi(this); @@ -34,8 +39,11 @@ OverviewPage::~OverviewPage() void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance) { - ui->labelBalance->setText(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, balance)); - ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, unconfirmedBalance)); + int unit = model->getOptionsModel()->getDisplayUnit(); + currentBalance = balance; + currentUnconfirmedBalance = unconfirmedBalance; + ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); + ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); } void OverviewPage::setNumTransactions(int count) @@ -54,4 +62,11 @@ void OverviewPage::setModel(WalletModel *model) setNumTransactions(model->getNumTransactions()); connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int))); + connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(displayUnitChanged())); +} + +void OverviewPage::displayUnitChanged() +{ + if(currentBalance != -1) + setBalance(currentBalance, currentUnconfirmedBalance); } diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index acf83c720..c54dda323 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -25,7 +25,11 @@ public slots: private: Ui::OverviewPage *ui; WalletModel *model; + qint64 currentBalance; + qint64 currentUnconfirmedBalance; +private slots: + void displayUnitChanged(); }; #endif // OVERVIEWPAGE_H diff --git a/src/qt/qvaluecombobox.cpp b/src/qt/qvaluecombobox.cpp new file mode 100644 index 000000000..c0ad8c12e --- /dev/null +++ b/src/qt/qvaluecombobox.cpp @@ -0,0 +1,27 @@ +#include "qvaluecombobox.h" + +QValueComboBox::QValueComboBox(QWidget *parent) : + QComboBox(parent), role(Qt::UserRole) +{ + connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(handleSelectionChanged(int))); +} + +int QValueComboBox::value() const +{ + return itemData(currentIndex(), role).toInt(); +} + +void QValueComboBox::setValue(int value) +{ + setCurrentIndex(findData(value, role)); +} + +void QValueComboBox::setRole(int role) +{ + this->role = role; +} + +void QValueComboBox::handleSelectionChanged(int idx) +{ + emit valueChanged(); +} diff --git a/src/qt/qvaluecombobox.h b/src/qt/qvaluecombobox.h new file mode 100644 index 000000000..2a3533da9 --- /dev/null +++ b/src/qt/qvaluecombobox.h @@ -0,0 +1,33 @@ +#ifndef QVALUECOMBOBOX_H +#define QVALUECOMBOBOX_H + +#include + +// QComboBox that can be used with QDataWidgetMapper to select +// ordinal values from a model. +class QValueComboBox : public QComboBox +{ + Q_OBJECT + Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged USER true); +public: + explicit QValueComboBox(QWidget *parent = 0); + + int value() const; + void setValue(int value); + + // Model role to use as value + void setRole(int role); + +signals: + void valueChanged(); + +public slots: + +private: + int role; + +private slots: + void handleSelectionChanged(int idx); +}; + +#endif // QVALUECOMBOBOX_H diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index f3847f169..abdbc81bd 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -4,6 +4,7 @@ #include "bitcoinunits.h" #include "addressbookpage.h" #include "walletmodel.h" +#include "optionsmodel.h" #include "addresstablemodel.h" #include "qapplication.h" @@ -71,6 +72,10 @@ void SendCoinsEntry::clear() ui->addAsLabel->clear(); ui->payAmount->clear(); ui->payTo->setFocus(); + if(model) + { + ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); + } } void SendCoinsEntry::on_deleteButton_clicked() diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 2b8fe0b47..99f2d5806 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -4,6 +4,7 @@ #include "guiconstants.h" #include "transactiondesc.h" #include "walletmodel.h" +#include "optionsmodel.h" #include "addresstablemodel.h" #include "bitcoinunits.h" @@ -398,7 +399,7 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx) QVariant TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const { - QString str = BitcoinUnits::format(BitcoinUnits::BTC, wtx->credit + wtx->debit); + QString str = BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), wtx->credit + wtx->debit); if(showUnconfirmed) { if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature) diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 9c38934ad..12fdc947d 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -9,6 +9,7 @@ #include "csvmodelwriter.h" #include "transactiondescdialog.h" #include "editaddressdialog.h" +#include "optionsmodel.h" #include #include @@ -227,7 +228,7 @@ void TransactionView::changedPrefix(const QString &prefix) void TransactionView::changedAmount(const QString &amount) { qint64 amount_parsed = 0; - if(BitcoinUnits::parse(BitcoinUnits::BTC, amount, &amount_parsed)) + if(BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amount, &amount_parsed)) { transactionProxyModel->setMinAmount(amount_parsed); } diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 732472c1a..4d8d6fe45 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -9,8 +9,8 @@ #include #include -WalletModel::WalletModel(CWallet *wallet, QObject *parent) : - QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0), +WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) : + QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0), transactionTableModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0) { @@ -20,7 +20,6 @@ WalletModel::WalletModel(CWallet *wallet, QObject *parent) : connect(timer, SIGNAL(timeout()), this, SLOT(update())); timer->start(MODEL_UPDATE_DELAY); - optionsModel = new OptionsModel(wallet, this); addressTableModel = new AddressTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this); } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index 668d44632..c989e7fbb 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -20,7 +20,7 @@ class WalletModel : public QObject { Q_OBJECT public: - explicit WalletModel(CWallet *wallet, QObject *parent = 0); + explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0); enum StatusCode {