Full support for other units, add configuration option for default unit (used when displaying amounts)

This commit is contained in:
Wladimir J. van der Laan 2011-07-29 14:36:35 +02:00
parent b5b1d1a66b
commit ee014e5b10
19 changed files with 152 additions and 34 deletions

View file

@ -89,7 +89,8 @@ HEADERS += src/qt/bitcoingui.h \
src/crypter.h \ src/crypter.h \
src/qt/sendcoinsentry.h \ src/qt/sendcoinsentry.h \
src/qt/qvalidatedlineedit.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 \ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/qt/transactiontablemodel.cpp \ src/qt/transactiontablemodel.cpp \
src/qt/addresstablemodel.cpp \ src/qt/addresstablemodel.cpp \
@ -132,7 +133,8 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
src/crypter.cpp \ src/crypter.cpp \
src/qt/sendcoinsentry.cpp \ src/qt/sendcoinsentry.cpp \
src/qt/qvalidatedlineedit.cpp \ src/qt/qvalidatedlineedit.cpp \
src/qt/bitcoinunits.cpp src/qt/bitcoinunits.cpp \
src/qt/qvaluecombobox.cpp
RESOURCES += \ RESOURCES += \
src/qt/bitcoin.qrc src/qt/bitcoin.qrc

View file

@ -4,6 +4,7 @@
#include "bitcoingui.h" #include "bitcoingui.h"
#include "clientmodel.h" #include "clientmodel.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "optionsmodel.h"
#include "qtwin.h" #include "qtwin.h"
#include "headers.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 // Put this in a block, so that BitcoinGUI is cleaned up properly before
// calling shutdown. // calling shutdown.
BitcoinGUI window; BitcoinGUI window;
ClientModel clientModel(pwalletMain); OptionsModel optionsModel(pwalletMain);
WalletModel walletModel(pwalletMain); ClientModel clientModel(&optionsModel);
WalletModel walletModel(pwalletMain, &optionsModel);
guiref = &window; guiref = &window;
window.setClientModel(&clientModel); window.setClientModel(&clientModel);

View file

@ -1,5 +1,6 @@
#include "bitcoinamountfield.h" #include "bitcoinamountfield.h"
#include "qvalidatedlineedit.h" #include "qvalidatedlineedit.h"
#include "qvaluecombobox.h"
#include "bitcoinunits.h" #include "bitcoinunits.h"
#include <QLabel> #include <QLabel>
@ -8,6 +9,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QKeyEvent> #include <QKeyEvent>
#include <QComboBox> #include <QComboBox>
#include <QDebug>
BitcoinAmountField::BitcoinAmountField(QWidget *parent): BitcoinAmountField::BitcoinAmountField(QWidget *parent):
QWidget(parent), amount(0), decimals(0), currentUnit(-1) QWidget(parent), amount(0), decimals(0), currentUnit(-1)
@ -27,7 +29,7 @@ BitcoinAmountField::BitcoinAmountField(QWidget *parent):
layout->addWidget(amount); layout->addWidget(amount);
layout->addWidget(new QLabel(QString("."))); layout->addWidget(new QLabel(QString(".")));
layout->addWidget(decimals); layout->addWidget(decimals);
unit = new QComboBox(this); unit = new QValueComboBox(this);
unit->setModel(new BitcoinUnits(this)); unit->setModel(new BitcoinUnits(this));
layout->addWidget(unit); layout->addWidget(unit);
layout->addStretch(1); layout->addStretch(1);
@ -78,7 +80,7 @@ bool BitcoinAmountField::validate()
decimals->setValid(false); decimals->setValid(false);
valid = false; valid = false;
} }
if(!BitcoinUnits::parse(BitcoinUnits::BTC, text(), 0)) if(!BitcoinUnits::parse(currentUnit, text(), 0))
{ {
setValid(false); setValid(false);
valid = false; valid = false;
@ -169,6 +171,9 @@ void BitcoinAmountField::unitChanged(int idx)
setText(""); setText("");
} }
setValid(true); setValid(true);
}
void BitcoinAmountField::setDisplayUnit(int newUnit)
{
unit->setValue(newUnit);
} }

View file

@ -5,7 +5,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QValidatedLineEdit; class QValidatedLineEdit;
class QComboBox; class QValueComboBox;
QT_END_NAMESPACE QT_END_NAMESPACE
// Coin amount entry widget with separate parts for whole // Coin amount entry widget with separate parts for whole
@ -13,7 +13,6 @@ QT_END_NAMESPACE
class BitcoinAmountField: public QWidget class BitcoinAmountField: public QWidget
{ {
Q_OBJECT 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); Q_PROPERTY(qint64 value READ value WRITE setValue NOTIFY textChanged USER true);
public: public:
explicit BitcoinAmountField(QWidget *parent = 0); explicit BitcoinAmountField(QWidget *parent = 0);
@ -25,6 +24,9 @@ public:
void setValid(bool valid); void setValid(bool valid);
bool validate(); bool validate();
// Change current unit
void setDisplayUnit(int unit);
// Make field empty and ready for new input // Make field empty and ready for new input
void clear(); void clear();
@ -42,7 +44,7 @@ protected:
private: private:
QValidatedLineEdit *amount; QValidatedLineEdit *amount;
QValidatedLineEdit *decimals; QValidatedLineEdit *decimals;
QComboBox *unit; QValueComboBox *unit;
int currentUnit; int currentUnit;
void setText(const QString &text); void setText(const QString &text);

View file

@ -463,7 +463,7 @@ void BitcoinGUI::incomingTransaction(const QModelIndex & parent, int start, int
trayIcon->showMessage((amount)<0 ? tr("Sent transaction") : trayIcon->showMessage((amount)<0 ? tr("Sent transaction") :
tr("Incoming transaction"), tr("Incoming transaction"),
tr("Date: ") + date + "\n" + 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("Type: ") + type + "\n" +
tr("Address: ") + address + "\n", tr("Address: ") + address + "\n",
QSystemTrayIcon::Information); QSystemTrayIcon::Information);

View file

@ -9,8 +9,8 @@
#include <QTimer> #include <QTimer>
#include <QDateTime> #include <QDateTime>
ClientModel::ClientModel(CWallet *wallet, QObject *parent) : ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(0), QObject(parent), optionsModel(optionsModel),
cachedNumConnections(0), cachedNumBlocks(0) cachedNumConnections(0), cachedNumBlocks(0)
{ {
// Until signal notifications is built into the bitcoin core, // Until signal notifications is built into the bitcoin core,
@ -18,8 +18,6 @@ ClientModel::ClientModel(CWallet *wallet, QObject *parent) :
QTimer *timer = new QTimer(this); QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update())); connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(MODEL_UPDATE_DELAY); timer->start(MODEL_UPDATE_DELAY);
optionsModel = new OptionsModel(wallet, this);
} }
int ClientModel::getNumConnections() const int ClientModel::getNumConnections() const

View file

@ -19,7 +19,7 @@ class ClientModel : public QObject
public: public:
// The only reason that this constructor takes a wallet is because // The only reason that this constructor takes a wallet is because
// the global client settings are stored in the main wallet. // 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(); OptionsModel *getOptionsModel();
@ -38,8 +38,6 @@ public:
QString formatFullVersion() const; QString formatFullVersion() const;
private: private:
CWallet *wallet;
OptionsModel *optionsModel; OptionsModel *optionsModel;
int cachedNumConnections; int cachedNumConnections;

View file

@ -3,6 +3,8 @@
#include "bitcoinamountfield.h" #include "bitcoinamountfield.h"
#include "monitoreddatamapper.h" #include "monitoreddatamapper.h"
#include "guiutil.h" #include "guiutil.h"
#include "bitcoinunits.h"
#include "qvaluecombobox.h"
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QVBoxLayout> #include <QVBoxLayout>
@ -49,7 +51,7 @@ public:
void setMapper(MonitoredDataMapper *mapper); void setMapper(MonitoredDataMapper *mapper);
private: private:
QLineEdit *unit; QValueComboBox *unit;
signals: signals:
public slots: public slots:
@ -72,7 +74,7 @@ OptionsDialog::OptionsDialog(QWidget *parent):
pages_widget->addWidget(main_page); pages_widget->addWidget(main_page);
QListWidgetItem *item_display = new QListWidgetItem(tr("Display")); QListWidgetItem *item_display = new QListWidgetItem(tr("Display"));
//contents_widget->addItem(item_display); contents_widget->addItem(item_display);
display_page = new DisplayOptionsPage(this); display_page = new DisplayOptionsPage(this);
pages_widget->addWidget(display_page); pages_widget->addWidget(display_page);
@ -122,7 +124,6 @@ void OptionsDialog::setModel(OptionsModel *model)
void OptionsDialog::changePage(int index) void OptionsDialog::changePage(int index)
{ {
qDebug() << "page" << index;
pages_widget->setCurrentIndex(index); pages_widget->setCurrentIndex(index);
} }
@ -249,9 +250,11 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
QVBoxLayout *layout = new QVBoxLayout(); QVBoxLayout *layout = new QVBoxLayout();
QHBoxLayout *unit_hbox = new QHBoxLayout(); QHBoxLayout *unit_hbox = new QHBoxLayout();
unit_hbox->addSpacing(18); 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_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_label->setBuddy(unit);
unit_hbox->addWidget(unit); unit_hbox->addWidget(unit);
@ -264,4 +267,5 @@ DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper) void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
{ {
mapper->addMapping(unit, OptionsModel::DisplayUnit);
} }

View file

@ -1,4 +1,5 @@
#include "optionsmodel.h" #include "optionsmodel.h"
#include "bitcoinunits.h"
#include "headers.h" #include "headers.h"
@ -6,8 +7,12 @@
OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) : OptionsModel::OptionsModel(CWallet *wallet, QObject *parent) :
QAbstractListModel(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 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())); return QVariant(QString::fromStdString(addrProxy.ToStringPort()));
case Fee: case Fee:
return QVariant(nTransactionFee); return QVariant(nTransactionFee);
case DisplayUnit:
return QVariant(nDisplayUnit);
default: default:
return QVariant(); return QVariant();
} }
@ -108,6 +115,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
walletdb.WriteSetting("nTransactionFee", nTransactionFee); walletdb.WriteSetting("nTransactionFee", nTransactionFee);
} }
break; break;
case DisplayUnit: {
int unit = value.toInt();
nDisplayUnit = unit;
walletdb.WriteSetting("nDisplayUnit", nDisplayUnit);
emit displayUnitChanged(unit);
}
default: default:
break; break;
} }
@ -131,3 +144,8 @@ bool OptionsModel::getMinimizeOnClose()
{ {
return fMinimizeOnClose; return fMinimizeOnClose;
} }
int OptionsModel::getDisplayUnit()
{
return nDisplayUnit;
}

View file

@ -26,6 +26,7 @@ public:
ProxyIP, // QString ProxyIP, // QString
ProxyPort, // QString ProxyPort, // QString
Fee, // qint64 Fee, // qint64
DisplayUnit, // BitcoinUnits::Unit
OptionIDRowCount OptionIDRowCount
}; };
@ -37,10 +38,13 @@ public:
qint64 getTransactionFee(); qint64 getTransactionFee();
bool getMinimizeToTray(); bool getMinimizeToTray();
bool getMinimizeOnClose(); bool getMinimizeOnClose();
int getDisplayUnit();
private: private:
// Wallet stores persistent options // Wallet stores persistent options
CWallet *wallet; CWallet *wallet;
int nDisplayUnit;
signals: signals:
void displayUnitChanged(int unit);
public slots: public slots:

View file

@ -3,10 +3,15 @@
#include "walletmodel.h" #include "walletmodel.h"
#include "bitcoinunits.h" #include "bitcoinunits.h"
#include "optionsmodel.h"
#include <QDebug>
OverviewPage::OverviewPage(QWidget *parent) : OverviewPage::OverviewPage(QWidget *parent) :
QWidget(parent), QWidget(parent),
ui(new Ui::OverviewPage) ui(new Ui::OverviewPage),
currentBalance(-1),
currentUnconfirmedBalance(-1)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -34,8 +39,11 @@ OverviewPage::~OverviewPage()
void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance) void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance)
{ {
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, balance)); int unit = model->getOptionsModel()->getDisplayUnit();
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(BitcoinUnits::BTC, unconfirmedBalance)); currentBalance = balance;
currentUnconfirmedBalance = unconfirmedBalance;
ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance));
ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance));
} }
void OverviewPage::setNumTransactions(int count) void OverviewPage::setNumTransactions(int count)
@ -54,4 +62,11 @@ void OverviewPage::setModel(WalletModel *model)
setNumTransactions(model->getNumTransactions()); setNumTransactions(model->getNumTransactions());
connect(model, SIGNAL(numTransactionsChanged(int)), this, SLOT(setNumTransactions(int))); 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);
} }

View file

@ -25,7 +25,11 @@ public slots:
private: private:
Ui::OverviewPage *ui; Ui::OverviewPage *ui;
WalletModel *model; WalletModel *model;
qint64 currentBalance;
qint64 currentUnconfirmedBalance;
private slots:
void displayUnitChanged();
}; };
#endif // OVERVIEWPAGE_H #endif // OVERVIEWPAGE_H

27
src/qt/qvaluecombobox.cpp Normal file
View file

@ -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();
}

33
src/qt/qvaluecombobox.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef QVALUECOMBOBOX_H
#define QVALUECOMBOBOX_H
#include <QComboBox>
// 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

View file

@ -4,6 +4,7 @@
#include "bitcoinunits.h" #include "bitcoinunits.h"
#include "addressbookpage.h" #include "addressbookpage.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "qapplication.h" #include "qapplication.h"
@ -71,6 +72,10 @@ void SendCoinsEntry::clear()
ui->addAsLabel->clear(); ui->addAsLabel->clear();
ui->payAmount->clear(); ui->payAmount->clear();
ui->payTo->setFocus(); ui->payTo->setFocus();
if(model)
{
ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
}
} }
void SendCoinsEntry::on_deleteButton_clicked() void SendCoinsEntry::on_deleteButton_clicked()

View file

@ -4,6 +4,7 @@
#include "guiconstants.h" #include "guiconstants.h"
#include "transactiondesc.h" #include "transactiondesc.h"
#include "walletmodel.h" #include "walletmodel.h"
#include "optionsmodel.h"
#include "addresstablemodel.h" #include "addresstablemodel.h"
#include "bitcoinunits.h" #include "bitcoinunits.h"
@ -398,7 +399,7 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx)
QVariant TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const 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(showUnconfirmed)
{ {
if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature) if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature)

View file

@ -9,6 +9,7 @@
#include "csvmodelwriter.h" #include "csvmodelwriter.h"
#include "transactiondescdialog.h" #include "transactiondescdialog.h"
#include "editaddressdialog.h" #include "editaddressdialog.h"
#include "optionsmodel.h"
#include <QScrollBar> #include <QScrollBar>
#include <QComboBox> #include <QComboBox>
@ -227,7 +228,7 @@ void TransactionView::changedPrefix(const QString &prefix)
void TransactionView::changedAmount(const QString &amount) void TransactionView::changedAmount(const QString &amount)
{ {
qint64 amount_parsed = 0; 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); transactionProxyModel->setMinAmount(amount_parsed);
} }

View file

@ -9,8 +9,8 @@
#include <QTimer> #include <QTimer>
#include <QSet> #include <QSet>
WalletModel::WalletModel(CWallet *wallet, QObject *parent) : WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(0), addressTableModel(0), QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
transactionTableModel(0), transactionTableModel(0),
cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0) cachedBalance(0), cachedUnconfirmedBalance(0), cachedNumTransactions(0)
{ {
@ -20,7 +20,6 @@ WalletModel::WalletModel(CWallet *wallet, QObject *parent) :
connect(timer, SIGNAL(timeout()), this, SLOT(update())); connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(MODEL_UPDATE_DELAY); timer->start(MODEL_UPDATE_DELAY);
optionsModel = new OptionsModel(wallet, this);
addressTableModel = new AddressTableModel(wallet, this); addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this); transactionTableModel = new TransactionTableModel(wallet, this);
} }

View file

@ -20,7 +20,7 @@ class WalletModel : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WalletModel(CWallet *wallet, QObject *parent = 0); explicit WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent = 0);
enum StatusCode enum StatusCode
{ {