293542866b9854c75dfc26bd2ac90c3b5ed01eda
[novacoin.git] / src / qt / qrcodedialog.cpp
1 #include "qrcodedialog.h"
2 #include "ui_qrcodedialog.h"
3
4 #include "bitcoinunits.h"
5 #include "guiconstants.h"
6 #include "guiutil.h"
7 #include "optionsmodel.h"
8
9 #include <QPixmap>
10 #include <QUrl>
11
12 #include <qrencode.h>
13
14 QRCodeDialog::QRCodeDialog(const QString &addr, const QString &label, bool enableReq, QWidget *parent) :
15     QDialog(parent),
16     ui(new Ui::QRCodeDialog),
17     model(0),
18     address(addr)
19 {
20     ui->setupUi(this);
21
22     setWindowTitle(QString("%1").arg(address));
23
24     ui->chkReqPayment->setVisible(enableReq);
25     ui->lblAmount->setVisible(enableReq);
26     ui->lnReqAmount->setVisible(enableReq);
27
28     ui->lnLabel->setText(label);
29
30     ui->btnSaveAs->setEnabled(false);
31
32     genCode();
33 }
34
35 QRCodeDialog::~QRCodeDialog()
36 {
37     delete ui;
38 }
39
40 void QRCodeDialog::setModel(OptionsModel *model)
41 {
42     this->model = model;
43
44     if (model)
45         connect(model, SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
46
47     // update the display unit, to not use the default ("BTC")
48     updateDisplayUnit();
49 }
50
51 void QRCodeDialog::genCode()
52 {
53     QString uri = getURI();
54
55     if (uri != "")
56     {
57         ui->lblQRCode->setText("");
58
59         QRcode *code = QRcode_encodeString(uri.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
60         if (!code)
61         {
62             ui->lblQRCode->setText(tr("Error encoding URI into QR Code."));
63             return;
64         }
65         myImage = QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
66         myImage.fill(0xffffff);
67         unsigned char *p = code->data;
68         for (int y = 0; y < code->width; y++)
69         {
70             for (int x = 0; x < code->width; x++)
71             {
72                 myImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
73                 p++;
74             }
75         }
76         QRcode_free(code);
77
78         ui->lblQRCode->setPixmap(QPixmap::fromImage(myImage).scaled(300, 300));
79
80         ui->outUri->setPlainText(uri);
81     }
82 }
83
84 QString QRCodeDialog::getURI()
85 {
86     QString ret = QString("novacoin:%1").arg(address);
87     int paramCount = 0;
88
89     ui->outUri->clear();
90
91     if (ui->chkReqPayment->isChecked())
92     {
93         if (ui->lnReqAmount->validate())
94         {
95             // even if we allow a non BTC unit input in lnReqAmount, we generate the URI with BTC as unit (as defined in BIP21)
96             ret += QString("?amount=%1").arg(BitcoinUnits::format(BitcoinUnits::BTC, ui->lnReqAmount->value()));
97             paramCount++;
98         }
99         else
100         {
101             ui->btnSaveAs->setEnabled(false);
102             ui->lblQRCode->setText(tr("The entered amount is invalid, please check."));
103             return QString("");
104         }
105     }
106
107     if (!ui->lnLabel->text().isEmpty())
108     {
109         QString lbl(QUrl::toPercentEncoding(ui->lnLabel->text()));
110         ret += QString("%1label=%2").arg(paramCount == 0 ? "?" : "&").arg(lbl);
111         paramCount++;
112     }
113
114     if (!ui->lnMessage->text().isEmpty())
115     {
116         QString msg(QUrl::toPercentEncoding(ui->lnMessage->text()));
117         ret += QString("%1message=%2").arg(paramCount == 0 ? "?" : "&").arg(msg);
118         paramCount++;
119     }
120
121     // limit URI length to prevent a DoS against the QR-Code dialog
122     if (ret.length() > MAX_URI_LENGTH)
123     {
124         ui->btnSaveAs->setEnabled(false);
125         ui->lblQRCode->setText(tr("Resulting URI too long, try to reduce the text for label / message."));
126         return QString("");
127     }
128
129     ui->btnSaveAs->setEnabled(true);
130     return ret;
131 }
132
133 void QRCodeDialog::on_lnReqAmount_textChanged()
134 {
135     genCode();
136 }
137
138 void QRCodeDialog::on_lnLabel_textChanged()
139 {
140     genCode();
141 }
142
143 void QRCodeDialog::on_lnMessage_textChanged()
144 {
145     genCode();
146 }
147
148 void QRCodeDialog::on_btnSaveAs_clicked()
149 {
150     QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(), tr("PNG Images (*.png)"));
151     if (!fn.isEmpty())
152         myImage.scaled(EXPORT_IMAGE_SIZE, EXPORT_IMAGE_SIZE).save(fn);
153 }
154
155 void QRCodeDialog::on_chkReqPayment_toggled(bool fChecked)
156 {
157     if (!fChecked)
158         // if chkReqPayment is not active, don't display lnReqAmount as invalid
159         ui->lnReqAmount->setValid(true);
160
161     genCode();
162 }
163
164 void QRCodeDialog::updateDisplayUnit()
165 {
166     if (model)
167     {
168         // Update lnReqAmount with the current unit
169         ui->lnReqAmount->setDisplayUnit(model->getDisplayUnit());
170     }
171 }