aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro14
-rw-r--r--contrib/gitian-descriptors/gitian.yml1
-rw-r--r--doc/build-osx.txt3
-rw-r--r--doc/build-unix.txt20
-rw-r--r--src/makefile.osx4
-rw-r--r--src/qt/addressbookpage.cpp30
-rw-r--r--src/qt/addressbookpage.h1
-rw-r--r--src/qt/bitcoin.qrc1
-rw-r--r--src/qt/forms/addressbookpage.ui11
-rw-r--r--src/qt/forms/qrcodedialog.ui213
-rw-r--r--src/qt/qrcodedialog.cpp106
-rw-r--r--src/qt/qrcodedialog.h37
-rw-r--r--src/qt/res/images/qrcode.pngbin0 -> 5993 bytes
13 files changed, 434 insertions, 7 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index 0bd2113c67..b690faecd7 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -19,6 +19,14 @@ OBJECTS_DIR = build
MOC_DIR = build
UI_DIR = build
+# use: qmake "USE_QRCODE=1"
+# libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support
+contains(USE_QRCODE, 1) {
+ message(Building with QRCode support)
+ DEFINES += USE_QRCODE
+ LIBS += -lqrencode
+}
+
# use: qmake "RELEASE=1"
contains(RELEASE, 1) {
# Mac: compile for maximum compatibility (10.5, 32-bit)
@@ -199,6 +207,12 @@ FORMS += \
src/qt/forms/sendcoinsentry.ui \
src/qt/forms/askpassphrasedialog.ui
+contains(USE_QRCODE, 1) {
+HEADERS += src/qt/qrcodedialog.h
+SOURCES += src/qt/qrcodedialog.cpp
+FORMS += src/qt/forms/qrcodedialog.ui
+}
+
CODECFORTR = UTF-8
# for lrelease/lupdate
diff --git a/contrib/gitian-descriptors/gitian.yml b/contrib/gitian-descriptors/gitian.yml
index 65005c61ff..6f503ac0bf 100644
--- a/contrib/gitian-descriptors/gitian.yml
+++ b/contrib/gitian-descriptors/gitian.yml
@@ -16,6 +16,7 @@ packages:
- "libssl-dev"
- "git-core"
- "unzip"
+- "qrencode"
reference_datetime: "2011-01-30 00:00:00"
remotes:
- "url": "https://github.com/bitcoin/bitcoin.git"
diff --git a/doc/build-osx.txt b/doc/build-osx.txt
index 800244153a..d47febe94b 100644
--- a/doc/build-osx.txt
+++ b/doc/build-osx.txt
@@ -43,6 +43,9 @@ pushd bitcoin/contrib/minipupnpc; sudo port install; popd
(this will be unnecessary soon, you will just port install miniupnpc
along with the rest of the dependencies).
+Optionally install qrencode (and set USE_QRCODE=1):
+sudo port install qrencode
+
4. Now you should be able to build bitcoind:
cd bitcoin/src
diff --git a/doc/build-unix.txt b/doc/build-unix.txt
index f4178caae5..538933984c 100644
--- a/doc/build-unix.txt
+++ b/doc/build-unix.txt
@@ -23,12 +23,13 @@ the graphical bitcoin.
Dependencies
------------
- Library Purpose Description
- ------- ------- -----------
- libssl SSL Support Secure communications
- libdb4.8 Berkeley DB Blockchain & wallet storage
- libboost Boost C++ Library
- miniupnpc UPnP Support Optional firewall-jumping support
+ Library Purpose Description
+ ------- ------- -----------
+ libssl SSL Support Secure communications
+ libdb4.8 Berkeley DB Blockchain & wallet storage
+ libboost Boost C++ Library
+ miniupnpc UPnP Support Optional firewall-jumping support
+ libqrencode QRCode generation Optional QRCode generation
miniupnpc may be used for UPnP port mapping. It can be downloaded from
http://miniupnp.tuxfamily.org/files/. UPnP support is compiled in and
@@ -37,6 +38,12 @@ turned off by default. Set USE_UPNP to a different value to control this:
USE_UPNP=0 (the default) UPnP support turned off by default at runtime
USE_UPNP=1 UPnP support turned on by default at runtime
+libqrencode may be used for QRCode image generation. It can be downloaded
+from http://fukuchi.org/works/qrencode/index.html.en, or installed via
+your package manager. Set USE_QRCODE to control this:
+ USE_QRCODE=0 (the default) No QRCode support - libarcode not required
+ USE_QRCODE=1 QRCode support enabled
+
Licenses of statically linked libraries:
Berkeley DB New BSD license with additional requirement that linked
software must be free open source
@@ -50,7 +57,6 @@ Versions used in this release:
Boost 1.37
miniupnpc 1.6
-
Dependency Build Instructions: Ubuntu & Debian
----------------------------------------------
sudo apt-get install build-essential
diff --git a/src/makefile.osx b/src/makefile.osx
index bd72e6bc03..cf5ec38d29 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -96,6 +96,10 @@ else
endif
endif
+ifdef USE_QRCODE
+ DEFS += -DUSE_QRCODE=$(USE_QRCODE)
+ LIBS += -lqrencode
+endif
all: bitcoind
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 &amp;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>&amp;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
new file mode 100644
index 0000000000..c89a49bbce
--- /dev/null
+++ b/src/qt/res/images/qrcode.png
Binary files differ