Browse Source

[Qt] Rework of payment request UI (mainly for insecure pr)

- this shows insecure (unsecured) payment requests in a new yellowish
  colored UI (based on the secure payment request UI) instead of our
  normal payment UI
- allows us to receive paymentACK messages for insecure payment requests
- allows us to handle expirations for insecure payment request
- changed walletmodel, so that all types of payment requests don't touch
  the addressbook
0.10
Philip Kaufmann 11 years ago
parent
commit
c6c97e0f4e
  1. 11
      src/qt/forms/sendcoinsdialog.ui
  2. 514
      src/qt/forms/sendcoinsentry.ui
  3. 74
      src/qt/paymentserver.cpp
  4. 10
      src/qt/sendcoinsdialog.cpp
  5. 62
      src/qt/sendcoinsentry.cpp
  6. 4
      src/qt/walletmodel.cpp
  7. 12
      src/qt/walletmodel.h

11
src/qt/forms/sendcoinsdialog.ui

@ -29,7 +29,16 @@
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1"> <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>

514
src/qt/forms/sendcoinsentry.ui

@ -10,13 +10,19 @@
<height>150</height> <height>150</height>
</rect> </rect>
</property> </property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
<widget class="QFrame" name="SendCoinsInsecure"> <widget class="QFrame" name="SendCoins">
<property name="toolTip">
<string>This is a normal payment.</string>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::StyledPanel</enum> <enum>QFrame::StyledPanel</enum>
</property> </property>
@ -143,7 +149,495 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QFrame" name="SendCoinsSecure"> <widget class="QFrame" name="SendCoins_InsecurePaymentRequest">
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>191</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>84</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>191</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>191</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>84</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>191</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>191</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>84</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>63</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="toolTip">
<string>This is an unverified payment request.</string>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_is">
<property name="spacing">
<number>12</number>
</property>
<item row="4" column="0">
<widget class="QLabel" name="memoLabel_is">
<property name="text">
<string>Memo:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="amountLabel_is">
<property name="text">
<string>Amount:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="payToLabel_is">
<property name="text">
<string>Pay To:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="BitcoinAmountField" name="payAmount_is">
<property name="acceptDrops">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<layout class="QHBoxLayout" name="payToLayout_is">
<property name="spacing">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="payTo_is"/>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="QLabel" name="memoTextLabel_is">
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="SendCoins_SecurePaymentRequest">
<property name="palette"> <property name="palette">
<palette> <palette>
<active> <active>
@ -586,6 +1080,9 @@
</disabled> </disabled>
</palette> </palette>
</property> </property>
<property name="toolTip">
<string>This is a verified payment request.</string>
</property>
<property name="autoFillBackground"> <property name="autoFillBackground">
<bool>true</bool> <bool>true</bool>
</property> </property>
@ -607,35 +1104,26 @@
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy">
<cstring>addAsLabel</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="5" column="0">
<widget class="QLabel" name="amountLabel_s"> <widget class="QLabel" name="amountLabel_s">
<property name="text"> <property name="text">
<string>A&amp;mount:</string> <string>Amount:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy">
<cstring>payAmount_s</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="payToLabel_s"> <widget class="QLabel" name="payToLabel_s">
<property name="text"> <property name="text">
<string>Pay &amp;To:</string> <string>Pay To:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property> </property>
<property name="buddy">
<cstring>payTo_s</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="5" column="2"> <item row="5" column="2">

74
src/qt/paymentserver.cpp

@ -280,9 +280,6 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) :
connect(this, SIGNAL(receivedPaymentACK(QString)), this, SLOT(handlePaymentACK(QString))); connect(this, SIGNAL(receivedPaymentACK(QString)), this, SLOT(handlePaymentACK(QString)));
} }
} }
// netManager is null until uiReady() is called
netManager = NULL;
} }
PaymentServer::~PaymentServer() PaymentServer::~PaymentServer()
@ -450,56 +447,57 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen
if (!optionsModel) if (!optionsModel)
return false; return false;
QList<std::pair<CScript,qint64> > sendingTos = request.getPayTo(); recipients.append(SendCoinsRecipient());
qint64 totalAmount = 0;
foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) {
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(CTransaction::nMinRelayTxFee)) {
QString msg = tr("Requested payment amount of %1 is too small (considered dust).")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second));
qDebug() << "PaymentServer::processPaymentRequest : " << msg; recipients[0].paymentRequest = request;
emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR); recipients[0].label = GUIUtil::HtmlEscape(request.getDetails().memo()); // Todo: Change to .message once available
return false;
}
totalAmount += sendingTo.second; request.getMerchant(PaymentServer::certStore, recipients[0].authenticatedMerchant);
}
recipients.append(SendCoinsRecipient()); QList<std::pair<CScript, qint64> > sendingTos = request.getPayTo();
if (request.getMerchant(PaymentServer::certStore, recipients[0].authenticatedMerchant)) { int i = 0;
recipients[0].paymentRequest = request; foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) {
recipients[0].amount = totalAmount; // Extract and check destination addresses
qDebug() << "PaymentServer::processPaymentRequest : Payment request from " << recipients[0].authenticatedMerchant;
}
else {
recipients.clear();
// Insecure payment requests may turn into more than one recipient if
// the merchant is requesting payment to more than one address.
for (int i = 0; i < sendingTos.size(); i++) {
std::pair<CScript, qint64>& sendingTo = sendingTos[i];
recipients.append(SendCoinsRecipient());
recipients[i].amount = sendingTo.second;
QString memo = QString::fromStdString(request.getDetails().memo());
recipients[i].label = GUIUtil::HtmlEscape(memo);
CTxDestination dest; CTxDestination dest;
if (ExtractDestination(sendingTo.first, dest)) { if (ExtractDestination(sendingTo.first, dest)) {
if (i == 0) // Tie request to first pay-to, we don't want multiple ACKs // Append destination address (for payment requests .address is used ONLY for GUI display)
recipients[i].paymentRequest = request; recipients[0].address.append(QString::fromStdString(CBitcoinAddress(dest).ToString()));
recipients[i].address = QString::fromStdString(CBitcoinAddress(dest).ToString()); if (i < sendingTos.size() - 1) // prevent new-line for last entry
qDebug() << "PaymentServer::processPaymentRequest : Payment request, insecure " << recipients[i].address; recipients[0].address.append("<br />");
} }
else { else if (!recipients[0].authenticatedMerchant.isEmpty()){
// Insecure payments to custom bitcoin addresses are not supported // Insecure payments to custom bitcoin addresses are not supported
// (there is no good way to tell the user where they are paying in a way // (there is no good way to tell the user where they are paying in a way
// they'd have a chance of understanding). // they'd have a chance of understanding).
emit message(tr("Payment request error"), emit message(tr("Payment request error"),
tr("Insecure requests to custom payment scripts unsupported"), tr("Unverified payment requests to custom payment scripts are unsupported."),
CClientUIInterface::MSG_ERROR); CClientUIInterface::MSG_ERROR);
return false; return false;
} }
// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(CTransaction::nMinRelayTxFee)) {
QString msg = tr("Requested payment amount of %1 is too small (considered dust).")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second));
qDebug() << "PaymentServer::processPaymentRequest : " << msg;
emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
return false;
}
recipients[0].amount += sendingTo.second;
i++;
}
// Store addresses and format them to fit nicely into the GUI
recipient.address = addresses.join("<br />");
if (!recipient.authenticatedMerchant.isEmpty()) {
qDebug() << "PaymentServer::processPaymentRequest : Secure payment request from " << recipient.authenticatedMerchant;
} }
else {
qDebug() << "PaymentServer::processPaymentRequest : Insecure payment request to " << addresses.join(", ");
} }
return true; return true;

10
src/qt/sendcoinsdialog.cpp

@ -102,7 +102,7 @@ void SendCoinsDialog::on_sendButton_clicked()
QString recipientElement; QString recipientElement;
if (rcp.authenticatedMerchant.isEmpty()) if (!rcp.paymentRequest.IsInitialized()) // normal payment
{ {
if(rcp.label.length() > 0) // label with address if(rcp.label.length() > 0) // label with address
{ {
@ -114,10 +114,14 @@ void SendCoinsDialog::on_sendButton_clicked()
recipientElement = tr("%1 to %2").arg(amount, address); recipientElement = tr("%1 to %2").arg(amount, address);
} }
} }
else // just merchant else if(!rcp.authenticatedMerchant.isEmpty()) // secure payment request
{ {
recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant)); recipientElement = tr("%1 to %2").arg(amount, GUIUtil::HtmlEscape(rcp.authenticatedMerchant));
} }
else // insecure payment request
{
recipientElement = tr("%1 to %2").arg(amount, address);
}
formatted.append(recipientElement); formatted.append(recipientElement);
} }
@ -313,7 +317,7 @@ void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv)
{ {
QString strSendCoins = tr("Send Coins"); QString strSendCoins = tr("Send Coins");
if (!rv.authenticatedMerchant.isEmpty()) { if (rv.paymentRequest.IsInitialized()) {
// Expired payment request? // Expired payment request?
const payments::PaymentDetails& details = rv.paymentRequest.getDetails(); const payments::PaymentDetails& details = rv.paymentRequest.getDetails();
if (details.has_expires() && (int64)details.expires() < GetTime()) if (details.has_expires() && (int64)details.expires() < GetTime())

62
src/qt/sendcoinsentry.cpp

@ -18,7 +18,7 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
setCurrentWidget(ui->SendCoinsInsecure); setCurrentWidget(ui->SendCoins);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
ui->payToLayout->setSpacing(4); ui->payToLayout->setSpacing(4);
@ -28,10 +28,12 @@ SendCoinsEntry::SendCoinsEntry(QWidget *parent) :
ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book")); ui->addAsLabel->setPlaceholderText(tr("Enter a label for this address to add it to your address book"));
ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)")); ui->payTo->setPlaceholderText(tr("Enter a Bitcoin address (e.g. 1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L)"));
#endif #endif
setFocusPolicy(Qt::TabFocus);
setFocusProxy(ui->payTo); setFocusProxy(ui->payTo);
// normal bitcoin address field
GUIUtil::setupAddressWidget(ui->payTo, this); GUIUtil::setupAddressWidget(ui->payTo, this);
// just a label for displaying bitcoin address(es)
ui->payTo_is->setFont(GUIUtil::bitcoinAddressFont());
} }
SendCoinsEntry::~SendCoinsEntry() SendCoinsEntry::~SendCoinsEntry()
@ -67,7 +69,7 @@ void SendCoinsEntry::setModel(WalletModel *model)
{ {
this->model = model; this->model = model;
if(model && model->getOptionsModel()) if (model && model->getOptionsModel())
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
clear(); clear();
@ -80,11 +82,15 @@ void SendCoinsEntry::setRemoveEnabled(bool enabled)
void SendCoinsEntry::clear() void SendCoinsEntry::clear()
{ {
// clear UI elements for insecure payments // clear UI elements for normal payment
ui->payTo->clear(); ui->payTo->clear();
ui->addAsLabel->clear(); ui->addAsLabel->clear();
ui->payAmount->clear(); ui->payAmount->clear();
// and the ones for secure payments just to be sure // clear UI elements for insecure payment request
ui->payTo_is->clear();
ui->memoTextLabel_is->clear();
ui->payAmount_is->clear();
// clear UI elements for secure payment request
ui->payTo_s->clear(); ui->payTo_s->clear();
ui->memoTextLabel_s->clear(); ui->memoTextLabel_s->clear();
ui->payAmount_s->clear(); ui->payAmount_s->clear();
@ -102,20 +108,23 @@ void SendCoinsEntry::on_deleteButton_clicked()
bool SendCoinsEntry::validate() bool SendCoinsEntry::validate()
{ {
if (!model)
return false;
// Check input validity // Check input validity
bool retval = true; bool retval = true;
if (!recipient.authenticatedMerchant.isEmpty()) // Skip checks for payment request
if (recipient.paymentRequest.IsInitialized())
return retval; return retval;
if (!ui->payTo->hasAcceptableInput() || if (!ui->payTo->hasAcceptableInput() || !model->validateAddress(ui->payTo->text()))
(model && !model->validateAddress(ui->payTo->text())))
{ {
ui->payTo->setValid(false); ui->payTo->setValid(false);
retval = false; retval = false;
} }
if(!ui->payAmount->validate()) if (!ui->payAmount->validate())
{ {
retval = false; retval = false;
} }
@ -131,10 +140,11 @@ bool SendCoinsEntry::validate()
SendCoinsRecipient SendCoinsEntry::getValue() SendCoinsRecipient SendCoinsEntry::getValue()
{ {
if (!recipient.authenticatedMerchant.isEmpty()) // Payment request
if (recipient.paymentRequest.IsInitialized())
return recipient; return recipient;
// User-entered or non-authenticated: // Normal payment
recipient.address = ui->payTo->text(); recipient.address = ui->payTo->text();
recipient.label = ui->addAsLabel->text(); recipient.label = ui->addAsLabel->text();
recipient.amount = ui->payAmount->value(); recipient.amount = ui->payAmount->value();
@ -156,21 +166,30 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
{ {
recipient = value; recipient = value;
if (recipient.authenticatedMerchant.isEmpty()) if (recipient.paymentRequest.IsInitialized()) // payment request
{ {
ui->payTo->setText(recipient.address); if (recipient.authenticatedMerchant.isEmpty()) // insecure
ui->addAsLabel->setText(recipient.label); {
ui->payAmount->setValue(recipient.amount); ui->payTo_is->setText(recipient.address);
ui->memoTextLabel_is->setText(recipient.label);
ui->payAmount_is->setValue(recipient.amount);
ui->payAmount_is->setReadOnly(true);
setCurrentWidget(ui->SendCoins_InsecurePaymentRequest);
} }
else else // secure
{ {
const payments::PaymentDetails& details = recipient.paymentRequest.getDetails();
ui->payTo_s->setText(recipient.authenticatedMerchant); ui->payTo_s->setText(recipient.authenticatedMerchant);
ui->memoTextLabel_s->setText(QString::fromStdString(details.memo())); ui->memoTextLabel_s->setText(recipient.label);
ui->payAmount_s->setValue(recipient.amount); ui->payAmount_s->setValue(recipient.amount);
ui->payAmount_s->setReadOnly(true); ui->payAmount_s->setReadOnly(true);
setCurrentWidget(ui->SendCoinsSecure); setCurrentWidget(ui->SendCoins_SecurePaymentRequest);
}
}
else // normal payment
{
ui->payTo->setText(recipient.address);
ui->addAsLabel->setText(recipient.label);
ui->payAmount->setValue(recipient.amount);
} }
} }
@ -182,7 +201,7 @@ void SendCoinsEntry::setAddress(const QString &address)
bool SendCoinsEntry::isClear() bool SendCoinsEntry::isClear()
{ {
return ui->payTo->text().isEmpty() && ui->payTo_s->text().isEmpty(); return ui->payTo->text().isEmpty() && ui->payTo_is->text().isEmpty() && ui->payTo_s->text().isEmpty();
} }
void SendCoinsEntry::setFocus() void SendCoinsEntry::setFocus()
@ -196,6 +215,7 @@ void SendCoinsEntry::updateDisplayUnit()
{ {
// Update payAmount with the current unit // Update payAmount with the current unit
ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); ui->payAmount->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
ui->payAmount_is->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
} }
} }

4
src/qt/walletmodel.cpp

@ -258,8 +258,8 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
// and emit coinsSent signal for each recipient // and emit coinsSent signal for each recipient
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients()) foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{ {
// Don't touch the address book when we have a secure payment-request // Don't touch the address book when we have a payment request
if (rcp.authenticatedMerchant.isEmpty()) if (!rcp.paymentRequest.IsInitialized())
{ {
std::string strAddress = rcp.address.toStdString(); std::string strAddress = rcp.address.toStdString();
CTxDestination dest = CBitcoinAddress(strAddress).Get(); CTxDestination dest = CBitcoinAddress(strAddress).Get();

12
src/qt/walletmodel.h

@ -25,14 +25,22 @@ public:
explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message): explicit SendCoinsRecipient(const QString &addr, const QString &label, quint64 amount, const QString &message):
address(addr), label(label), amount(amount), message(message) {} address(addr), label(label), amount(amount), message(message) {}
// If from an insecure payment request, this is used for storing
// the addresses, e.g. address-A<br />address-B<br />address-C.
// Info: As we don't need to process addresses in here when using
// payment requests, we can abuse it for displaying an address list.
// Todo: This is a hack, should be replaced with a cleaner solution!
QString address; QString address;
// If from a payment request, this is used for storing the memo
// Todo: This is a hack, should be replaced with a cleaner solution!
QString label; QString label;
qint64 amount; qint64 amount;
QString message; QString message;
// If from a payment request, paymentRequest.IsInitialized() will be true // If from a payment request, paymentRequest.IsInitialized() will be true
PaymentRequestPlus paymentRequest; PaymentRequestPlus paymentRequest;
QString authenticatedMerchant; // Empty if no authentication or invalid signature/cert/etc. // Empty if no authentication or invalid signature/cert/etc.
QString authenticatedMerchant;
}; };
/** Interface to Bitcoin wallet from Qt view code. */ /** Interface to Bitcoin wallet from Qt view code. */
@ -160,7 +168,7 @@ signals:
// this means that the unlocking failed or was cancelled. // this means that the unlocking failed or was cancelled.
void requireUnlock(); void requireUnlock();
// Asynchronous message notification // Fired when a message should be reported to the user
void message(const QString &title, const QString &message, unsigned int style); void message(const QString &title, const QString &message, unsigned int style);
// Coins sent: from wallet, to recipient, in (serialized) transaction: // Coins sent: from wallet, to recipient, in (serialized) transaction:

Loading…
Cancel
Save