diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2011-12-23 02:50:28 -0800 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2011-12-23 02:50:28 -0800 |
commit | 96b1e085c345f9d89288e1c7dfb37fcdbc09c083 (patch) | |
tree | 84f14ac2c8164c318b5436f05078736599936c17 /src/qt | |
parent | 2e17ac83c65b65fe2037b8c8941c25e288905903 (diff) | |
parent | 22123c85f3722abad896aebb564a89d88da92e81 (diff) |
Merge pull request #629 from sje397/master
QR Code generation via libqrencode
Diffstat (limited to 'src/qt')
-rw-r--r-- | src/qt/addressbookpage.cpp | 30 | ||||
-rw-r--r-- | src/qt/addressbookpage.h | 1 | ||||
-rw-r--r-- | src/qt/bitcoin.qrc | 1 | ||||
-rw-r--r-- | src/qt/forms/addressbookpage.ui | 11 | ||||
-rw-r--r-- | src/qt/forms/qrcodedialog.ui | 213 | ||||
-rw-r--r-- | src/qt/qrcodedialog.cpp | 106 | ||||
-rw-r--r-- | src/qt/qrcodedialog.h | 37 | ||||
-rw-r--r-- | src/qt/res/images/qrcode.png | bin | 0 -> 5993 bytes |
8 files changed, 399 insertions, 0 deletions
diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp index 0a147c9e10..d207fe30fa 100644 --- a/src/qt/addressbookpage.cpp +++ b/src/qt/addressbookpage.cpp @@ -10,6 +10,10 @@ #include <QFileDialog> #include <QMessageBox> +#ifdef USE_QRCODE +#include "qrcodedialog.h" +#endif + AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : QDialog(parent), ui(new Ui::AddressBookPage), @@ -25,6 +29,10 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) : ui->deleteButton->setIcon(QIcon()); #endif +#ifndef USE_QRCODE + ui->showQRCode->setVisible(false); +#endif + switch(mode) { case ForSending: @@ -169,10 +177,12 @@ void AddressBookPage::selectionChanged() break; } ui->copyToClipboard->setEnabled(true); + ui->showQRCode->setEnabled(true); } else { ui->deleteButton->setEnabled(false); + ui->showQRCode->setEnabled(false); ui->copyToClipboard->setEnabled(false); } } @@ -227,3 +237,23 @@ void AddressBookPage::exportClicked() QMessageBox::Abort, QMessageBox::Abort); } } + +void AddressBookPage::on_showQRCode_clicked() +{ +#ifdef USE_QRCODE + QTableView *table = ui->tableView; + QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address); + + + QRCodeDialog *d; + foreach (QModelIndex index, indexes) + { + QString address = index.data().toString(), + label = index.sibling(index.row(), 0).data().toString(), + title = QString("%1 << %2 >>").arg(label).arg(address); + + QRCodeDialog *d = new QRCodeDialog(title, address, label, tab == ReceivingTab, this); + d->show(); + } +#endif +} diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h index 1a97f3d602..2538f319dd 100644 --- a/src/qt/addressbookpage.h +++ b/src/qt/addressbookpage.h @@ -54,6 +54,7 @@ private slots: void on_newAddressButton_clicked(); void on_copyToClipboard_clicked(); void selectionChanged(); + void on_showQRCode_clicked(); }; #endif // ADDRESSBOOKDIALOG_H diff --git a/src/qt/bitcoin.qrc b/src/qt/bitcoin.qrc index aea61d6982..5693ae187e 100644 --- a/src/qt/bitcoin.qrc +++ b/src/qt/bitcoin.qrc @@ -41,6 +41,7 @@ <qresource prefix="/images"> <file alias="about">res/images/about.png</file> <file alias="splash">res/images/splash2.jpg</file> + <file alias="qrcode">res/images/qrcode.png</file> </qresource> <qresource prefix="/movies"> <file alias="update_spinner">res/movies/update_spinner.mng</file> diff --git a/src/qt/forms/addressbookpage.ui b/src/qt/forms/addressbookpage.ui index fb098c8280..9b301cbbfa 100644 --- a/src/qt/forms/addressbookpage.ui +++ b/src/qt/forms/addressbookpage.ui @@ -80,6 +80,17 @@ </widget> </item> <item> + <widget class="QPushButton" name="showQRCode"> + <property name="text"> + <string>Show &QR Code</string> + </property> + <property name="icon"> + <iconset resource="../bitcoin.qrc"> + <normaloff>:/images/qrcode</normaloff>:/images/qrcode</iconset> + </property> + </widget> + </item> + <item> <widget class="QPushButton" name="deleteButton"> <property name="toolTip"> <string>Delete the currently selected address from the list. Only sending addresses can be deleted.</string> diff --git a/src/qt/forms/qrcodedialog.ui b/src/qt/forms/qrcodedialog.ui new file mode 100644 index 0000000000..fa21f60b9e --- /dev/null +++ b/src/qt/forms/qrcodedialog.ui @@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QRCodeDialog</class> + <widget class="QDialog" name="QRCodeDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>320</width> + <height>404</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLabel" name="lblQRCode"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>300</height> + </size> + </property> + <property name="text"> + <string>QR Code</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QCheckBox" name="chkReq"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Request Payment</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="lblAm1"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Amount:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnReqAmount</cstring> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lnReqAmount"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="lblAm2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>BTC</string> + </property> + <property name="buddy"> + <cstring>lnReqAmount</cstring> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Label:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnLabel</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lnLabel"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Message:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="buddy"> + <cstring>lnMessage</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lnMessage"> + <property name="minimumSize"> + <size> + <width>100</width> + <height>0</height> + </size> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="btnSaveAs"> + <property name="text"> + <string>&Save As...</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>chkReq</sender> + <signal>clicked(bool)</signal> + <receiver>lnReqAmount</receiver> + <slot>setEnabled(bool)</slot> + <hints> + <hint type="sourcelabel"> + <x>92</x> + <y>285</y> + </hint> + <hint type="destinationlabel"> + <x>98</x> + <y>311</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/qt/qrcodedialog.cpp b/src/qt/qrcodedialog.cpp new file mode 100644 index 0000000000..ed4c758e38 --- /dev/null +++ b/src/qt/qrcodedialog.cpp @@ -0,0 +1,106 @@ +#include "qrcodedialog.h" +#include "ui_qrcodedialog.h" +#include <QPixmap> +#include <QUrl> +#include <QFileDialog> +#include <QDesktopServices> +#include <QDebug> + +#include <qrencode.h> + +#define EXPORT_IMAGE_SIZE 256 + +QRCodeDialog::QRCodeDialog(const QString &title, const QString &addr, const QString &label, bool enableReq, QWidget *parent) : + QDialog(parent), + ui(new Ui::QRCodeDialog), + address(addr) +{ + ui->setupUi(this); + setWindowTitle(title); + setAttribute(Qt::WA_DeleteOnClose); + + ui->chkReq->setVisible(enableReq); + ui->lnReqAmount->setVisible(enableReq); + ui->lblAm1->setVisible(enableReq); + ui->lblAm2->setVisible(enableReq); + + ui->lnLabel->setText(label); + + genCode(); +} + +QRCodeDialog::~QRCodeDialog() +{ + delete ui; +} + +void QRCodeDialog::genCode() { + + QString uri = getURI(); + //qDebug() << "Encoding:" << uri.toUtf8().constData(); + QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1); + myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32); + myImage.fill(0xffffff); + unsigned char *p = code->data; + for(int y = 0; y < code->width; y++) { + for(int x = 0; x < code->width; x++) { + myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff)); + p++; + } + } + QRcode_free(code); + ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300)); +} + +QString QRCodeDialog::getURI() { + QString ret = QString("bitcoin:%1").arg(address); + + int paramCount = 0; + if(ui->chkReq->isChecked() && ui->lnReqAmount->text().isEmpty() == false) { + bool ok= false; + double amount = ui->lnReqAmount->text().toDouble(&ok); + if(ok) { + ret += QString("?amount=%1X8").arg(ui->lnReqAmount->text()); + paramCount++; + } + } + + if(ui->lnLabel->text().isEmpty() == false) { + QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text())); + ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl); + paramCount++; + } + + if(ui->lnMessage->text().isEmpty() == false) { + QString msg(QUrl::toPercentEncoding(ui->lnMessage->text())); + ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg); + paramCount++; + } + + return ret; +} + +void QRCodeDialog::on_lnReqAmount_textChanged(const QString &) { + genCode(); +} + +void QRCodeDialog::on_lnLabel_textChanged(const QString &) { + genCode(); +} + +void QRCodeDialog::on_lnMessage_textChanged(const QString &) { + genCode(); +} + +void QRCodeDialog::on_btnSaveAs_clicked() +{ + QString fn = QFileDialog::getSaveFileName(this, "Save Image...", QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation), "Images (*.png)"); + if(!fn.isEmpty()) { + myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn); + } +} + +void QRCodeDialog::on_chkReq_toggled(bool) +{ + genCode(); +} diff --git a/src/qt/qrcodedialog.h b/src/qt/qrcodedialog.h new file mode 100644 index 0000000000..7463a8810e --- /dev/null +++ b/src/qt/qrcodedialog.h @@ -0,0 +1,37 @@ +#ifndef QRCODEDIALOG_H +#define QRCODEDIALOG_H + +#include <QDialog> +#include <QImage> + +namespace Ui { + class QRCodeDialog; +} + +class QRCodeDialog : public QDialog +{ + Q_OBJECT + +public: + explicit QRCodeDialog(const QString &title, const QString &address, const QString &label, bool allowReq, QWidget *parent = 0); + ~QRCodeDialog(); + +private slots: + void on_lnReqAmount_textChanged(const QString &arg1); + void on_lnLabel_textChanged(const QString &arg1); + void on_lnMessage_textChanged(const QString &arg1); + void on_btnSaveAs_clicked(); + + void on_chkReq_toggled(bool checked); + +private: + Ui::QRCodeDialog *ui; + QImage myImage; + + QString getURI(); + QString address; + + void genCode(); +}; + +#endif // QRCODEDIALOG_H diff --git a/src/qt/res/images/qrcode.png b/src/qt/res/images/qrcode.png Binary files differnew file mode 100644 index 0000000000..c89a49bbce --- /dev/null +++ b/src/qt/res/images/qrcode.png |