Accept "bitcoin:" URL drops from browsers
This commit is contained in:
parent
330c190958
commit
db7f023417
8 changed files with 130 additions and 15 deletions
|
@ -38,6 +38,9 @@
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QMovie>
|
#include <QMovie>
|
||||||
|
|
||||||
|
#include <QDragEnterEvent>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -143,7 +146,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
||||||
// Clicking on a transaction simply sends you to transaction history page
|
// Clicking on a transaction simply sends you to transaction history page
|
||||||
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
|
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
|
||||||
|
|
||||||
gotoOverviewPage();
|
setAcceptDrops(true);
|
||||||
|
|
||||||
|
gotoOverviewPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitcoinGUI::createActions()
|
void BitcoinGUI::createActions()
|
||||||
|
@ -502,10 +507,36 @@ void BitcoinGUI::gotoReceiveCoinsPage()
|
||||||
void BitcoinGUI::gotoSendCoinsPage()
|
void BitcoinGUI::gotoSendCoinsPage()
|
||||||
{
|
{
|
||||||
sendCoinsAction->setChecked(true);
|
sendCoinsAction->setChecked(true);
|
||||||
sendCoinsPage->clear();
|
if(centralWidget->currentWidget() != sendCoinsPage)
|
||||||
|
{
|
||||||
|
// Clear the current contents if we arrived from another tab
|
||||||
|
sendCoinsPage->clear();
|
||||||
|
}
|
||||||
centralWidget->setCurrentWidget(sendCoinsPage);
|
centralWidget->setCurrentWidget(sendCoinsPage);
|
||||||
|
|
||||||
exportAction->setEnabled(false);
|
exportAction->setEnabled(false);
|
||||||
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
disconnect(exportAction, SIGNAL(triggered()), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BitcoinGUI::dragEnterEvent(QDragEnterEvent *event)
|
||||||
|
{
|
||||||
|
// Accept only URLs
|
||||||
|
if(event->mimeData()->hasUrls())
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitcoinGUI::dropEvent(QDropEvent *event)
|
||||||
|
{
|
||||||
|
if(event->mimeData()->hasUrls())
|
||||||
|
{
|
||||||
|
gotoSendCoinsPage();
|
||||||
|
QList<QUrl> urls = event->mimeData()->urls();
|
||||||
|
foreach(const QUrl &url, urls)
|
||||||
|
{
|
||||||
|
sendCoinsPage->handleURL(&url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event->acceptProposedAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ class QAbstractItemModel;
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
class QProgressBar;
|
class QProgressBar;
|
||||||
class QStackedWidget;
|
class QStackedWidget;
|
||||||
|
class QUrl;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class BitcoinGUI : public QMainWindow
|
class BitcoinGUI : public QMainWindow
|
||||||
|
@ -41,6 +42,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void changeEvent(QEvent *e);
|
void changeEvent(QEvent *e);
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
void dragEnterEvent(QDragEnterEvent *event);
|
||||||
|
void dropEvent(QDropEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClientModel *clientModel;
|
ClientModel *clientModel;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "guiutil.h"
|
#include "guiutil.h"
|
||||||
#include "bitcoinaddressvalidator.h"
|
#include "bitcoinaddressvalidator.h"
|
||||||
|
#include "walletmodel.h"
|
||||||
|
#include "bitcoinunits.h"
|
||||||
|
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
|
|
||||||
|
@ -8,6 +10,7 @@
|
||||||
#include <QDoubleValidator>
|
#include <QDoubleValidator>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
QString GUIUtil::DateTimeStr(qint64 nTime)
|
QString GUIUtil::DateTimeStr(qint64 nTime)
|
||||||
{
|
{
|
||||||
|
@ -41,3 +44,22 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
||||||
widget->setValidator(amountValidator);
|
widget->setValidator(amountValidator);
|
||||||
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out)
|
||||||
|
{
|
||||||
|
if(url->scheme() != QString("bitcoin"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SendCoinsRecipient rv;
|
||||||
|
rv.address = url->path();
|
||||||
|
rv.label = url->queryItemValue("label");
|
||||||
|
if(!BitcoinUnits::parse(BitcoinUnits::BTC, url->queryItemValue("amount"), &rv.amount))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(out)
|
||||||
|
{
|
||||||
|
*out = rv;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -8,20 +8,26 @@ class QFont;
|
||||||
class QLineEdit;
|
class QLineEdit;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
class QDateTime;
|
class QDateTime;
|
||||||
|
class QUrl;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
class SendCoinsRecipient;
|
||||||
|
|
||||||
class GUIUtil
|
class GUIUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Create human-readable string from date
|
||||||
static QString DateTimeStr(qint64 nTime);
|
static QString DateTimeStr(qint64 nTime);
|
||||||
static QString DateTimeStr(const QDateTime &datetime);
|
static QString DateTimeStr(const QDateTime &datetime);
|
||||||
|
|
||||||
// Render bitcoin addresses in monospace font
|
// Render bitcoin addresses in monospace font
|
||||||
static QFont bitcoinAddressFont();
|
static QFont bitcoinAddressFont();
|
||||||
|
|
||||||
|
// Set up widgets for address and amounts
|
||||||
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
||||||
|
|
||||||
static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
||||||
|
|
||||||
|
// Parse "bitcoin:" URL into recipient object, return true on succesful parsing
|
||||||
|
static bool parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GUIUTIL_H
|
#endif // GUIUTIL_H
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
#include "addressbookpage.h"
|
#include "addressbookpage.h"
|
||||||
#include "optionsmodel.h"
|
#include "optionsmodel.h"
|
||||||
#include "sendcoinsentry.h"
|
#include "sendcoinsentry.h"
|
||||||
|
#include "guiutil.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QTextDocument>
|
#include <QTextDocument>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
|
SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
|
@ -133,17 +134,11 @@ void SendCoinsDialog::on_sendButton_clicked()
|
||||||
void SendCoinsDialog::clear()
|
void SendCoinsDialog::clear()
|
||||||
{
|
{
|
||||||
// Remove entries until only one left
|
// Remove entries until only one left
|
||||||
while(ui->entries->count() > 1)
|
while(ui->entries->count())
|
||||||
{
|
{
|
||||||
delete ui->entries->takeAt(0)->widget();
|
delete ui->entries->takeAt(0)->widget();
|
||||||
}
|
}
|
||||||
|
addEntry();
|
||||||
// Reset the entry that is left to empty
|
|
||||||
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
|
|
||||||
if(entry)
|
|
||||||
{
|
|
||||||
entry->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateRemoveEnabled();
|
updateRemoveEnabled();
|
||||||
|
|
||||||
|
@ -160,7 +155,7 @@ void SendCoinsDialog::accept()
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendCoinsDialog::addEntry()
|
SendCoinsEntry *SendCoinsDialog::addEntry()
|
||||||
{
|
{
|
||||||
SendCoinsEntry *entry = new SendCoinsEntry(this);
|
SendCoinsEntry *entry = new SendCoinsEntry(this);
|
||||||
entry->setModel(model);
|
entry->setModel(model);
|
||||||
|
@ -171,6 +166,7 @@ void SendCoinsDialog::addEntry()
|
||||||
|
|
||||||
// Focus the field, so that entry can start immediately
|
// Focus the field, so that entry can start immediately
|
||||||
entry->clear();
|
entry->clear();
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendCoinsDialog::updateRemoveEnabled()
|
void SendCoinsDialog::updateRemoveEnabled()
|
||||||
|
@ -208,3 +204,34 @@ QWidget *SendCoinsDialog::setupTabChain(QWidget *prev)
|
||||||
QWidget::setTabOrder(ui->addButton, ui->sendButton);
|
QWidget::setTabOrder(ui->addButton, ui->sendButton);
|
||||||
return ui->sendButton;
|
return ui->sendButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendCoinsDialog::pasteEntry(const SendCoinsRecipient &rv)
|
||||||
|
{
|
||||||
|
SendCoinsEntry *entry = 0;
|
||||||
|
// Replace the first entry if it is still unused
|
||||||
|
if(ui->entries->count() == 1)
|
||||||
|
{
|
||||||
|
SendCoinsEntry *first = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget());
|
||||||
|
if(first->isClear())
|
||||||
|
{
|
||||||
|
entry = first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!entry)
|
||||||
|
{
|
||||||
|
entry = addEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->setValue(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SendCoinsDialog::handleURL(const QUrl *url)
|
||||||
|
{
|
||||||
|
SendCoinsRecipient rv;
|
||||||
|
if(!GUIUtil::parseBitcoinURL(url, &rv))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pasteEntry(rv);
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,11 @@ namespace Ui {
|
||||||
}
|
}
|
||||||
class WalletModel;
|
class WalletModel;
|
||||||
class SendCoinsEntry;
|
class SendCoinsEntry;
|
||||||
|
class SendCoinsRecipient;
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QUrl;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class SendCoinsDialog : public QDialog
|
class SendCoinsDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -23,11 +28,14 @@ public:
|
||||||
// Hence we have to set it up manually
|
// Hence we have to set it up manually
|
||||||
QWidget *setupTabChain(QWidget *prev);
|
QWidget *setupTabChain(QWidget *prev);
|
||||||
|
|
||||||
|
void pasteEntry(const SendCoinsRecipient &rv);
|
||||||
|
void handleURL(const QUrl *url);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void clear();
|
void clear();
|
||||||
void reject();
|
void reject();
|
||||||
void accept();
|
void accept();
|
||||||
void addEntry();
|
SendCoinsEntry *addEntry();
|
||||||
void updateRemoveEnabled();
|
void updateRemoveEnabled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -102,7 +102,6 @@ bool SendCoinsEntry::validate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!ui->payTo->hasAcceptableInput() ||
|
if(!ui->payTo->hasAcceptableInput() ||
|
||||||
(model && !model->validateAddress(ui->payTo->text())))
|
(model && !model->validateAddress(ui->payTo->text())))
|
||||||
{
|
{
|
||||||
|
@ -133,3 +132,16 @@ QWidget *SendCoinsEntry::setupTabChain(QWidget *prev)
|
||||||
QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
|
QWidget::setTabOrder(ui->deleteButton, ui->addAsLabel);
|
||||||
return ui->payAmount->setupTabChain(ui->addAsLabel);
|
return ui->payAmount->setupTabChain(ui->addAsLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
|
||||||
|
{
|
||||||
|
ui->payTo->setText(value.address);
|
||||||
|
ui->addAsLabel->setText(value.label);
|
||||||
|
ui->payAmount->setValue(value.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SendCoinsEntry::isClear()
|
||||||
|
{
|
||||||
|
return ui->payTo->text().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,12 @@ public:
|
||||||
void setModel(WalletModel *model);
|
void setModel(WalletModel *model);
|
||||||
bool validate();
|
bool validate();
|
||||||
SendCoinsRecipient getValue();
|
SendCoinsRecipient getValue();
|
||||||
|
|
||||||
|
// Return true if the entry is still empty and unedited
|
||||||
|
bool isClear();
|
||||||
|
|
||||||
|
void setValue(const SendCoinsRecipient &value);
|
||||||
|
|
||||||
// Qt messes up the tab chain by default in some cases (issue http://bugreports.qt.nokia.com/browse/QTBUG-10907)
|
// Qt messes up the tab chain by default in some cases (issue http://bugreports.qt.nokia.com/browse/QTBUG-10907)
|
||||||
// Hence we have to set it up manually
|
// Hence we have to set it up manually
|
||||||
QWidget *setupTabChain(QWidget *prev);
|
QWidget *setupTabChain(QWidget *prev);
|
||||||
|
|
Loading…
Reference in a new issue