Mercurial > hg > bitcoin
changeset 1257:3f0305184c57 draft
Accept "bitcoin:" URL drops from browsers
author | Wladimir J. van der Laan <laanwj@gmail.com> |
---|---|
date | Sun, 07 Aug 2011 16:04:48 +0200 |
parents | 3a687b55c04b |
children | d0d7e33253e5 |
files | src/qt/bitcoingui.cpp src/qt/bitcoingui.h src/qt/guiutil.cpp src/qt/guiutil.h src/qt/sendcoinsdialog.cpp src/qt/sendcoinsdialog.h src/qt/sendcoinsentry.cpp src/qt/sendcoinsentry.h |
diffstat | 8 files changed, 130 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -38,6 +38,9 @@ #include <QDateTime> #include <QMovie> +#include <QDragEnterEvent> +#include <QUrl> + #include <QDebug> #include <iostream> @@ -143,7 +146,9 @@ // Clicking on a transaction simply sends you to transaction history page connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage())); - gotoOverviewPage(); + setAcceptDrops(true); + + gotoOverviewPage(); } void BitcoinGUI::createActions() @@ -502,10 +507,36 @@ void BitcoinGUI::gotoSendCoinsPage() { sendCoinsAction->setChecked(true); - sendCoinsPage->clear(); + if(centralWidget->currentWidget() != sendCoinsPage) + { + // Clear the current contents if we arrived from another tab + sendCoinsPage->clear(); + } centralWidget->setCurrentWidget(sendCoinsPage); exportAction->setEnabled(false); 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(); +} +
--- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -20,6 +20,7 @@ class QModelIndex; class QProgressBar; class QStackedWidget; +class QUrl; QT_END_NAMESPACE class BitcoinGUI : public QMainWindow @@ -41,6 +42,8 @@ protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent *event); + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); private: ClientModel *clientModel;
--- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1,5 +1,7 @@ #include "guiutil.h" #include "bitcoinaddressvalidator.h" +#include "walletmodel.h" +#include "bitcoinunits.h" #include "headers.h" @@ -8,6 +10,7 @@ #include <QDoubleValidator> #include <QFont> #include <QLineEdit> +#include <QUrl> QString GUIUtil::DateTimeStr(qint64 nTime) { @@ -41,3 +44,22 @@ widget->setValidator(amountValidator); 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; +}
--- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -8,20 +8,26 @@ class QLineEdit; class QWidget; class QDateTime; +class QUrl; QT_END_NAMESPACE +class SendCoinsRecipient; class GUIUtil { public: + // Create human-readable string from date static QString DateTimeStr(qint64 nTime); static QString DateTimeStr(const QDateTime &datetime); // Render bitcoin addresses in monospace font static QFont bitcoinAddressFont(); + // Set up widgets for address and amounts 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
--- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -5,11 +5,12 @@ #include "addressbookpage.h" #include "optionsmodel.h" #include "sendcoinsentry.h" - +#include "guiutil.h" #include <QMessageBox> #include <QLocale> #include <QTextDocument> +#include <QDebug> SendCoinsDialog::SendCoinsDialog(QWidget *parent) : QDialog(parent), @@ -133,17 +134,11 @@ void SendCoinsDialog::clear() { // Remove entries until only one left - while(ui->entries->count() > 1) + while(ui->entries->count()) { delete ui->entries->takeAt(0)->widget(); } - - // Reset the entry that is left to empty - SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(0)->widget()); - if(entry) - { - entry->clear(); - } + addEntry(); updateRemoveEnabled(); @@ -160,7 +155,7 @@ clear(); } -void SendCoinsDialog::addEntry() +SendCoinsEntry *SendCoinsDialog::addEntry() { SendCoinsEntry *entry = new SendCoinsEntry(this); entry->setModel(model); @@ -171,6 +166,7 @@ // Focus the field, so that entry can start immediately entry->clear(); + return entry; } void SendCoinsDialog::updateRemoveEnabled() @@ -208,3 +204,34 @@ QWidget::setTabOrder(ui->addButton, 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); +}
--- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -8,6 +8,11 @@ } class WalletModel; class SendCoinsEntry; +class SendCoinsRecipient; + +QT_BEGIN_NAMESPACE +class QUrl; +QT_END_NAMESPACE class SendCoinsDialog : public QDialog { @@ -23,11 +28,14 @@ // Hence we have to set it up manually QWidget *setupTabChain(QWidget *prev); + void pasteEntry(const SendCoinsRecipient &rv); + void handleURL(const QUrl *url); + public slots: void clear(); void reject(); void accept(); - void addEntry(); + SendCoinsEntry *addEntry(); void updateRemoveEnabled(); private:
--- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -102,7 +102,6 @@ } } - if(!ui->payTo->hasAcceptableInput() || (model && !model->validateAddress(ui->payTo->text()))) { @@ -133,3 +132,16 @@ QWidget::setTabOrder(ui->deleteButton, 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(); +} +
--- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -20,6 +20,12 @@ void setModel(WalletModel *model); bool validate(); 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) // Hence we have to set it up manually QWidget *setupTabChain(QWidget *prev);