Browse Source

Added QRCode generation functions via libqrencode. Switch on with USE_QRENCODE=1.

Amended build docs for Linux and OSX, and OSX makefile.
Added package 'qrencode' to gitian.yml
tags/v0.15.1
sje397 10 years ago
parent
commit
22123c85f3

+ 14
- 0
bitcoin-qt.pro View File

@@ -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

+ 1
- 0
contrib/gitian-descriptors/gitian.yml View File

@@ -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"

+ 3
- 0
doc/build-osx.txt View File

@@ -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

+ 13
- 7
doc/build-unix.txt View File

@@ -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

+ 4
- 0
src/makefile.osx View File

@@ -95,6 +95,10 @@ else
endif
endif

ifdef USE_QRCODE
DEFS += -DUSE_QRCODE=$(USE_QRCODE)
LIBS += -lqrencode
endif

all: bitcoind


+ 30
- 0
src/qt/addressbookpage.cpp View File

@@ -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
}

+ 1
- 0
src/qt/addressbookpage.h View File

@@ -54,6 +54,7 @@ private slots:
void on_newAddressButton_clicked();
void on_copyToClipboard_clicked();
void selectionChanged();
void on_showQRCode_clicked();
};

#endif // ADDRESSBOOKDIALOG_H

+ 1
- 0
src/qt/bitcoin.qrc View File

@@ -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>

+ 11
- 0
src/qt/forms/addressbookpage.ui View File

@@ -79,6 +79,17 @@
</property>
</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">

+ 213
- 0
src/qt/forms/qrcodedialog.ui View File

@@ -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>

+ 106
- 0
src/qt/qrcodedialog.cpp View File

@@ -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();
}

+ 37
- 0
src/qt/qrcodedialog.h View File

@@ -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

BIN
src/qt/res/images/qrcode.png View File


Loading…
Cancel
Save