Browse Source

Initial checkin

import_zecw
Aditya Kulkarni 6 years ago
parent
commit
684edead71
  1. 12
      .gitignore
  2. 18928
      3rdparty/json/json.hpp
  3. 41
      3rdparty/qrcode/BitBuffer.cpp
  4. 52
      3rdparty/qrcode/BitBuffer.hpp
  5. 620
      3rdparty/qrcode/QrCode.cpp
  6. 351
      3rdparty/qrcode/QrCode.hpp
  7. 225
      3rdparty/qrcode/QrSegment.cpp
  8. 216
      3rdparty/qrcode/QrSegment.hpp
  9. BIN
      Ubuntu-R.ttf
  10. 87
      about.ui
  11. 5
      application.qrc
  12. 92
      balancestablemodel.cpp
  13. 24
      balancestablemodel.h
  14. 139
      confirm.ui
  15. 23
      main.cpp
  16. 275
      mainwindow.cpp
  17. 47
      mainwindow.h
  18. 674
      mainwindow.ui
  19. 40
      precompiled.h
  20. 712
      qt5.natvis
  21. 495
      rpc.cpp
  22. 80
      rpc.h
  23. 256
      sendtab.cpp
  24. 64
      settings.cpp
  25. 24
      settings.h
  26. 194
      settings.ui
  27. 12
      transactionitem.cpp
  28. 20
      transactionitem.h
  29. 71
      txid.ui
  30. 75
      txtablemodel.cpp
  31. 26
      txtablemodel.h
  32. 86
      ui_about.h
  33. 130
      ui_confirm.h
  34. 683
      ui_mainwindow.h
  35. 175
      ui_settings.h
  36. 9
      unspentoutput.cpp
  37. 18
      unspentoutput.h
  38. 70
      zcash-qt-wallet.pro

12
.gitignore

@ -0,0 +1,12 @@
bin/
debug/
release/
x64/
.vscode/
*.autosave
.qmake.stash
zcash-qt-wallet
zcash-qt-wallet.pro.user
Makefile
qrc_application.cpp
zcash-qt-wallet_plugin_import.cpp

18928
3rdparty/json/json.hpp

File diff suppressed because it is too large

41
3rdparty/qrcode/BitBuffer.cpp

@ -0,0 +1,41 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <stdexcept>
#include "BitBuffer.hpp"
namespace qrcodegen {
BitBuffer::BitBuffer()
: std::vector<bool>() {}
void BitBuffer::appendBits(std::uint32_t val, int len) {
if (len < 0 || len > 31 || val >> len != 0)
throw std::domain_error("Value out of range");
for (int i = len - 1; i >= 0; i--) // Append bit by bit
this->push_back(((val >> i) & 1) != 0);
}
}

52
3rdparty/qrcode/BitBuffer.hpp

@ -0,0 +1,52 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#pragma once
#include <cstdint>
#include <vector>
namespace qrcodegen {
/*
* An appendable sequence of bits (0s and 1s). Mainly used by QrSegment.
*/
class BitBuffer final : public std::vector<bool> {
/*---- Constructor ----*/
// Creates an empty bit buffer (length 0).
public: BitBuffer();
/*---- Method ----*/
// Appends the given number of low-order bits of the given value
// to this buffer. Requires 0 <= len <= 31 and val < 2^len.
public: void appendBits(std::uint32_t val, int len);
};
}

620
3rdparty/qrcode/QrCode.cpp

@ -0,0 +1,620 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <algorithm>
#include <climits>
#include <cstddef>
#include <cstdlib>
#include <sstream>
#include <stdexcept>
#include <utility>
#include "BitBuffer.hpp"
#include "QrCode.hpp"
using std::int8_t;
using std::uint8_t;
using std::size_t;
using std::vector;
namespace qrcodegen {
int QrCode::getFormatBits(Ecc ecl) {
switch (ecl) {
case Ecc::LOW : return 1;
case Ecc::MEDIUM : return 0;
case Ecc::QUARTILE: return 3;
case Ecc::HIGH : return 2;
default: throw std::logic_error("Assertion error");
}
}
QrCode QrCode::encodeText(const char *text, Ecc ecl) {
vector<QrSegment> segs = QrSegment::makeSegments(text);
return encodeSegments(segs, ecl);
}
QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
vector<QrSegment> segs{QrSegment::makeBytes(data)};
return encodeSegments(segs, ecl);
}
QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
int minVersion, int maxVersion, int mask, bool boostEcl) {
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
throw std::invalid_argument("Invalid value");
// Find the minimal version number to use
int version, dataUsedBits;
for (version = minVersion; ; version++) {
int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available
dataUsedBits = QrSegment::getTotalBits(segs, version);
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data
throw std::length_error("Data too long");
}
if (dataUsedBits == -1)
throw std::logic_error("Assertion error");
// Increase the error correction level while the data still fits in the current version number
for (Ecc newEcl : vector<Ecc>{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { // From low to high
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
// Concatenate all segments to create the data bit string
BitBuffer bb;
for (const QrSegment &seg : segs) {
bb.appendBits(seg.getMode().getModeBits(), 4);
bb.appendBits(seg.getNumChars(), seg.getMode().numCharCountBits(version));
bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
}
if (bb.size() != static_cast<unsigned int>(dataUsedBits))
throw std::logic_error("Assertion error");
// Add terminator and pad up to a byte if applicable
size_t dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
if (bb.size() > dataCapacityBits)
throw std::logic_error("Assertion error");
bb.appendBits(0, std::min<size_t>(4, dataCapacityBits - bb.size()));
bb.appendBits(0, (8 - bb.size() % 8) % 8);
if (bb.size() % 8 != 0)
throw std::logic_error("Assertion error");
// Pad with alternating bytes until data capacity is reached
for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
// Pack bits into bytes in big endian
vector<uint8_t> dataCodewords(bb.size() / 8);
for (size_t i = 0; i < bb.size(); i++)
dataCodewords[i >> 3] |= (bb.at(i) ? 1 : 0) << (7 - (i & 7));
// Create the QR Code object
return QrCode(version, ecl, dataCodewords, mask);
}
QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int mask) :
// Initialize fields and check arguments
version(ver),
errorCorrectionLevel(ecl) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw std::domain_error("Version value out of range");
if (mask < -1 || mask > 7)
throw std::domain_error("Mask value out of range");
size = ver * 4 + 17;
modules = vector<vector<bool> >(size, vector<bool>(size)); // Initially all white
isFunction = vector<vector<bool> >(size, vector<bool>(size));
// Compute ECC, draw modules, do masking
drawFunctionPatterns();
const vector<uint8_t> allCodewords = addEccAndInterleave(dataCodewords);
drawCodewords(allCodewords);
this->mask = handleConstructorMasking(mask);
isFunction.clear();
isFunction.shrink_to_fit();
}
int QrCode::getVersion() const {
return version;
}
int QrCode::getSize() const {
return size;
}
QrCode::Ecc QrCode::getErrorCorrectionLevel() const {
return errorCorrectionLevel;
}
int QrCode::getMask() const {
return mask;
}
bool QrCode::getModule(int x, int y) const {
return 0 <= x && x < size && 0 <= y && y < size && module(x, y);
}
std::string QrCode::toSvgString(int border) const {
if (border < 0)
throw std::domain_error("Border must be non-negative");
if (border > INT_MAX / 2 || border * 2 > INT_MAX - size)
throw std::overflow_error("Border too large");
std::ostringstream sb;
sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
sb << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n";
sb << "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewBox=\"0 0 ";
sb << (size + border * 2) << " " << (size + border * 2) << "\" stroke=\"none\">\n";
sb << "\t<rect width=\"100%\" height=\"100%\" fill=\"#FFFFFF\"/>\n";
sb << "\t<path d=\"";
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
if (getModule(x, y)) {
if (x != 0 || y != 0)
sb << " ";
sb << "M" << (x + border) << "," << (y + border) << "h1v1h-1z";
}
}
}
sb << "\" fill=\"#000000\"/>\n";
sb << "</svg>\n";
return sb.str();
}
void QrCode::drawFunctionPatterns() {
// Draw horizontal and vertical timing patterns
for (int i = 0; i < size; i++) {
setFunctionModule(6, i, i % 2 == 0);
setFunctionModule(i, 6, i % 2 == 0);
}
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
drawFinderPattern(3, 3);
drawFinderPattern(size - 4, 3);
drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns
const vector<int> alignPatPos = getAlignmentPatternPositions();
int numAlign = alignPatPos.size();
for (int i = 0; i < numAlign; i++) {
for (int j = 0; j < numAlign; j++) {
// Don't draw on the three finder corners
if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j));
}
}
// Draw configuration data
drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
drawVersion();
}
void QrCode::drawFormatBits(int mask) {
// Calculate error correction code and pack bits
int data = getFormatBits(errorCorrectionLevel) << 3 | mask; // errCorrLvl is uint2, mask is uint3
int rem = data;
for (int i = 0; i < 10; i++)
rem = (rem << 1) ^ ((rem >> 9) * 0x537);
int bits = (data << 10 | rem) ^ 0x5412; // uint15
if (bits >> 15 != 0)
throw std::logic_error("Assertion error");
// Draw first copy
for (int i = 0; i <= 5; i++)
setFunctionModule(8, i, getBit(bits, i));
setFunctionModule(8, 7, getBit(bits, 6));
setFunctionModule(8, 8, getBit(bits, 7));
setFunctionModule(7, 8, getBit(bits, 8));
for (int i = 9; i < 15; i++)
setFunctionModule(14 - i, 8, getBit(bits, i));
// Draw second copy
for (int i = 0; i <= 7; i++)
setFunctionModule(size - 1 - i, 8, getBit(bits, i));
for (int i = 8; i < 15; i++)
setFunctionModule(8, size - 15 + i, getBit(bits, i));
setFunctionModule(8, size - 8, true); // Always black
}
void QrCode::drawVersion() {
if (version < 7)
return;
// Calculate error correction code and pack bits
int rem = version; // version is uint6, in the range [7, 40]
for (int i = 0; i < 12; i++)
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
long bits = (long)version << 12 | rem; // uint18
if (bits >> 18 != 0)
throw std::logic_error("Assertion error");
// Draw two copies
for (int i = 0; i < 18; i++) {
bool bit = getBit(bits, i);
int a = size - 11 + i % 3;
int b = i / 3;
setFunctionModule(a, b, bit);
setFunctionModule(b, a, bit);
}
}
void QrCode::drawFinderPattern(int x, int y) {
for (int dy = -4; dy <= 4; dy++) {
for (int dx = -4; dx <= 4; dx++) {
int dist = std::max(std::abs(dx), std::abs(dy)); // Chebyshev/infinity norm
int xx = x + dx, yy = y + dy;
if (0 <= xx && xx < size && 0 <= yy && yy < size)
setFunctionModule(xx, yy, dist != 2 && dist != 4);
}
}
}
void QrCode::drawAlignmentPattern(int x, int y) {
for (int dy = -2; dy <= 2; dy++) {
for (int dx = -2; dx <= 2; dx++)
setFunctionModule(x + dx, y + dy, std::max(std::abs(dx), std::abs(dy)) != 1);
}
}
void QrCode::setFunctionModule(int x, int y, bool isBlack) {
modules.at(y).at(x) = isBlack;
isFunction.at(y).at(x) = true;
}
bool QrCode::module(int x, int y) const {
return modules.at(y).at(x);
}
vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel)))
throw std::invalid_argument("Invalid argument");
// Calculate parameter numbers
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
int blockEccLen = ECC_CODEWORDS_PER_BLOCK [static_cast<int>(errorCorrectionLevel)][version];
int rawCodewords = getNumRawDataModules(version) / 8;
int numShortBlocks = numBlocks - rawCodewords % numBlocks;
int shortBlockLen = rawCodewords / numBlocks;
// Split data into blocks and append ECC to each block
vector<vector<uint8_t> > blocks;
const ReedSolomonGenerator rs(blockEccLen);
for (int i = 0, k = 0; i < numBlocks; i++) {
vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
k += dat.size();
const vector<uint8_t> ecc = rs.getRemainder(dat);
if (i < numShortBlocks)
dat.push_back(0);
dat.insert(dat.end(), ecc.cbegin(), ecc.cend());
blocks.push_back(std::move(dat));
}
// Interleave (not concatenate) the bytes from every block into a single sequence
vector<uint8_t> result;
for (size_t i = 0; i < blocks.at(0).size(); i++) {
for (size_t j = 0; j < blocks.size(); j++) {
// Skip the padding byte in short blocks
if (i != static_cast<unsigned int>(shortBlockLen - blockEccLen) || j >= static_cast<unsigned int>(numShortBlocks))
result.push_back(blocks.at(j).at(i));
}
}
if (result.size() != static_cast<unsigned int>(rawCodewords))
throw std::logic_error("Assertion error");
return result;
}
void QrCode::drawCodewords(const vector<uint8_t> &data) {
if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8))
throw std::invalid_argument("Invalid argument");
size_t i = 0; // Bit index into the data
// Do the funny zigzag scan
for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
if (right == 6)
right = 5;
for (int vert = 0; vert < size; vert++) { // Vertical counter
for (int j = 0; j < 2; j++) {
int x = right - j; // Actual x coordinate
bool upward = ((right + 1) & 2) == 0;
int y = upward ? size - 1 - vert : vert; // Actual y coordinate
if (!isFunction.at(y).at(x) && i < data.size() * 8) {
modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
i++;
}
// If this QR Code has any remainder bits (0 to 7), they were assigned as
// 0/false/white by the constructor and are left unchanged by this method
}
}
}
if (i != data.size() * 8)
throw std::logic_error("Assertion error");
}
void QrCode::applyMask(int mask) {
if (mask < 0 || mask > 7)
throw std::domain_error("Mask value out of range");
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
bool invert;
switch (mask) {
case 0: invert = (x + y) % 2 == 0; break;
case 1: invert = y % 2 == 0; break;
case 2: invert = x % 3 == 0; break;
case 3: invert = (x + y) % 3 == 0; break;
case 4: invert = (x / 3 + y / 2) % 2 == 0; break;
case 5: invert = x * y % 2 + x * y % 3 == 0; break;
case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
default: throw std::logic_error("Assertion error");
}
modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x));
}
}
}
int QrCode::handleConstructorMasking(int mask) {
if (mask == -1) { // Automatically choose best mask
long minPenalty = LONG_MAX;
for (int i = 0; i < 8; i++) {
drawFormatBits(i);
applyMask(i);
long penalty = getPenaltyScore();
if (penalty < minPenalty) {
mask = i;
minPenalty = penalty;
}
applyMask(i); // Undoes the mask due to XOR
}
}
if (mask < 0 || mask > 7)
throw std::logic_error("Assertion error");
drawFormatBits(mask); // Overwrite old format bits
applyMask(mask); // Apply the final choice of mask
return mask; // The caller shall assign this value to the final-declared field
}
long QrCode::getPenaltyScore() const {
long result = 0;
// Adjacent modules in row having same color
for (int y = 0; y < size; y++) {
bool colorX = false;
for (int x = 0, runX = -1; x < size; x++) {
if (x == 0 || module(x, y) != colorX) {
colorX = module(x, y);
runX = 1;
} else {
runX++;
if (runX == 5)
result += PENALTY_N1;
else if (runX > 5)
result++;
}
}
}
// Adjacent modules in column having same color
for (int x = 0; x < size; x++) {
bool colorY = false;
for (int y = 0, runY = -1; y < size; y++) {
if (y == 0 || module(x, y) != colorY) {
colorY = module(x, y);
runY = 1;
} else {
runY++;
if (runY == 5)
result += PENALTY_N1;
else if (runY > 5)
result++;
}
}
}
// 2*2 blocks of modules having same color
for (int y = 0; y < size - 1; y++) {
for (int x = 0; x < size - 1; x++) {
bool color = module(x, y);
if ( color == module(x + 1, y) &&
color == module(x, y + 1) &&
color == module(x + 1, y + 1))
result += PENALTY_N2;
}
}
// Finder-like pattern in rows
for (int y = 0; y < size; y++) {
for (int x = 0, bits = 0; x < size; x++) {
bits = ((bits << 1) & 0x7FF) | (module(x, y) ? 1 : 0);
if (x >= 10 && (bits == 0x05D || bits == 0x5D0)) // Needs 11 bits accumulated
result += PENALTY_N3;
}
}
// Finder-like pattern in columns
for (int x = 0; x < size; x++) {
for (int y = 0, bits = 0; y < size; y++) {
bits = ((bits << 1) & 0x7FF) | (module(x, y) ? 1 : 0);
if (y >= 10 && (bits == 0x05D || bits == 0x5D0)) // Needs 11 bits accumulated
result += PENALTY_N3;
}
}
// Balance of black and white modules
int black = 0;
for (const vector<bool> &row : modules) {
for (bool color : row) {
if (color)
black++;
}
}
int total = size * size; // Note that size is odd, so black/total != 1/2
// Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)%
int k = static_cast<int>((std::abs(black * 20L - total * 10L) + total - 1) / total) - 1;
result += k * PENALTY_N4;
return result;
}
vector<int> QrCode::getAlignmentPatternPositions() const {
if (version == 1)
return vector<int>();
else {
int numAlign = version / 7 + 2;
int step = (version == 32) ? 26 :
(version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
vector<int> result;
for (int i = 0, pos = size - 7; i < numAlign - 1; i++, pos -= step)
result.insert(result.begin(), pos);
result.insert(result.begin(), 6);
return result;
}
}
int QrCode::getNumRawDataModules(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION)
throw std::domain_error("Version number out of range");
int result = (16 * ver + 128) * ver + 64;
if (ver >= 2) {
int numAlign = ver / 7 + 2;
result -= (25 * numAlign - 10) * numAlign - 55;
if (ver >= 7)
result -= 36;
}
return result;
}
int QrCode::getNumDataCodewords(int ver, Ecc ecl) {
return getNumRawDataModules(ver) / 8
- ECC_CODEWORDS_PER_BLOCK [static_cast<int>(ecl)][ver]
* NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(ecl)][ver];
}
bool QrCode::getBit(long x, int i) {
return ((x >> i) & 1) != 0;
}
/*---- Tables of constants ----*/
const int QrCode::PENALTY_N1 = 3;
const int QrCode::PENALTY_N2 = 3;
const int QrCode::PENALTY_N3 = 40;
const int QrCode::PENALTY_N4 = 10;
const int8_t QrCode::ECC_CODEWORDS_PER_BLOCK[4][41] = {
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low
{-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium
{-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile
{-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High
};
const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
// Version: (note that index 0 is for padding, and is set to an illegal value)
//0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
{-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low
{-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium
{-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile
{-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High
};
QrCode::ReedSolomonGenerator::ReedSolomonGenerator(int degree) :
coefficients() {
if (degree < 1 || degree > 255)
throw std::domain_error("Degree out of range");
// Start with the monomial x^0
coefficients.resize(degree);
coefficients.at(degree - 1) = 1;
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// drop the highest term, and store the rest of the coefficients in order of descending powers.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
uint8_t root = 1;
for (int i = 0; i < degree; i++) {
// Multiply the current product by (x - r^i)
for (size_t j = 0; j < coefficients.size(); j++) {
coefficients.at(j) = multiply(coefficients.at(j), root);
if (j + 1 < coefficients.size())
coefficients.at(j) ^= coefficients.at(j + 1);
}
root = multiply(root, 0x02);
}
}
vector<uint8_t> QrCode::ReedSolomonGenerator::getRemainder(const vector<uint8_t> &data) const {
// Compute the remainder by performing polynomial division
vector<uint8_t> result(coefficients.size());
for (uint8_t b : data) {
uint8_t factor = b ^ result.at(0);
result.erase(result.begin());
result.push_back(0);
for (size_t j = 0; j < result.size(); j++)
result.at(j) ^= multiply(coefficients.at(j), factor);
}
return result;
}
uint8_t QrCode::ReedSolomonGenerator::multiply(uint8_t x, uint8_t y) {
// Russian peasant multiplication
int z = 0;
for (int i = 7; i >= 0; i--) {
z = (z << 1) ^ ((z >> 7) * 0x11D);
z ^= ((y >> i) & 1) * x;
}
if (z >> 8 != 0)
throw std::logic_error("Assertion error");
return static_cast<uint8_t>(z);
}
}

351
3rdparty/qrcode/QrCode.hpp

@ -0,0 +1,351 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "QrSegment.hpp"
namespace qrcodegen {
/*
* A QR Code symbol, which is a type of two-dimension barcode.
* Invented by Denso Wave and described in the ISO/IEC 18004 standard.
* Instances of this class represent an immutable square grid of black and white cells.
* The class provides static factory functions to create a QR Code from text or binary data.
* The class covers the QR Code Model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
*
* Ways to create a QR Code object:
* - High level: Take the payload data and call QrCode::encodeText() or QrCode::encodeBinary().
* - Mid level: Custom-make the list of segments and call QrCode::encodeSegments().
* - Low level: Custom-make the array of data codeword bytes (including
* segment headers and final padding, excluding error correction codewords),
* supply the appropriate version number, and call the QrCode() constructor.
* (Note that all ways require supplying the desired error correction level.)
*/
class QrCode final {
/*---- Public helper enumeration ----*/
/*
* The error correction level in a QR Code symbol.
*/
public: enum class Ecc {
LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords
MEDIUM , // The QR Code can tolerate about 15% erroneous codewords
QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
HIGH , // The QR Code can tolerate about 30% erroneous codewords
};
// Returns a value in the range 0 to 3 (unsigned 2-bit integer).
private: static int getFormatBits(Ecc ecl);
/*---- Static factory functions (high level) ----*/
/*
* Returns a QR Code representing the given Unicode text string at the given error correction level.
* As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer
* UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible
* QR Code version is automatically chosen for the output. The ECC level of the result may be higher than
* the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeText(const char *text, Ecc ecl);
/*
* Returns a QR Code representing the given binary data at the given error correction level.
* This function always encodes using the binary segment mode, not any text mode. The maximum number of
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
* The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeBinary(const std::vector<std::uint8_t> &data, Ecc ecl);
/*---- Static factory functions (mid level) ----*/
/*
* Returns a QR Code representing the given segments with the given encoding parameters.
* The smallest possible QR Code version within the given range is automatically
* chosen for the output. Iff boostEcl is true, then the ECC level of the result
* may be higher than the ecl argument if it can be done without increasing the
* version. The mask number is either between 0 to 7 (inclusive) to force that
* mask, or -1 to automatically choose an appropriate mask (which may be slow).
* This function allows the user to create a custom sequence of segments that switches
* between modes (such as alphanumeric and byte) to encode text in less space.
* This is a mid-level API; the high-level API is encodeText() and encodeBinary().
*/
public: static QrCode encodeSegments(const std::vector<QrSegment> &segs, Ecc ecl,
int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters
/*---- Instance fields ----*/
// Immutable scalar parameters:
/* The version number of this QR Code, which is between 1 and 40 (inclusive).
* This determines the size of this barcode. */
private: int version;
/* The width and height of this QR Code, measured in modules, between
* 21 and 177 (inclusive). This is equal to version * 4 + 17. */
private: int size;
/* The error correction level used in this QR Code. */
private: Ecc errorCorrectionLevel;
/* The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
* Even if a QR Code is created with automatic masking requested (mask = -1),
* the resulting object still has a mask value between 0 and 7. */
private: int mask;
// Private grids of modules/pixels, with dimensions of size*size:
// The modules of this QR Code (false = white, true = black).
// Immutable after constructor finishes. Accessed through getModule().
private: std::vector<std::vector<bool> > modules;
// Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
private: std::vector<std::vector<bool> > isFunction;
/*---- Constructor (low level) ----*/
/*
* Creates a new QR Code with the given version number,
* error correction level, data codeword bytes, and mask number.
* This is a low-level API that most users should not use directly.
* A mid-level API is the encodeSegments() function.
*/
public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int mask);
/*---- Public instance methods ----*/
/*
* Returns this QR Code's version, in the range [1, 40].
*/
public: int getVersion() const;
/*
* Returns this QR Code's size, in the range [21, 177].
*/
public: int getSize() const;
/*
* Returns this QR Code's error correction level.
*/
public: Ecc getErrorCorrectionLevel() const;
/*
* Returns this QR Code's mask, in the range [0, 7].
*/
public: int getMask() const;
/*
* Returns the color of the module (pixel) at the given coordinates, which is false
* for white or true for black. The top left corner has the coordinates (x=0, y=0).
* If the given coordinates are out of bounds, then false (white) is returned.
*/
public: bool getModule(int x, int y) const;
/*
* Returns a string of SVG code for an image depicting this QR Code, with the given number
* of border modules. The string always uses Unix newlines (\n), regardless of the platform.
*/
public: std::string toSvgString(int border) const;
/*---- Private helper methods for constructor: Drawing function modules ----*/
// Reads this object's version field, and draws and marks all function modules.
private: void drawFunctionPatterns();
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
private: void drawFormatBits(int mask);
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field, iff 7 <= version <= 40.
private: void drawVersion();
// Draws a 9*9 finder pattern including the border separator,
// with the center module at (x, y). Modules can be out of bounds.
private: void drawFinderPattern(int x, int y);
// Draws a 5*5 alignment pattern, with the center module
// at (x, y). All modules must be in bounds.
private: void drawAlignmentPattern(int x, int y);
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in bounds.
private: void setFunctionModule(int x, int y, bool isBlack);
// Returns the color of the module at the given coordinates, which must be in range.
private: bool module(int x, int y) const;
/*---- Private helper methods for constructor: Codewords and masking ----*/
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
private: std::vector<std::uint8_t> addEccAndInterleave(const std::vector<std::uint8_t> &data) const;
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code. Function modules need to be marked off before this is called.
private: void drawCodewords(const std::vector<std::uint8_t> &data);
// XORs the codeword modules in this QR Code with the given mask pattern.
// The function modules must be marked and the codeword bits must be drawn
// before masking. Due to the arithmetic of XOR, calling applyMask() with
// the same mask value a second time will undo the mask. A final well-formed
// QR Code needs exactly one (not zero, two, etc.) mask applied.
private: void applyMask(int mask);
// A messy helper function for the constructors. This QR Code must be in an unmasked state when this
// method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed.
// This method applies and returns the actual mask chosen, from 0 to 7.
private: int handleConstructorMasking(int mask);
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
private: long getPenaltyScore() const;
/*---- Private helper functions ----*/
// Returns an ascending list of positions of alignment patterns for this version number.
// Each position is in the range [0,177), and are used on both the x and y axes.
// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes.
private: std::vector<int> getAlignmentPatternPositions() const;
// Returns the number of data bits that can be stored in a QR Code of the given version number, after
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
private: static int getNumRawDataModules(int ver);
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
// QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
private: static int getNumDataCodewords(int ver, Ecc ecl);
// Returns true iff the i'th bit of x is set to 1.
private: static bool getBit(long x, int i);
/*---- Constants and tables ----*/
// The minimum version number supported in the QR Code Model 2 standard.
public: static constexpr int MIN_VERSION = 1;
// The maximum version number supported in the QR Code Model 2 standard.
public: static constexpr int MAX_VERSION = 40;
// For use in getPenaltyScore(), when evaluating which mask is best.
private: static const int PENALTY_N1;
private: static const int PENALTY_N2;
private: static const int PENALTY_N3;
private: static const int PENALTY_N4;
private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
/*---- Private helper class ----*/
/*
* Computes the Reed-Solomon error correction codewords for a sequence of data codewords
* at a given degree. Objects are immutable, and the state only depends on the degree.
* This class exists because each data block in a QR Code shares the same the divisor polynomial.
*/
private: class ReedSolomonGenerator final {
/*-- Immutable field --*/
// Coefficients of the divisor polynomial, stored from highest to lowest power, excluding the leading term which
// is always 1. For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
private: std::vector<std::uint8_t> coefficients;
/*-- Constructor --*/
/*
* Creates a Reed-Solomon ECC generator for the given degree. This could be implemented
* as a lookup table over all possible parameter values, instead of as an algorithm.
*/
public: explicit ReedSolomonGenerator(int degree);
/*-- Method --*/
/*
* Computes and returns the Reed-Solomon error correction codewords for the given
* sequence of data codewords. The returned object is always a new byte array.
* This method does not alter this object's state (because it is immutable).
*/
public: std::vector<std::uint8_t> getRemainder(const std::vector<std::uint8_t> &data) const;
/*-- Static function --*/
// Returns the product of the two given field elements modulo GF(2^8/0x11D).
// All inputs are valid. This could be implemented as a 256*256 lookup table.
private: static std::uint8_t multiply(std::uint8_t x, std::uint8_t y);
};
};
}

225
3rdparty/qrcode/QrSegment.cpp

@ -0,0 +1,225 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#include <climits>
#include <cstring>
#include <stdexcept>
#include <utility>
#include "QrSegment.hpp"
using std::uint8_t;
using std::vector;
namespace qrcodegen {
QrSegment::Mode::Mode(int mode, int cc0, int cc1, int cc2) :
modeBits(mode) {
numBitsCharCount[0] = cc0;
numBitsCharCount[1] = cc1;
numBitsCharCount[2] = cc2;
}
int QrSegment::Mode::getModeBits() const {
return modeBits;
}
int QrSegment::Mode::numCharCountBits(int ver) const {
return numBitsCharCount[(ver + 7) / 17];
}
const QrSegment::Mode QrSegment::Mode::NUMERIC (0x1, 10, 12, 14);
const QrSegment::Mode QrSegment::Mode::ALPHANUMERIC(0x2, 9, 11, 13);
const QrSegment::Mode QrSegment::Mode::BYTE (0x4, 8, 16, 16);
const QrSegment::Mode QrSegment::Mode::KANJI (0x8, 8, 10, 12);
const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0);
QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
if (data.size() > static_cast<unsigned int>(INT_MAX))
throw std::length_error("Data too long");
BitBuffer bb;
for (uint8_t b : data)
bb.appendBits(b, 8);
return QrSegment(Mode::BYTE, static_cast<int>(data.size()), std::move(bb));
}
QrSegment QrSegment::makeNumeric(const char *digits) {
BitBuffer bb;
int accumData = 0;
int accumCount = 0;
int charCount = 0;
for (; *digits != '\0'; digits++, charCount++) {
char c = *digits;
if (c < '0' || c > '9')
throw std::domain_error("String contains non-numeric characters");
accumData = accumData * 10 + (c - '0');
accumCount++;
if (accumCount == 3) {
bb.appendBits(accumData, 10);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 or 2 digits remaining
bb.appendBits(accumData, accumCount * 3 + 1);
return QrSegment(Mode::NUMERIC, charCount, std::move(bb));
}
QrSegment QrSegment::makeAlphanumeric(const char *text) {
BitBuffer bb;
int accumData = 0;
int accumCount = 0;
int charCount = 0;
for (; *text != '\0'; text++, charCount++) {
const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
if (temp == nullptr)
throw std::domain_error("String contains unencodable characters in alphanumeric mode");
accumData = accumData * 45 + (temp - ALPHANUMERIC_CHARSET);
accumCount++;
if (accumCount == 2) {
bb.appendBits(accumData, 11);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 character remaining
bb.appendBits(accumData, 6);
return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb));
}
vector<QrSegment> QrSegment::makeSegments(const char *text) {
// Select the most efficient segment encoding automatically
vector<QrSegment> result;
if (*text == '\0'); // Leave result empty
else if (isNumeric(text))
result.push_back(makeNumeric(text));
else if (isAlphanumeric(text))
result.push_back(makeAlphanumeric(text));
else {
vector<uint8_t> bytes;
for (; *text != '\0'; text++)
bytes.push_back(static_cast<uint8_t>(*text));
result.push_back(makeBytes(bytes));
}
return result;
}
QrSegment QrSegment::makeEci(long assignVal) {
BitBuffer bb;
if (assignVal < 0)
throw std::domain_error("ECI assignment value out of range");
else if (assignVal < (1 << 7))
bb.appendBits(assignVal, 8);
else if (assignVal < (1 << 14)) {
bb.appendBits(2, 2);
bb.appendBits(assignVal, 14);
} else if (assignVal < 1000000L) {
bb.appendBits(6, 3);
bb.appendBits(assignVal, 21);
} else
throw std::domain_error("ECI assignment value out of range");
return QrSegment(Mode::ECI, 0, std::move(bb));
}
QrSegment::QrSegment(Mode md, int numCh, const std::vector<bool> &dt) :
mode(md),
numChars(numCh),
data(dt) {
if (numCh < 0)
throw std::domain_error("Invalid value");
}
QrSegment::QrSegment(Mode md, int numCh, std::vector<bool> &&dt) :
mode(md),
numChars(numCh),
data(std::move(dt)) {
if (numCh < 0)
throw std::domain_error("Invalid value");
}
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
int result = 0;
for (const QrSegment &seg : segs) {
int ccbits = seg.mode.numCharCountBits(version);
if (seg.numChars >= (1L << ccbits))
return -1; // The segment's length doesn't fit the field's bit width
if (4 + ccbits > INT_MAX - result)
return -1; // The sum will overflow an int type
result += 4 + ccbits;
if (seg.data.size() > static_cast<unsigned int>(INT_MAX - result))
return -1; // The sum will overflow an int type
result += static_cast<int>(seg.data.size());
}
return result;
}
bool QrSegment::isAlphanumeric(const char *text) {
for (; *text != '\0'; text++) {
if (std::strchr(ALPHANUMERIC_CHARSET, *text) == nullptr)
return false;
}
return true;
}
bool QrSegment::isNumeric(const char *text) {
for (; *text != '\0'; text++) {
char c = *text;
if (c < '0' || c > '9')
return false;
}
return true;
}
QrSegment::Mode QrSegment::getMode() const {
return mode;
}
int QrSegment::getNumChars() const {
return numChars;
}
const std::vector<bool> &QrSegment::getData() const {
return data;
}
const char *QrSegment::ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
}

216
3rdparty/qrcode/QrSegment.hpp

@ -0,0 +1,216 @@
/*
* QR Code generator library (C++)
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* - The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* - The Software is provided "as is", without warranty of any kind, express or
* implied, including but not limited to the warranties of merchantability,
* fitness for a particular purpose and noninfringement. In no event shall the
* authors or copyright holders be liable for any claim, damages or other
* liability, whether in an action of contract, tort or otherwise, arising from,
* out of or in connection with the Software or the use or other dealings in the
* Software.
*/
#pragma once
#include <cstdint>
#include <vector>
#include "BitBuffer.hpp"
namespace qrcodegen {
/*
* A segment of character/binary/control data in a QR Code symbol.
* Instances of this class are immutable.
* The mid-level way to create a segment is to take the payload data
* and call a static factory function such as QrSegment::makeNumeric().
* The low-level way to create a segment is to custom-make the bit buffer
* and call the QrSegment() constructor with appropriate values.
* This segment class imposes no length restrictions, but QR Codes have restrictions.
* Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
*/
class QrSegment final {
/*---- Public helper enumeration ----*/
/*
* Describes how a segment's data bits are interpreted. Immutable.
*/
public: class Mode final {
/*-- Constants --*/
public: static const Mode NUMERIC;
public: static const Mode ALPHANUMERIC;
public: static const Mode BYTE;
public: static const Mode KANJI;
public: static const Mode ECI;
/*-- Fields --*/
// The mode indicator bits, which is a uint4 value (range 0 to 15).
private: int modeBits;
// Number of character count bits for three different version ranges.
private: int numBitsCharCount[3];
/*-- Constructor --*/
private: Mode(int mode, int cc0, int cc1, int cc2);
/*-- Methods --*/
/*
* (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15).
*/
public: int getModeBits() const;
/*
* (Package-private) Returns the bit width of the character count field for a segment in
* this mode in a QR Code at the given version number. The result is in the range [0, 16].
*/
public: int numCharCountBits(int ver) const;
};
/*---- Static factory functions (mid level) ----*/
/*
* Returns a segment representing the given binary data encoded in
* byte mode. All input byte vectors are acceptable. Any text string
* can be converted to UTF-8 bytes and encoded as a byte mode segment.
*/
public: static QrSegment makeBytes(const std::vector<std::uint8_t> &data);
/*
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
*/
public: static QrSegment makeNumeric(const char *digits);
/*
* Returns a segment representing the given text string encoded in alphanumeric mode.
* The characters allowed are: 0 to 9, A to Z (uppercase only), space,
* dollar, percent, asterisk, plus, hyphen, period, slash, colon.
*/
public: static QrSegment makeAlphanumeric(const char *text);
/*
* Returns a list of zero or more segments to represent the given text string. The result
* may use various segment modes and switch modes to optimize the length of the bit stream.
*/
public: static std::vector<QrSegment> makeSegments(const char *text);
/*
* Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the given assignment value.
*/
public: static QrSegment makeEci(long assignVal);
/*---- Public static helper functions ----*/
/*
* Tests whether the given string can be encoded as a segment in alphanumeric mode.
* A string is encodable iff each character is in the following set: 0 to 9, A to Z
* (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
*/
public: static bool isAlphanumeric(const char *text);
/*
* Tests whether the given string can be encoded as a segment in numeric mode.
* A string is encodable iff each character is in the range 0 to 9.
*/
public: static bool isNumeric(const char *text);
/*---- Instance fields ----*/
/* The mode indicator of this segment. Accessed through getMode(). */
private: Mode mode;
/* The length of this segment's unencoded data. Measured in characters for
* numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
* Always zero or positive. Not the same as the data's bit length.
* Accessed through getNumChars(). */
private: int numChars;
/* The data bits of this segment. Accessed through getData(). */
private: std::vector<bool> data;
/*---- Constructors (low level) ----*/
/*
* Creates a new QR Code segment with the given attributes and data.
* The character count (numCh) must agree with the mode and the bit buffer length,
* but the constraint isn't checked. The given bit buffer is copied and stored.
*/
public: QrSegment(Mode md, int numCh, const std::vector<bool> &dt);
/*
* Creates a new QR Code segment with the given parameters and data.
* The character count (numCh) must agree with the mode and the bit buffer length,
* but the constraint isn't checked. The given bit buffer is moved and stored.
*/
public: QrSegment(Mode md, int numCh, std::vector<bool> &&dt);
/*---- Methods ----*/
/*
* Returns the mode field of this segment.
*/
public: Mode getMode() const;
/*
* Returns the character count field of this segment.
*/
public: int getNumChars() const;
/*
* Returns the data bits of this segment.
*/
public: const std::vector<bool> &getData() const;
// (Package-private) Calculates the number of bits needed to encode the given segments at
// the given version. Returns a non-negative number if successful. Otherwise returns -1 if a
// segment has too many characters to fit its length field, or the total bits exceeds INT_MAX.
public: static int getTotalBits(const std::vector<QrSegment> &segs, int version);
/*---- Private constant ----*/
/* The set of all legal characters in alphanumeric mode, where
* each character value maps to the index in the string. */
private: static const char *ALPHANUMERIC_CHARSET;
};
}

BIN
Ubuntu-R.ttf

Binary file not shown.

87
about.ui

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>about</class>
<widget class="QDialog" name="about">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>497</width>
<height>448</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Copyright (c) 2018 Aditya Kulkarni. (MIT License)&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Special thanks to:&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;JSON for Modern C++ : &lt;a href=&quot;https://nlohmann.github.io/json/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;https://nlohmann.github.io/json/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;QR Code generator library Nayuki : &lt;a href=&quot;https://www.nayuki.io/page/qr-code-generator-library&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;https://www.nayuki.io/page/qr-code-ge…&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Made with QT : &lt;a href=&quot;https://www.qt.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#007af4;&quot;&gt;https://www.qt.io/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;LICENSE:&lt;/p&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:&lt;/p&gt;
&lt;ul style=&quot;margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;&quot;&gt;&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;/li&gt;
&lt;li style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The Software is provided &amp;quot;as is&amp;quot;, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.&lt;/li&gt;&lt;/ul&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>about</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>about</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

5
application.qrc

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/fonts">
<file>Ubuntu-R.ttf</file>
</qresource>
</RCC>

92
balancestablemodel.cpp

@ -0,0 +1,92 @@
#include "balancestablemodel.h"
BalancesTableModel::BalancesTableModel(
QObject *parent,
const QMap<QString, double>* balances,
const QList<UnspentOutput>* outputs)
: QAbstractTableModel(parent)
{
// Copy over the utxos for our use
utxos = new QList<UnspentOutput>();
// This is a QList deep copy.
*utxos = *outputs;
// Process the address balances into a list
modeldata = new QList<std::tuple<QString, QString>>();
std::for_each(balances->constKeyValueBegin(), balances->constKeyValueEnd(), [=] (auto it) {
modeldata->push_back(std::make_tuple(it.first, QString::number(it.second, 'f')));
});
}
BalancesTableModel::~BalancesTableModel() {
delete modeldata;
delete utxos;
}
int BalancesTableModel::rowCount(const QModelIndex&) const
{
return modeldata->size();
}
int BalancesTableModel::columnCount(const QModelIndex&) const
{
return 2;
}
QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::TextAlignmentRole && index.column() == 1) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::ForegroundRole) {
// If any of the UTXOs for this address has zero confirmations, paint it in red
const auto& addr = std::get<0>(modeldata->at(index.row()));
for (auto utxo : *utxos) {
if (utxo.address == addr && utxo.confirmations == 0) {
QBrush b;
b.setColor(Qt::red);
return b;
}
}
// Else, just return the default brush
QBrush b;
b.setColor(Qt::black);
return b;
}
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return std::get<0>(modeldata->at(index.row()));
case 1: return QVariant(std::get<1>(modeldata->at(index.row())) % " ZEC");
}
}
return QVariant();
}
QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::TextAlignmentRole && section == 1) {
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
}
if (role == Qt::FontRole) {
QFont f;
f.setBold(true);
return f;
}
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
switch (section) {
case 0: return tr("Address");
case 1: return tr("Amount");
default: return QVariant();
}
}
return QVariant();
}

24
balancestablemodel.h

@ -0,0 +1,24 @@
#ifndef BALANCESTABLEMODEL_H
#define BALANCESTABLEMODEL_H
#include "unspentoutput.h"
#include "precompiled.h"
class BalancesTableModel : public QAbstractTableModel
{
public:
BalancesTableModel(QObject* parent, const QMap<QString, double>* balances, const QList<UnspentOutput>* outputs);
~BalancesTableModel();
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
QList<std::tuple<QString, QString>>* modeldata;
QList<UnspentOutput>* utxos;
};
#endif // BALANCESTABLEMODEL_H

139
confirm.ui

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>confirm</class>
<widget class="QDialog" name="confirm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>429</width>
<height>371</height>
</rect>
</property>
<property name="windowTitle">
<string>Confirm Transaction</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>From</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="sendFrom">
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="sendToAddrs">
<property name="title">
<string>To</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="Addr1">
<property name="text">
<string>TextLabel</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="Amt1">
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Fees: 0.0001 ZEC</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>confirm</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>confirm</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

23
main.cpp

@ -0,0 +1,23 @@
#include "mainwindow.h"
#include "precompiled.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setOrganizationName("adityapk");
QCoreApplication::setOrganizationDomain("adityapk.com");
QCoreApplication::setApplicationName("zcash-qt-wallet");
QApplication a(argc, argv);
#ifdef Q_OS_LINUX
QFontDatabase::addApplicationFont(":/fonts/Ubuntu-R.ttf");
qApp->setFont(QFont("Ubuntu", 11, QFont::Normal, false));
#endif
MainWindow w;
w.show();
return QApplication::exec();
}

275
mainwindow.cpp

@ -0,0 +1,275 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_about.h"
#include "ui_settings.h"
#include "rpc.h"
#include "balancestablemodel.h"
#include "settings.h"
#include "precompiled.h"
#include "ui_about.h"
using json = nlohmann::json;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Load settings
settings = new Settings();
// Status Bar
statusLabel = new QLabel();
ui->statusBar->addPermanentWidget(statusLabel);
statusIcon = new QLabel();
ui->statusBar->addPermanentWidget(statusIcon);
// Set up File -> Settings action
QObject::connect(ui->actionSettings, &QAction::triggered, [=]() {
QDialog settingsDialog(this);
Ui_Settings settings;
settings.setupUi(&settingsDialog);
QIntValidator validator(0, 65535);
settings.port->setValidator(&validator);
// Load previous values into the dialog
settings.hostname ->setText(this->getSettings()->getHost());
settings.port ->setText(this->getSettings()->getPort());
settings.rpcuser ->setText(this->getSettings()->getUsernamePassword().split(":")[0]);
settings.rpcpassword->setText(this->getSettings()->getUsernamePassword().split(":")[1]);
if (settingsDialog.exec() == QDialog::Accepted) {
// Save settings
QSettings s;
s.setValue("connection/host", settings.hostname->text());
s.setValue("connection/port", settings.port->text());
s.setValue("connection/rpcuser", settings.rpcuser->text());
s.setValue("connection/rpcpassword", settings.rpcpassword->text());
s.sync();
// Then refresh everything
this->getSettings()->refresh();
this->rpc->reloadConnectionInfo();
this->rpc->refresh();
};
});
// Set up exit action
QObject::connect(ui->actionExit, &QAction::triggered, [=] { this->close(); });
// Set up about action
QObject::connect(ui->actionAbout, &QAction::triggered, [=] () {
QDialog aboutDialog(this);
Ui_about about;
about.setupUi(&aboutDialog);
aboutDialog.exec();
});
// Initialize to the balances tab
ui->tabWidget->setCurrentIndex(0);
setupSendTab();
setupTransactionsTab();
setupRecieveTab();
setupBalancesTab();
rpc = new RPC(new QNetworkAccessManager(this), this);
rpc->refresh();
}
void MainWindow::setupBalancesTab() {
ui->unconfirmedWarning->setVisible(false);
// Setup context menu on balances tab
ui->balancesTable->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ui->balancesTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
QModelIndex index = ui->balancesTable->indexAt(pos);
if (index.row() < 0) return;
index = index.sibling(index.row(), 0);
QMenu menu(this);
menu.addAction("Copy Address", [=] () {
QClipboard *clipboard = QGuiApplication::clipboard();
clipboard->setText(ui->balancesTable->model()->data(index).toString());
});
menu.exec(ui->balancesTable->viewport()->mapToGlobal(pos));
});
}
void MainWindow::setupTransactionsTab() {
// Set up context menu on transactions tab
ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
QModelIndex index = ui->transactionsTable->indexAt(pos);
if (index.row() < 0) return;
QMenu menu(this);
menu.addAction("View txid", [=] () {
QMessageBox msg(this);
msg.setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
msg.setIcon(QMessageBox::Icon::Information);
msg.setWindowTitle("Transaction ID");
auto txModel = dynamic_cast<TxTableModel *>(ui->transactionsTable->model());
msg.setText("Transaction ID: \n\n" + txModel->getTxId(index.row()));
msg.exec();
});
menu.exec(ui->transactionsTable->viewport()->mapToGlobal(pos));
});
}
void MainWindow::setupRecieveTab() {
auto addNewTAddr = [=] () {
rpc->newTaddr([=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
// Just double make sure the T-address is still checked
if (ui->rdioTAddr->isChecked()) {
ui->listRecieveAddresses->insertItem(0, addr);
ui->listRecieveAddresses->setCurrentIndex(0);
ui->statusBar->showMessage("Created new recieving tAddr", 10 * 1000);
}
});
};
// Connect t-addr radio button
QObject::connect(ui->rdioTAddr, &QRadioButton::toggled, [=] (bool checked) {
// Whenever the T-address is selected, we generate a new address, because we don't
// want to reuse T-addrs
if (checked && this->rpc->getUTXOs() != nullptr) {
auto utxos = this->rpc->getUTXOs();
ui->listRecieveAddresses->clear();
std::for_each(utxos->begin(), utxos->end(), [=] (auto& utxo) {
auto addr = utxo.address;
if (addr.startsWith("t") && ui->listRecieveAddresses->findText(addr) < 0) {
ui->listRecieveAddresses->addItem(addr);
}
});
addNewTAddr();
}
});
auto addNewZaddr = [=] () {
rpc->newZaddr([=] (json reply) {
QString addr = QString::fromStdString(reply.get<json::string_t>());
// Make sure the RPC class reloads the Z-addrs for future use
rpc->refreshAddresses();
// Just double make sure the Z-address is still checked
if (ui->rdioZAddr->isChecked()) {
ui->listRecieveAddresses->insertItem(0, addr);
ui->listRecieveAddresses->setCurrentIndex(0);
ui->statusBar->showMessage("Created new zAddr", 10 * 1000);
}
});
};
auto addZAddrsToComboList = [=] (bool checked) {
if (checked && this->rpc->getAllZAddresses() != nullptr) {
auto addrs = this->rpc->getAllZAddresses();
ui->listRecieveAddresses->clear();
std::for_each(addrs->begin(), addrs->end(), [=] (auto addr) {
ui->listRecieveAddresses->addItem(addr);
});
// If z-addrs are empty, then create a new one.
if (addrs->isEmpty()) {
addNewZaddr();
}
}
};
QObject::connect(ui->rdioZAddr, &QRadioButton::toggled, addZAddrsToComboList);
// Explicitly get new address button.
QObject::connect(ui->btnRecieveNewAddr, &QPushButton::clicked, [=] () {
if (ui->rdioZAddr->isChecked()) {
addNewZaddr();
} else if (ui->rdioTAddr->isChecked()) {
addNewTAddr();
}
});
// Focus enter for the Recieve Tab
QObject::connect(ui->tabWidget, &QTabWidget::currentChanged, [=] (int tab) {
if (tab == 2) {
// Switched to recieve tab, so update everything.
// Set the radio button to "Z-Addr", which should update the Address combo
ui->rdioZAddr->setChecked(true);
// And then select the first one
ui->listRecieveAddresses->setCurrentIndex(0);
}
});
QObject::connect(ui->listRecieveAddresses,
QOverload<const QString &>::of(&QComboBox::currentIndexChanged), [=] (const QString& addr) {
if (addr.isEmpty()) {
// Draw empty stuff
ui->txtRecieve->clear();
ui->qrcodeDisplay->clear();
return;
}
ui->txtRecieve->setPlainText(addr);
QSize sz = ui->qrcodeDisplay->size();
QPixmap pm(sz);
pm.fill(Qt::white);
QPainter painter(&pm);
// NOTE: At this point you will use the API to get the encoding and format you want, instead of my hardcoded stuff:
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(addr.toUtf8().constData(), qrcodegen::QrCode::Ecc::LOW);
const int s = qr.getSize()>0?qr.getSize():1;
const double w = sz.width();
const double h = sz.height();
const double aspect = w/h;
const double size = ((aspect>1.0)?h:w);
const double scale = size/(s+2);
const double offset = (w - size) > 0 ? (w - size) / 2 : 0;
// NOTE: For performance reasons my implementation only draws the foreground parts in supplied color.
// It expects background to be prepared already (in white or whatever is preferred).
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(Qt::black));
for(int y=0; y<s; y++) {
for(int x=0; x<s; x++) {
const int color=qr.getModule(x, y); // 0 for white, 1 for black
if(0!=color) {
const double rx1=(x+1)*scale+ offset, ry1=(y+1)*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
ui->qrcodeDisplay->setPixmap(pm);
});
}
Settings* MainWindow::getSettings() {
return settings;
}
MainWindow::~MainWindow()
{
delete ui;
delete rpc;
delete settings;
}

47
mainwindow.h

@ -0,0 +1,47 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "precompiled.h"
// Forward declare to break circular dependency.
class RPC;
class Settings;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
Settings* getSettings();
Ui::MainWindow* ui;
QLabel* statusLabel;
QLabel* statusIcon;
private:
void setupSendTab();
void setupTransactionsTab();
void setupRecieveTab();
void setupBalancesTab();
void removeExtraAddresses();
void setDefaultPayFrom();
void cancelButton();
void sendButton();
void inputComboTextChanged(const QString& text);
void addAddressSection();
void maxAmountChecked(int checked);
RPC* rpc;
Settings* settings;
};
#endif // MAINWINDOW_H

674
mainwindow.ui

@ -0,0 +1,674 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>838</width>
<height>595</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Balance</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Summary</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Shielded</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="balSheilded">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Transparent</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="balTransparent">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Total</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="balTotal">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="unconfirmedWarning">
<property name="styleSheet">
<string notr="true">color: red;</string>
</property>
<property name="text">
<string>Some transactions are not yet confirmed</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Address Balances</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QTableView" name="balancesTable">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Send</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Pay From</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QComboBox" name="inputsCombo"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Address Balance:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="sendAddressBalance">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Send To</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QScrollArea" name="sendToScrollArea">
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="sendToWidgets">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>774</width>
<height>276</height>
</rect>
</property>
<layout class="QVBoxLayout" name="sendToLayout">
<item>
<widget class="QGroupBox" name="verticalGroupBox">
<property name="title">
<string>Recipient</string>
</property>
<layout class="QVBoxLayout" name="sendAddressLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Address</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="Address1">
<property name="placeholderText">
<string>Address</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Amount</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="Amount1">
<property name="baseSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>Amount</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="Max1">
<property name="text">
<string>Maximum Available</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<spacer name="horizontalSpacer_2">
<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="addAddressButton">
<property name="baseSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Add Address</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Fees</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Fee</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit">
<property name="text">
<string>0.0001 ZEC</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<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="sendTransactionButton">
<property name="baseSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Send</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelSendButton">
<property name="baseSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Recieve</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Recieve Address</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Address Type</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QRadioButton" name="rdioZAddr">
<property name="text">
<string>z-Addr</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="rdioTAddr">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>t-Addr</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<widget class="QComboBox" name="listRecieveAddresses">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRecieveNewAddr">
<property name="text">
<string>New Address</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QPlainTextEdit" name="txtRecieve">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="qrcodeDisplay">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">background-color: #fff</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>Transactions</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QTableView" name="transactionsTable">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>838</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuBalance">
<property name="title">
<string>File</string>
</property>
<addaction name="actionSettings"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuBalance"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
<action name="actionSettings">
<property name="text">
<string>Settings</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>inputsCombo</tabstop>
<tabstop>sendAddressBalance</tabstop>
<tabstop>sendToScrollArea</tabstop>
<tabstop>Address1</tabstop>
<tabstop>Amount1</tabstop>
<tabstop>Max1</tabstop>
<tabstop>addAddressButton</tabstop>
<tabstop>lineEdit</tabstop>
<tabstop>sendTransactionButton</tabstop>
<tabstop>cancelSendButton</tabstop>
<tabstop>balancesTable</tabstop>
<tabstop>rdioZAddr</tabstop>
<tabstop>rdioTAddr</tabstop>
<tabstop>listRecieveAddresses</tabstop>
<tabstop>btnRecieveNewAddr</tabstop>
<tabstop>txtRecieve</tabstop>
<tabstop>transactionsTable</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

40
precompiled.h

@ -0,0 +1,40 @@
#if defined __cplusplus
/* Add C++ includes here */
#include <iostream>
#include <QApplication>
#include <QFontDatabase>
#include <QAbstractTableModel>
#include <QClipboard>
#include <QStringBuilder>
#include <QAbstractItemModel>
#include <QMessageBox>
#include <QCheckBox>
#include <QScrollBar>
#include <QPainter>
#include <QTimer>
#include <QSettings>
#include <QFile>
#include <QErrorMessage>
#include <QApplication>
#include <QStandardPaths>
#include <QMainWindow>
#include <QPushButton>
#include <QLabel>
#include <QDialog>
#include <QUrl>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QJsonDocument>
#include <QAbstractTableModel>
#include <QAbstractItemModel>
#include <QObject>
#include "3rdparty/json/json.hpp"
#include "3rdparty/qrcode/QrCode.hpp"
#define QT6_VIRTUAL
#endif

712
qt5.natvis

@ -0,0 +1,712 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt VS Tools.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************
-->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="QPoint">
<AlternativeType Name="QPointF"/>
<DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString>
<Expand>
<Item Name="[x]">xp</Item>
<Item Name="[y]">yp</Item>
</Expand>
</Type>
<Type Name="QRect">
<DisplayString>{{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }}</DisplayString>
<Expand>
<Item Name="[x]">x1</Item>
<Item Name="[y]">y1</Item>
<Item Name="[width]">x2 - x1 + 1</Item>
<Item Name="[height]">y2 - y1 + 1</Item>
</Expand>
</Type>
<Type Name="QRectF">
<DisplayString>{{ x = {xp}, y = {yp}, width = {w}, height = {h} }}</DisplayString>
<Expand>
<Item Name="[x]">xp</Item>
<Item Name="[y]">yp</Item>
<Item Name="[width]">w</Item>
<Item Name="[height]">h</Item>
</Expand>
</Type>
<Type Name="QSize">
<AlternativeType Name="QSizeF"/>
<DisplayString>{{ width = {wd}, height = {ht} }}</DisplayString>
<Expand>
<Item Name="[width]">wd</Item>
<Item Name="[height]">ht</Item>
</Expand>
</Type>
<Type Name="QLine">
<AlternativeType Name="QLineF"/>
<DisplayString>{{ start point = {pt1}, end point = {pt2} }}</DisplayString>
<Expand>
<Synthetic Name="[start point]">
<DisplayString>{pt1}</DisplayString>
<Expand>
<ExpandedItem>pt1</ExpandedItem>
</Expand>
</Synthetic>
<Synthetic Name="[end point]">
<DisplayString>{pt2}</DisplayString>
<Expand>
<ExpandedItem>pt2</ExpandedItem>
</Expand>
</Synthetic>
</Expand>
</Type>
<Type Name="QPolygon">
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<ArrayItems>
<Size>d-&gt;size</Size>
<ValuePointer>(QPoint*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="QPolygonF">
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[closed]">
d-&gt;size &gt; 0
&amp;&amp; ((((QPointF*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)[0]).xp
== (((QPointF*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)[d-&gt;size - 1]).xp)
&amp;&amp; ((((QPointF*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)[0]).yp
== (((QPointF*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)[d-&gt;size - 1]).yp)
</Item>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<ArrayItems>
<Size>d-&gt;size</Size>
<ValuePointer>(QPointF*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name ="QVector2D">
<DisplayString>{{ x = {xp}, y = {yp} }}</DisplayString>
<Expand>
<Item Name="[x]">xp</Item>
<Item Name="[y]">yp</Item>
</Expand>
</Type>
<Type Name ="QVector3D">
<DisplayString>{{ x = {xp}, y = {yp}, z = {zp} }}</DisplayString>
<Expand>
<Item Name="[x]">xp</Item>
<Item Name="[y]">yp</Item>
<Item Name="[z]">zp</Item>
</Expand>
</Type>
<Type Name ="QVector4D">
<DisplayString>{{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }}</DisplayString>
<Expand>
<Item Name="[x]">xp</Item>
<Item Name="[y]">yp</Item>
<Item Name="[z]">zp</Item>
<Item Name="[w]">wp</Item>
</Expand>
</Type>
<Type Name ="QMatrix">
<DisplayString>
{{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }}
</DisplayString>
<Expand>
<Item Name="[m11]">_m11</Item>
<Item Name="[m12]">_m12</Item>
<Item Name="[m21]">_m21</Item>
<Item Name="[m22]">_m22</Item>
<Item Name="[dx]">_dx</Item>
<Item Name="[dy]">_dy</Item>
</Expand>
</Type>
<Type Name ="QMatrix4x4">
<DisplayString>
{{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }}
</DisplayString>
<Expand>
<Item Name="[m11]">m[0][0]</Item>
<Item Name="[m12]">m[1][0]</Item>
<Item Name="[m13]">m[2][0]</Item>
<Item Name="[m14]">m[3][0]</Item>
<Item Name="[m21]">m[0][1]</Item>
<Item Name="[m22]">m[1][1]</Item>
<Item Name="[m23]">m[2][1]</Item>
<Item Name="[m24]">m[3][1]</Item>
<Item Name="[m31]">m[0][2]</Item>
<Item Name="[m32]">m[1][2]</Item>
<Item Name="[m33]">m[2][2]</Item>
<Item Name="[m34]">m[3][2]</Item>
<Item Name="[m41]">m[0][3]</Item>
<Item Name="[m42]">m[1][3]</Item>
<Item Name="[m43]">m[2][3]</Item>
<Item Name="[m44]">m[3][3]</Item>
</Expand>
</Type>
<Type Name="QSizePolicy">
<DisplayString>
{{ horizontal = {static_cast&lt;Policy&gt;(bits.horPolicy)}, vertical = {static_cast&lt;Policy&gt;(bits.verPolicy)}, type = {ControlType(1 &lt;&lt; bits.ctype)} }}
</DisplayString>
<Expand>
<Synthetic Name="[vertical policy]">
<DisplayString>QSizePolicy::Policy::{static_cast&lt;Policy&gt;(bits.verPolicy)}</DisplayString>
</Synthetic>
<Synthetic Name="[horizontal policy]">
<DisplayString>QSizePolicy::Policy::{static_cast&lt;Policy&gt;(bits.horPolicy)}</DisplayString>
</Synthetic>
<Synthetic Name="[control type]">
<DisplayString>QSizePolicy::ControlType::{ControlType(1 &lt;&lt; bits.ctype)}</DisplayString>
</Synthetic>
<Synthetic Name="[expanding directions]">
<DisplayString
Condition="(static_cast&lt;Policy&gt;(bits.verPolicy) &amp; ExpandFlag)">
Qt::Vertical (2)
</DisplayString>
<DisplayString
Condition="(static_cast&lt;Policy&gt;(bits.horPolicy) &amp; ExpandFlag)">
Qt::Horizontal (1)
</DisplayString>
</Synthetic>
<Item Name="[vertical stretch]">static_cast&lt;int&gt;(bits.verStretch)</Item>
<Item Name="[horizontal stretch]">static_cast&lt;int&gt;(bits.horStretch)</Item>
<Item Name="[has height for width]">bits.hfw == 1</Item>
<Item Name="[has width for height]">bits.wfh == 1</Item>
</Expand>
</Type>
<Type Name="QChar">
<DisplayString>{ucs,c}</DisplayString>
<StringView>ucs,c</StringView>
<Expand>
<Item Name="[latin 1]">ucs > 0xff ? '\0' : char(ucs),c</Item>
<Item Name="[unicode]">ucs,c</Item>
</Expand>
</Type>
<Type Name="QString">
<DisplayString>{((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),sub}</DisplayString>
<StringView>((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),sub</StringView>
<Expand>
<Item Name="[size]">d-&gt;size</Item>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<ArrayItems>
<Size>d-&gt;size</Size>
<ValuePointer>((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),c</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="QByteArray">
<DisplayString>{((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),sb}</DisplayString>
<StringView>((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),sb</StringView>
<Expand>
<Item Name="[size]">d-&gt;size</Item>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<ArrayItems>
<Size>d-&gt;size</Size>
<ValuePointer>((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),c</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="QBitArray">
<DisplayString>{{ size = {(d.d-&gt;size &lt;&lt; 3) - *((reinterpret_cast&lt;char*&gt;(d.d)) + d.d-&gt;offset)} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d.d-&gt;ref.atomic._q_value</Item>
<IndexListItems>
<Size>(d.d-&gt;size &lt;&lt; 3) - *((reinterpret_cast&lt;char*&gt;(d.d)) + d.d-&gt;offset)</Size>
<ValueNode>
(*(reinterpret_cast&lt;const unsigned char*&gt;((reinterpret_cast&lt;char*&gt;(d.d)) + d.d-&gt;offset) + 1
+ ($i &gt;&gt; 3)) &amp; (1 &lt;&lt; ($i &amp; 7))) != 0
</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="QVarLengthArray&lt;*&gt;">
<AlternativeType Name="QVarLengthArray&lt;*, int&gt;"/>
<DisplayString>{{ size = {s} }}</DisplayString>
<Expand>
<Item Name="[capacity]">a</Item>
<ArrayItems>
<Size>s</Size>
<ValuePointer>ptr</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="QDate">
<DisplayString>{{ julian day = {jd} }}</DisplayString>
<Expand></Expand>
</Type>
<Type Name="QTime">
<DisplayString
Condition="mds == 1">{{ millisecond = {mds} }}</DisplayString>
<DisplayString
Condition="mds != 1">{{ milliseconds = {mds} }}</DisplayString>
<Expand>
<Item Name="[hour]"
Condition="(mds / 3600000) == 1">mds / 3600000, d</Item>
<Item Name="[hours]"
Condition="(mds / 3600000) != 1">mds / 3600000, d</Item>
<Item Name="[minute]"
Condition="((mds % 3600000) / 60000) == 1">(mds % 3600000) / 60000, d</Item>
<Item Name="[minutes]"
Condition="((mds % 3600000) / 60000) != 1">(mds % 3600000) / 60000, d</Item>
<Item Name="[second]"
Condition="((mds / 1000) % 60) == 1">(mds / 1000) % 60, d</Item>
<Item Name="[seconds]"
Condition="((mds / 1000) % 60) != 1">(mds / 1000) % 60, d</Item>
<Item Name="[millisecond]"
Condition="(mds % 1000) == 1">mds % 1000, d</Item>
<Item Name="[milliseconds]"
Condition="(mds % 1000) != 1">mds % 1000, d</Item>
</Expand>
</Type>
<Type Name="QRegularExpression">
<DisplayString>{d.pattern}</DisplayString>
</Type>
<Type Name="QSharedData">
<Expand>
<Item Name="[referenced]">ref._q_value</Item>
</Expand>
</Type>
<Type Name="QSharedPointer&lt;*&gt;">
<DisplayString>strong reference to shared pointer of type {"$T1"}</DisplayString>
<Expand>
<Item Name="[is null]">value == 0</Item>
<Item Name="[weak referenced]">d-&gt;weakref._q_value</Item>
<Item Name="[strong referenced]">d-&gt;strongref._q_value</Item>
</Expand>
</Type>
<Type Name="QSharedDataPointer&lt;*&gt;">
<DisplayString>pointer to implicit shared object of type {"$T1"}</DisplayString>
<Expand>
<ExpandedItem>d</ExpandedItem>
</Expand>
</Type>
<Type Name="QExplicitlySharedDataPointer&lt;*&gt;">
<DisplayString>pointer to explicit shared object of type {"$T1"}</DisplayString>
<Expand>
<ExpandedItem>d</ExpandedItem>
</Expand>
</Type>
<Type Name="QPointer&lt;*&gt;">
<DisplayString>guarded pointer to subclass of QObject of type {"$T1"}</DisplayString>
<Expand>
<Item Name="[is null]">wp.d == 0 || wp.d-&gt;strongref._q_value == 0 || wp.value == 0</Item>
</Expand>
</Type>
<Type Name="QWeakPointer&lt;*&gt;">
<DisplayString>weak reference to shared pointer of type {"$T1"}</DisplayString>
<Expand>
<Item Name="[is null]">d == 0 || d-&gt;strongref._q_value == 0 || value == 0</Item>
<Item Name="[weak referenced]">d-&gt;weakref._q_value</Item>
<Item Name="[strong referenced]">d-&gt;strongref._q_value</Item>
</Expand>
</Type>
<Type Name="QScopedPointer&lt;*&gt;">
<DisplayString>scoped pointer to a dynamically allocated object of type {"$T1"}</DisplayString>
<Expand>
<Item Name="[is null]">!d</Item>
</Expand>
</Type>
<Type Name="QScopedArrayPointer&lt;*&gt;">
<DisplayString>scoped pointer to dynamically allocated array of objects of type {"$T1"}</DisplayString>
<Expand>
<Item Name="[is null]">!d</Item>
</Expand>
</Type>
<Type Name="QPair&lt;*,*&gt;">
<DisplayString>({first}, {second})</DisplayString>
<Expand>
<Item Name="[first]">first</Item>
<Item Name="[second]">second</Item>
</Expand>
</Type>
<Type Name="QVector&lt;*&gt;">
<AlternativeType Name="QStack&lt;*&gt;"></AlternativeType>
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<ArrayItems>
<Size>d-&gt;size</Size>
<ValuePointer>($T1*)((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset)</ValuePointer>
</ArrayItems>
</Expand>
</Type>
<Type Name="QList&lt;*&gt;">
<AlternativeType Name="QStringList"></AlternativeType>
<AlternativeType Name="QQueue&lt;*&gt;"></AlternativeType>
<DisplayString>{{ size = {d-&gt;end - d-&gt;begin} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<IndexListItems>
<Size>d-&gt;end - d-&gt;begin</Size>
<ValueNode>*reinterpret_cast&lt;$T1*&gt;((sizeof($T1) &gt; sizeof(void*))
? reinterpret_cast&lt;Node*&gt;(d->array + d->begin + $i)->v
: reinterpret_cast&lt;$T1*&gt;(d->array + d->begin + $i))
</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="QLinkedList&lt;*&gt;">
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<LinkedListItems>
<Size>d-&gt;size</Size>
<HeadPointer>d-&gt;n</HeadPointer>
<NextPointer>n</NextPointer>
<ValueNode>(*(QLinkedListNode&lt;$T1&gt;*)this).t</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="QMapNode&lt;*,*&gt;">
<DisplayString>({key}, {value})</DisplayString>
<Expand>
<Item Name="[key]">key</Item>
<Item Name="[value]">value</Item>
</Expand>
</Type>
<Type Name="QMap&lt;*,*&gt;">
<AlternativeType Name="QMultiMap&lt;*,*&gt;"/>
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<TreeItems>
<Size>d-&gt;size</Size>
<HeadPointer>d-&gt;header.left</HeadPointer>
<LeftPointer>left</LeftPointer>
<RightPointer>right</RightPointer>
<ValueNode>*((QMapNode&lt;$T1,$T2&gt;*)this)</ValueNode>
</TreeItems>
</Expand>
</Type>
<Type Name="QHashNode&lt;*,*&gt;">
<DisplayString Condition="next == 0">(empty)</DisplayString>
<DisplayString Condition="next != 0">({key}, {value})</DisplayString>
<Expand>
<Item Name="[key]" Condition="next != 0">key</Item>
<Item Name="[value]" Condition="next != 0">value</Item>
</Expand>
</Type>
<Type Name="QHash&lt;*,*&gt;">
<AlternativeType Name="QMultiHash&lt;*,*&gt;"/>
<DisplayString>{{ size = {d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
<IndexListItems>
<Size>d-&gt;numBuckets</Size>
<ValueNode>*((QHashNode&lt;$T1,$T2&gt;*)d-&gt;buckets[$i])</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="QHashNode&lt;*,QHashDummyValue&gt;">
<DisplayString Condition="next == 0">(empty)</DisplayString>
<DisplayString Condition="next != 0">({key})</DisplayString>
<Expand>
<Item Name="[key]" Condition="next != 0">key</Item>
</Expand>
</Type>
<Type Name="QSet&lt;*&gt;">
<DisplayString>{{ size = {q_hash.d-&gt;size} }}</DisplayString>
<Expand>
<ExpandedItem>q_hash</ExpandedItem>
</Expand>
</Type>
<Type Name="QCache&lt;*,*&gt;::Node">
<DisplayString>({*keyPtr}, {*t})</DisplayString>
<Expand>
<Item Name="[key]">*keyPtr</Item>
<Item Name="[value]">*t</Item>
</Expand>
</Type>
<Type Name="QCache&lt;*,*&gt;">
<DisplayString>{{ size = {hash.d-&gt;size} }}</DisplayString>
<Expand>
<Item Name="[max coast]">mx</Item>
<Item Name="[total coast]">total</Item>
<Item Name="[referenced]">hash.d-&gt;ref.atomic._q_value</Item>
<LinkedListItems>
<Size>hash.d-&gt;size</Size>
<HeadPointer>f</HeadPointer>
<NextPointer>n</NextPointer>
<ValueNode>*((Node*)this)</ValueNode>
</LinkedListItems>
</Expand>
</Type>
<Type Name="QVariant">
<!--Region DisplayString QVariant-->
<DisplayString Condition="d.type == QMetaType::UnknownType">Invalid</DisplayString>
<DisplayString Condition="d.type == QMetaType::Bool">{d.data.b}</DisplayString>
<DisplayString Condition="d.type == QMetaType::Int">{d.data.i}</DisplayString>
<DisplayString Condition="d.type == QMetaType::UInt">{d.data.u}</DisplayString>
<DisplayString Condition="d.type == QMetaType::LongLong">{d.data.ll}</DisplayString>
<DisplayString Condition="d.type == QMetaType::ULongLong">{d.data.ull}</DisplayString>
<DisplayString Condition="d.type == QMetaType::Double">{d.data.d}</DisplayString>
<DisplayString Condition="d.type == QMetaType::QChar">{d.data.c}</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVariantMap">
{*((QMap&lt;QString,QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVariantList">
{*((QList&lt;QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QString">
{*((QString*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QStringList">
{*((QStringList*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QByteArray">
{*((QByteArray*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QBitArray">
{*((QBitArray*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QDate">
{*((QDate*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QTime">
{*((QTime*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QDateTime">DateTime</DisplayString>
<DisplayString Condition="d.type == QMetaType::QUrl">Url</DisplayString>
<DisplayString Condition="d.type == QMetaType::QLocale">Locale</DisplayString>
<DisplayString Condition="d.type == QMetaType::QRect">
{*((QRect*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QRectF">
{*((QRectF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QSize">
{*((QSize*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QSizeF">
{*((QSizeF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QLine">
{*((QLine*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QLineF">
{*((QLineF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPoint">
{*((QPoint*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPointF">
{*((QPointF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QRegExp">RegExp</DisplayString>
<DisplayString Condition="d.type == QMetaType::QRegularExpression">RegularExpression</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVariantHash">
{*((QHash&lt;QString,QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))}
</DisplayString>
<DisplayString Condition="d.type == QMetaType::QEasingCurve">EasingCurve</DisplayString>
<DisplayString Condition="d.type == QMetaType::QUuid">Uuid</DisplayString>
<DisplayString Condition="d.type == QMetaType::QModelIndex">ModelIndex</DisplayString>
<DisplayString Condition="d.type == QMetaType::LastCoreType">LastCoreType</DisplayString>
<DisplayString Condition="d.type == QMetaType::QFont">Font</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPixmap">Pixmap</DisplayString>
<DisplayString Condition="d.type == QMetaType::QBrush">Brush</DisplayString>
<DisplayString Condition="d.type == QMetaType::QColor">Color</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPalette">Palette</DisplayString>
<DisplayString Condition="d.type == QMetaType::QImage">Image</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPolygon">Polygon</DisplayString>
<DisplayString Condition="d.type == QMetaType::QRegion">Region</DisplayString>
<DisplayString Condition="d.type == QMetaType::QBitmap">Bitmap</DisplayString>
<DisplayString Condition="d.type == QMetaType::QCursor">Cursor</DisplayString>
<DisplayString Condition="d.type == QMetaType::QKeySequence">KeySequence</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPen">Pen</DisplayString>
<DisplayString Condition="d.type == QMetaType::QTextLength">TextLength</DisplayString>
<DisplayString Condition="d.type == QMetaType::QTextFormat">TextFormat</DisplayString>
<DisplayString Condition="d.type == QMetaType::QMatrix">Matrix</DisplayString>
<DisplayString Condition="d.type == QMetaType::QTransform">Transform</DisplayString>
<DisplayString Condition="d.type == QMetaType::QMatrix4x4">Matrix4x4</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVector2D">Vector2D</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVector3D">Vector3D</DisplayString>
<DisplayString Condition="d.type == QMetaType::QVector4D">Vector4D</DisplayString>
<DisplayString Condition="d.type == QMetaType::QQuaternion">Quaternion</DisplayString>
<DisplayString Condition="d.type == QMetaType::QPolygonF">PolygonF</DisplayString>
<DisplayString Condition="d.type == QMetaType::QIcon">Icon</DisplayString>
<DisplayString Condition="d.type == QMetaType::LastGuiType">LastGuiType</DisplayString>
<DisplayString Condition="d.type == QMetaType::QSizePolicy">SizePolicy</DisplayString>
<DisplayString Condition="d.type == QMetaType::User">UserType</DisplayString>
<DisplayString Condition="d.type == 0xffffffff">LastType</DisplayString>
<!--End region DisplayString QVariant-->
<!--Region DisplayView QVariant-->
<StringView Condition="d.type == QMetaType::QChar">d.data.c</StringView>
<StringView Condition="d.type == QMetaType::QString">
*((QString*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</StringView>
<StringView Condition="d.type == QMetaType::QByteArray">
*((QByteArray*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</StringView>
<!--End region DisplayView QVariant-->
<!--Region Expand QVariant-->
<Expand>
<ExpandedItem Condition="d.type == QMetaType::QVariantMap">
*((QMap&lt;QString,QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QVariantList">
*((QList&lt;QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QString">
*((QString*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QStringList">
*((QStringList*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QByteArray">
*((QByteArray*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QBitArray">
*((QBitArray*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QDate">
*((QDate*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QTime">
*((QTime*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QRect">
*((QRect*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QRectF">
*((QRectF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QSize">
*((QSize*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QSizeF">
*((QSizeF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QLine">
*((QLine*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QLineF">
*((QLineF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QPoint">
*((QPoint*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QPointF">
*((QPointF*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
<ExpandedItem Condition="d.type == QMetaType::QVariantHash">
*((QHash&lt;QString,QVariant&gt;*)(d.is_shared ? d.data.shared-&gt;ptr
: reinterpret_cast&lt;const void *&gt;(&amp;d.data.ptr)))
</ExpandedItem>
</Expand>
<!--End region Expand QVariant-->
</Type>
</AutoVisualizer>

495
rpc.cpp

@ -0,0 +1,495 @@
#include "rpc.h"
#include "transactionitem.h"
#include "settings.h"
using json = nlohmann::json;
RPC::RPC(QNetworkAccessManager* client, MainWindow* main) {
this->restclient = client;
this->main = main;
this->ui = main->ui;
reloadConnectionInfo();
// Set up a timer to refresh the UI every few seconds
timer = new QTimer(main);
QObject::connect(timer, &QTimer::timeout, [=]() {
refresh();
});
timer->start(1 * 60 * 1000); // Query every minute
// Set up the timer to watch for tx status
txTimer = new QTimer(main);
QObject::connect(txTimer, &QTimer::timeout, [=]() {
refreshTxStatus();
});
// Start at every minute. When an operation is pending, this will change to every second
txTimer->start(1 * 60 * 1000);
}
RPC::~RPC() {
delete timer;
delete txTimer;
delete transactionsTableModel;
delete balancesTableModel;
delete utxos;
delete allBalances;
delete zaddresses;
delete restclient;
}
void RPC::reloadConnectionInfo() {
// Reset for any errors caused.
firstTime = true;
QUrl myurl;
myurl.setScheme("http"); //https also applicable
myurl.setHost(main->getSettings()->getHost());
myurl.setPort(main->getSettings()->getPort().toInt());
request.setUrl(myurl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
QString headerData = "Basic " + main->getSettings()->getUsernamePassword().toLocal8Bit().toBase64();
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
void RPC::doRPC(const json& payload, const std::function<void(json)>& cb) {
QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump()));
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
handleConnectionError(QString::fromStdString(parsed["error"]["message"]));
} else {
handleConnectionError(reply->errorString());
}
return;
}
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (parsed.is_discarded()) {
handleConnectionError("Unknown error");
}
cb(parsed["result"]);
});
}
void RPC::getZAddresses(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_listaddresses"},
};
doRPC(payload, cb);
}
void RPC::getTransparentUnspent(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "listunspent"},
{"params", {0}} // Get UTXOs with 0 confirmations as well.
};
doRPC(payload, cb);
}
void RPC::getZUnspent(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_listunspent"},
{"params", {0}} // Get UTXOs with 0 confirmations as well.
};
doRPC(payload, cb);
}
void RPC::newZaddr(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_getnewaddress"},
};
doRPC(payload, cb);
}
void RPC::newTaddr(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getnewaddress"},
};
doRPC(payload, cb);
}
void RPC::getBalance(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_gettotalbalance"},
{"params", {0}} // Get Unconfirmed balance as well.
};
doRPC(payload, cb);
}
void RPC::getTransactions(const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "listtransactions"}
};
doRPC(payload, cb);
}
void RPC::doSendRPC(const json& payload, const std::function<void(json)>& cb) {
QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump()));
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
handleTxError(QString::fromStdString(parsed["error"]["message"]));
} else {
handleTxError(reply->errorString());
}
return;
}
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (parsed.is_discarded()) {
handleTxError("Unknown error");
}
cb(parsed["result"]);
});
}
void RPC::sendZTransaction(json params, const std::function<void(json)>& cb) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_sendmany"},
{"params", params}
};
doSendRPC(payload, cb);
}
void RPC::handleConnectionError(const QString& error) {
if (error.isNull()) return;
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
main->statusIcon->setPixmap(icon.pixmap(16, 16));
main->statusLabel->setText("No Connection");
if (firstTime) {
this->firstTime = false;
QMessageBox msg(main);
msg.setIcon(QMessageBox::Icon::Critical);
msg.setWindowTitle("Connection Error");
QString explanation;
if (error.contains("authentication", Qt::CaseInsensitive)) {
explanation = QString()
% "\n\nThis is most likely because of misconfigured rpcuser/rpcpassword. "
% "zcashd needs the following options set in ~/.zcash/zcash.conf\n\n"
% "rpcuser=<someusername>\n"
% "rpcpassword=<somepassword>\n"
% "\nIf you're connecting to a remote note, you can change the username/password in the "
% "File->Settings menu.";
} else if (error.contains("connection", Qt::CaseInsensitive)) {
explanation = QString()
% "\n\nThis is most likely because we couldn't connect to zcashd. Is zcashd running and "
% "accepting connections from this machine? \nIf you need to change the host/port, you can set that in the "
% "File->Settings menu.";
} else if (error.contains("bad request", Qt::CaseInsensitive)) {
explanation = QString()
% "\n\nThis is most likely an internal error. Are you using zcashd v2.0 or higher? You might "
% "need to file a bug report here: ";
} else if (error.contains("internal server error", Qt::CaseInsensitive)) {
explanation = QString()
% "\n\nIf you just started zcashd, then it's still loading and you might have to wait a while. If zcashd is ready, then you've run into "
% "something unexpected, and might need to file a bug report here: ";
} else {
explanation = QString()
% "\n\nThis is most likely an internal error. Something unexpected happened. "
% "You might need to file a bug report here: ";
}
msg.setText("There was a network connection error. The error was: \n\n"
+ error + explanation);
msg.exec();
return;
}
}
void RPC::handleTxError(const QString& error) {
if (error.isNull()) return;
QMessageBox msg(main);
msg.setIcon(QMessageBox::Icon::Critical);
msg.setWindowTitle("Transaction Error");
msg.setText("There was an error sending the transaction. The error was: \n\n"
+ error);
msg.exec();
}
/// This will refresh all the balance data from zcashd
void RPC::refresh() {
// First, test the connection to see if we can actually get info.
getInfoThenRefresh();
}
void RPC::getInfoThenRefresh() {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getinfo"}
};
doRPC(payload, [=] (json reply) {
QString statusText = QString::fromStdString("Connected (")
.append(QString::number(reply["blocks"].get<json::number_unsigned_t>()))
.append(")");
main->statusLabel->setText(statusText);
main->statusIcon->clear(); // TODO: Add checked icon
// Now, refreshing the balances and transactions causes UI flicked and selections
// to disappear, so we'll only do it if the balance in the wallet has
// updated (i.e., something changed)
if (QString::number(reply["balance"].get<json::number_float_t>()) != currentBalance) {
currentBalance = QString::number(reply["balance"].get<json::number_float_t>());
refreshBalances();
refreshTransactions();
}
// Addresses can be created without a transaction, so we'll call that outside
refreshAddresses();
});
}
void RPC::refreshAddresses() {
delete zaddresses;
zaddresses = new QList<QString>();
getZAddresses([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
auto addr = QString::fromStdString(it.get<json::string_t>());
zaddresses->push_back(addr);
}
});
}
void RPC::refreshBalances() {
ui->unconfirmedWarning->setVisible(false);
// 1. Get the Balances
getBalance([=] (json reply) {
ui->balSheilded ->setText(QString::fromStdString(reply["private"]) % " ZEC");
ui->balTransparent ->setText(QString::fromStdString(reply["transparent"]) % " ZEC");
ui->balTotal ->setText(QString::fromStdString(reply["total"]) % " ZEC");
});
// 2. Get the UTXOs
// First, create a new UTXO list, deleting the old one;
delete utxos;
utxos = new QList<UnspentOutput>();
delete allBalances;
allBalances = new QMap<QString, double>();
// Function to process reply of the listunspent and z_listunspent API calls, used below.
auto processUnspent = [=] (const json& reply) {
for (auto& it : reply.get<json::array_t>()) {
QString qsAddr = QString::fromStdString(it["address"]);
auto confirmations = it["confirmations"].get<json::number_unsigned_t>();
if (confirmations == 0) {
ui->unconfirmedWarning->setVisible(true);
}
utxos->push_back(
UnspentOutput(
qsAddr,
QString::fromStdString(it["txid"]),
QString::number(it["amount"].get<json::number_float_t>(), 'f', 8),
confirmations
)
);
(*allBalances)[qsAddr] = (*allBalances)[qsAddr] + it["amount"].get<json::number_float_t>();
}
};
// Function to create the data model and update the views, used below.
auto updateUI = [=] () {
// Create the balances table model.
// Delete the old Model, because the setModel() doesn't take ownership of the Model object
delete balancesTableModel;
balancesTableModel = new BalancesTableModel(ui->balancesTable, allBalances, utxos);
ui->balancesTable->setModel(balancesTableModel);
// Configure Balances Table
ui->balancesTable->setColumnWidth(0, 300);
// Add all the addresses into the inputs combo box
ui->inputsCombo->clear();
auto i = allBalances->constBegin();
while (i != allBalances->constEnd()) {
ui->inputsCombo->addItem(i.key() % "(" % QString::number(i.value(), 'f', 8) % " ZEC)");
++i;
}
};
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
getTransparentUnspent([=] (json reply) {
processUnspent(reply);
getZUnspent([=] (json reply) {
processUnspent(reply);
updateUI();
});
});
}
void RPC::refreshTransactions() {
// First, delete the previous headers
delete transactionsTableModel;
auto txdata = new QList<TransactionItem>();
getTransactions([=] (json reply) {
for (auto& it : reply.get<json::array_t>()) {
TransactionItem tx(
QString::fromStdString(it["category"]),
QDateTime::fromSecsSinceEpoch(it["time"].get<json::number_unsigned_t>()).toLocalTime().toString(),
(it["address"].is_null() ? "" : QString::fromStdString(it["address"])),
QString::fromStdString(it["txid"]),
it["amount"].get<json::number_float_t>(),
it["confirmations"].get<json::number_float_t>()
);
txdata->push_front(tx);
}
transactionsTableModel = new TxTableModel(ui->transactionsTable, txdata);
ui->transactionsTable->setModel(transactionsTableModel);
ui->transactionsTable->setColumnWidth(1, 300);
ui->transactionsTable->setColumnWidth(2, 200);
ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
});
}
void RPC::refreshTxStatus(const QString& newOpid) {
if (!newOpid.isEmpty()) {
qDebug() << QString::fromStdString("Adding opid ") % newOpid;
watchingOps.insert(newOpid);
}
// Make an RPC to load pending operation statues
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "z_getoperationstatus"},
};
doRPC(payload, [=] (const json& reply) {
// There's an array for each item in the status
for (auto& it : reply.get<json::array_t>()) {
// If we were watching this Tx and it's status became "success", then we'll show a status bar alert
QString id = QString::fromStdString(it["id"]);
if (watchingOps.contains(id)) {
// And if it ended up successful
QString status = QString::fromStdString(it["status"]);
qDebug() << QString::fromStdString("Watching opid, current status= ") % status;
if (status == "success") {
qDebug() << QString::fromStdString("Success, showing status message");
main->ui->statusBar->showMessage(" Tx " % id % " computed successfully and submitted");
watchingOps.remove(id);
txTimer->start(1 * 60 * 1000);
// Refresh balances to show unconfirmed balances
refresh();
} else if (status == "failed") {
// If it failed, then we'll actually show a warning.
auto errorMsg = QString::fromStdString(it["error"]["message"]);
qDebug() << QString::fromStdString("Failed with message") % errorMsg;
QMessageBox msg(
QMessageBox::Critical,
"Transaction Error",
"The transaction with id " % id % " failed. The error was:\n\n" % errorMsg,
QMessageBox::Ok,
main
);
txTimer->start(1 * 60 * 1000);
watchingOps.remove(id);
main->ui->statusBar->showMessage(" Tx " % id % " failed", 15 * 1000);
msg.exec();
} else if (status == "executing") {
// If the operation is executing, then watch every second.
qDebug() << QString::fromStdString("executing, doing again in 1 sec");
txTimer->start(1 * 1000);
}
}
}
});
}
/*
[
{
"id": "opid-ad54b34c-1d89-48af-9cb5-4825905fc62e",
"status": "executing",
"creation_time": 1539490482,
"method": "z_sendmany",
"params": {
"fromaddress": "t1aWhRh9JNKWzpzjn2gmULDJzfKLC724EPS",
"amounts": [
{
"address": "zcVHg9euUSQF8ef7ZXztrv4LcdC1mytEUYLuoj4W5iSygLFYjm1yQCggAYnnydUaHLy2GBaxF4PX5vjaJjnj2Lq3ecQtGF4",
"amount": 0.0001
}
],
"minconf": 1,
"fee": 0.0001
}
},{
"id": "opid-7807e672-7f8c-428a-8587-3354d0ae1b88",
"status": "failed",
"creation_time": 1539490847,
"error": {
"code": -6,
"message": "Insufficient protected funds, have 0.0006001, need 111.0001"
},
]
*/

80
rpc.h

@ -0,0 +1,80 @@
#ifndef RPCCLIENT_H
#define RPCCLIENT_H
#include "precompiled.h"
#include "unspentoutput.h"
#include "balancestablemodel.h"
#include "txtablemodel.h"
#include "ui_mainwindow.h"
#include "mainwindow.h"
using json = nlohmann::json;
class RPC
{
public:
RPC(QNetworkAccessManager* restclient, MainWindow* main);
~RPC();
void refresh(); // Refresh all transactions
void refreshTxStatus(const QString& newOpid = QString()); // Refresh the status of all pending txs.
void refreshAddresses(); // Refresh wallet Z-addrs
void sendZTransaction (json params, const std::function<void(json)>& cb);
BalancesTableModel* getBalancesModel() { return balancesTableModel; }
const QList<QString>* getAllZAddresses() { return zaddresses; }
const QList<UnspentOutput>* getUTXOs() { return utxos; }
const QMap<QString, double>* getAllBalances() { return allBalances; }
void reloadConnectionInfo();
void newZaddr (const std::function<void(json)>& cb);
void newTaddr (const std::function<void(json)>& cb);
private:
void doRPC (const json& payload, const std::function<void(json)>& cb);
void doSendRPC (const json& payload, const std::function<void(json)>& cb);
void refreshBalances();
void refreshTransactions();
void getInfoThenRefresh();
void getBalance(const std::function<void(json)>& cb);
void getTransparentUnspent (const std::function<void(json)>& cb);
void getZUnspent (const std::function<void(json)>& cb);
void getTransactions (const std::function<void(json)>& cb);
void getZAddresses (const std::function<void(json)>& cb);
void handleConnectionError (const QString& error);
void handleTxError (const QString& error);
QNetworkAccessManager* restclient;
QNetworkRequest request;
QList<UnspentOutput>* utxos = nullptr;
QMap<QString, double>* allBalances = nullptr;
QList<QString>* zaddresses = nullptr;
QSet<QString> watchingOps;
TxTableModel* transactionsTableModel = nullptr;
BalancesTableModel* balancesTableModel = nullptr;
QTimer* timer;
QTimer* txTimer;
Ui::MainWindow* ui;
MainWindow* main;
// Current balance in the UI. If this number updates, then refresh the UI
QString currentBalance;
// First time warning flag for no connection
bool firstTime = true;
};
#endif // RPCCLIENT_H

256
sendtab.cpp

@ -0,0 +1,256 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui_confirm.h"
#include "settings.h"
#include "rpc.h"
#include "precompiled.h"
using json = nlohmann::json;
void MainWindow::setupSendTab() {
// Create the validator for send to/amount fields
auto amtValidator = new QDoubleValidator(0, 21000000, 8, ui->Amount1);
amtValidator->setNotation(QDoubleValidator::StandardNotation);
ui->Amount1->setValidator(amtValidator);
setDefaultPayFrom();
// Send button
QObject::connect(ui->sendTransactionButton, &QPushButton::clicked, this, &MainWindow::sendButton);
// Cancel Button
QObject::connect(ui->cancelSendButton, &QPushButton::clicked, this, &MainWindow::cancelButton);
// Input Combobox current text changed
QObject::connect(ui->inputsCombo, QOverload<const QString &>::of(&QComboBox::currentIndexChanged),
this, &MainWindow::inputComboTextChanged);
// Hook up add address button click
QObject::connect(ui->addAddressButton, &QPushButton::clicked, this, &MainWindow::addAddressSection);
// Max available Checkbox
QObject::connect(ui->Max1, &QCheckBox::stateChanged, this, &MainWindow::maxAmountChecked);
}
void MainWindow::setDefaultPayFrom() {
auto findMax = [=] (QString startsWith) {
double max_amt = 0;
int idx = -1;
for (int i=0; i < ui->inputsCombo->count(); i++) {
auto addr = ui->inputsCombo->itemText(i);
if (addr.startsWith(startsWith)) {
auto amt = rpc->getAllBalances()->value(addr.split("(")[0]);
if (max_amt < amt) {
max_amt = amt;
idx = i;
}
}
}
return idx;
};
// By default, select the z-address with the most balance from the inputs combo
auto maxZ = findMax("z");
if (maxZ >= 0) {
ui->inputsCombo->setCurrentIndex(maxZ);
} else {
auto maxT = findMax("t");
maxT = maxT >= 0 ? maxT : 0;
ui->inputsCombo->setCurrentIndex(maxT);
}
};
void MainWindow::inputComboTextChanged(const QString& text) {
auto bal = rpc->getAllBalances()->value(text.split("(")[0].trimmed());
auto balFmt = QString::number(bal, 'f', 8) + " ZEC";
ui->sendAddressBalance->setText(balFmt);
}
void MainWindow::addAddressSection() {
int itemNumber = ui->sendToWidgets->children().size() - 1;
auto verticalGroupBox = new QGroupBox(ui->sendToWidgets);
verticalGroupBox->setTitle(QString("Recipient ") % QString::number(itemNumber));
verticalGroupBox->setObjectName(QString("AddressGroupBox") % QString::number(itemNumber));
auto sendAddressLayout = new QVBoxLayout(verticalGroupBox);
sendAddressLayout->setSpacing(6);
sendAddressLayout->setContentsMargins(11, 11, 11, 11);
auto horizontalLayout_12 = new QHBoxLayout();
horizontalLayout_12->setSpacing(6);
auto label_4 = new QLabel(verticalGroupBox);
label_4->setText("Address");
horizontalLayout_12->addWidget(label_4);
auto Address1 = new QLineEdit(verticalGroupBox);
Address1->setObjectName(QString("Address") % QString::number(itemNumber));
Address1->setPlaceholderText("Address");
horizontalLayout_12->addWidget(Address1);
sendAddressLayout->addLayout(horizontalLayout_12);
auto horizontalLayout_13 = new QHBoxLayout();
horizontalLayout_13->setSpacing(6);
auto label_6 = new QLabel(verticalGroupBox);
label_6->setText("Amount");
horizontalLayout_13->addWidget(label_6);
auto Amount1 = new QLineEdit(verticalGroupBox);
Amount1->setPlaceholderText("Amount");
Amount1->setObjectName(QString("Amount") % QString::number(itemNumber));
Amount1->setBaseSize(QSize(200, 0));
// Create the validator for send to/amount fields
auto amtValidator = new QDoubleValidator(0, 21000000, 8, Amount1);
Amount1->setValidator(amtValidator);
horizontalLayout_13->addWidget(Amount1);
auto horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_13->addItem(horizontalSpacer_4);
sendAddressLayout->addLayout(horizontalLayout_13);
ui->sendToLayout->insertWidget(itemNumber-1, verticalGroupBox);
// Delay the call to scroll to allow the scroll window to adjust
QTimer::singleShot(10, [=] () {ui->sendToScrollArea->ensureWidgetVisible(ui->addAddressButton);});
}
void MainWindow::removeExtraAddresses() {
// The last one is a spacer, so ignore that
int totalItems = ui->sendToWidgets->children().size() - 2;
// Clear the first field
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address1"));
addr->clear();
auto amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount1"));
amt->clear();
auto max = ui->sendToWidgets->findChild<QCheckBox*>(QString("Max1"));
max->setChecked(false);
// Start the deletion after the first item, since we want to keep 1 send field there all there
for (int i=1; i < totalItems; i++) {
auto addressGroupBox = ui->sendToWidgets->findChild<QGroupBox*>(QString("AddressGroupBox") % QString::number(i+1));
delete addressGroupBox;
}
}
void MainWindow::maxAmountChecked(int checked) {
if (checked == Qt::Checked) {
ui->Amount1->setReadOnly(true);
if (rpc->getAllBalances() == nullptr) return;
// Calculate maximum amount
double sumAllAmounts = 0.0;
// Calculate all other amounts
int totalItems = ui->sendToWidgets->children().size() - 2; // The last one is a spacer, so ignore that
// Start counting the sum skipping the first one, because the MAX button is on the first one, and we don't
// want to include it in the sum.
for (int i=1; i < totalItems; i++) {
auto amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount") % QString::number(i+1));
sumAllAmounts += amt->text().toDouble();
}
sumAllAmounts += settings->fees();
auto addr = ui->inputsCombo->currentText().split("(")[0];
auto maxamount = rpc->getAllBalances()->value(addr) - sumAllAmounts;
maxamount = (maxamount < 0) ? 0 : maxamount;
ui->Amount1->setText(QString::number(maxamount, 'f'));
} else if (checked == Qt::Unchecked) {
// Just remove the readonly part, don't change the content
ui->Amount1->setReadOnly(false);
}
}
void MainWindow::sendButton() {
auto fnSplitAddressForWrap = [=] (const QString& a) -> QString {
if (!a.startsWith("z")) return a;
auto half = a.length() / 2;
auto splitted = a.left(half) + "\n" + a.right(a.length() - half);
return splitted;
};
// Get all the addresses and amounts
json allRecepients = json::array();
// Show a confirmation dialog
QDialog d(this);
Ui_confirm confirm;
confirm.setupUi(&d);
// Remove all existing address/amt qlabels
int totalConfirmAddrItems = confirm.sendToAddrs->children().size();
for (int i = 0; i < totalConfirmAddrItems; i++) {
auto addr = confirm.sendToAddrs->findChild<QLabel*>(QString("Addr") % QString::number(i+1));
auto amt = confirm.sendToAddrs->findChild<QLabel*>(QString("Amt") % QString::number(i+1));
delete addr;
delete amt;
}
// For each addr/amt in the sendTo tab
int totalItems = ui->sendToWidgets->children().size() - 2; // The last one is a spacer, so ignore that
for (int i=0; i < totalItems; i++) {
auto addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address") % QString::number(i+1));
auto amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount") % QString::number(i+1));
// Construct the JSON params
json rec = json::object();
rec["address"] = addr->text().toStdString();
rec["amount"] = amt->text().toDouble();
allRecepients.push_back(rec);
// Add new Address widgets instead of the same one.
{
auto Addr = new QLabel(confirm.sendToAddrs);
Addr->setObjectName(QString("Addr") % QString::number(i + 1));
Addr->setWordWrap(true);
Addr->setText(fnSplitAddressForWrap(addr->text()));
confirm.gridLayout->addWidget(Addr, i, 0, 1, 1);
auto Amt = new QLabel(confirm.sendToAddrs);
Amt->setObjectName(QString("Amt") % QString::number(i + 1));
Amt->setText(amt->text() % " ZEC");
Amt->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
confirm.gridLayout->addWidget(Amt, i, 1, 1, 1);
}
}
// Add sender
json params = json::array();
params.push_back(ui->inputsCombo->currentText().split("(")[0].trimmed().toStdString());
params.push_back(allRecepients);
// And show it in the confirm dialog
auto fromAddr = ui->inputsCombo->currentText().split("(")[0];
confirm.sendFrom->setText(fnSplitAddressForWrap(fromAddr));
// Show the dialog and submit it if the user confirms
if (d.exec() == QDialog::Accepted) {
rpc->sendZTransaction(params, [=](const json& reply) {
QString opid = QString::fromStdString(reply.get<json::string_t>());
ui->statusBar->showMessage("Computing Tx: " % opid);
// And then start monitoring the transaction
rpc->refreshTxStatus(opid);
});
// Then delete the additional fields from the sendTo tab
removeExtraAddresses();
}
}
void MainWindow::cancelButton() {
removeExtraAddresses();
// Back to the balances tab
ui->tabWidget->setCurrentIndex(0);
}

64
settings.cpp

@ -0,0 +1,64 @@
#include "precompiled.h"
#include "settings.h"
Settings::Settings()
{
refresh();
}
QString Settings::getHost() {
if (host.isNull() || host == "") return "127.0.0.1";
return host;
}
QString Settings::getPort() {
if (port.isNull() || port == "") return "8232";
return port;
}
QString Settings::getUsernamePassword() {
return username % ":" % password;
}
void Settings::refresh() {
// First step is to try and load from the QT Settings
QSettings s;
host = s.value("connection/host", "127.0.0.1" ).toString();
port = s.value("connection/port", "8232" ).toString();
username = s.value("connection/rpcuser", "" ).toString();
password = s.value("connection/rpcpassword", "" ).toString();
if (username == "") {
// Nothing in QT Settings, so try to read from file.
QString zcashdconf = QStandardPaths::locate(QStandardPaths::HomeLocation, ".zcash/zcash.conf");
if (zcashdconf.isNull()) {
// No zcash file, just return with nothing
return;
}
QFile file(zcashdconf);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << file.errorString();
return;
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
QStringList fields = line.split("=");
if (fields[0].trimmed().toLower() == "rpcuser") {
username = fields[1].trimmed();
}
if (fields[0].trimmed().toLower() == "rpcpassword") {
password = fields[1].trimmed();
}
}
file.close();
}
}

24
settings.h

@ -0,0 +1,24 @@
#ifndef SETTINGS_H
#define SETTINGS_H
class Settings
{
public:
Settings();
QString getUsernamePassword();
QString getHost();
QString getPort();
double fees() { return 0.0001; }
void refresh();
private:
QString host;
QString port;
QString username;
QString password;
};
#endif // SETTINGS_H

194
settings.ui

@ -0,0 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Settings</class>
<widget class="QDialog" name="Settings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Connection</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>zcashd connection</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>10</number>
</property>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>RPC Username</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLineEdit" name="rpcuser"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Host</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="hostname">
<property name="placeholderText">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="port">
<property name="placeholderText">
<string>8232</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>RPC Password</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLineEdit" name="rpcpassword"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="minimumSize">
<size>
<width>60</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Port</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Options</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>tabWidget</tabstop>
<tabstop>hostname</tabstop>
<tabstop>port</tabstop>
<tabstop>rpcuser</tabstop>
<tabstop>rpcpassword</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Settings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Settings</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

12
transactionitem.cpp

@ -0,0 +1,12 @@
#include "transactionitem.h"
TransactionItem::TransactionItem(const QString& type, const QString& datetime, const QString& address, const QString& txid,
double amount, int confirmations)
{
this->type = type;
this->datetime = datetime;
this->address = address;
this->txid = txid;
this->amount = amount;
this->confirmations = confirmations;
}

20
transactionitem.h

@ -0,0 +1,20 @@
#ifndef TRANSACTIONITEM_H
#define TRANSACTIONITEM_H
#include "precompiled.h"
class TransactionItem
{
public:
TransactionItem(const QString& type, const QString& datetime, const QString& address, const QString& txid,
double amount, int confirmations);
QString type;
QString datetime;
QString address;
QString txid;
double amount;
int confirmations;
};
#endif // TRANSACTIONITEM_H

71
txid.ui

@ -0,0 +1,71 @@
<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="geometry" >
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<pixmapfunction></pixmapfunction>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

75
txtablemodel.cpp

@ -0,0 +1,75 @@
#include "txtablemodel.h"
TxTableModel::TxTableModel(QObject *parent, QList<TransactionItem>* data)
: QAbstractTableModel(parent)
{
modeldata = data;
headers << "Category" << "Address" << "Date/Time" << "Amount";
}
TxTableModel::~TxTableModel() {
delete modeldata;
}
int TxTableModel::rowCount(const QModelIndex&) const
{
return modeldata->size();
}
int TxTableModel::columnCount(const QModelIndex&) const
{
return headers.size();
}
QVariant TxTableModel::data(const QModelIndex &index, int role) const
{
// Align column 4 (amount) right
if (role == Qt::TextAlignmentRole && index.column() == 3) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::ForegroundRole) {
if (modeldata->at(index.row()).confirmations == 0) {
QBrush b;
b.setColor(Qt::red);
return b;
}
// Else, just return the default brush
QBrush b;
b.setColor(Qt::black);
return b;
}
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return modeldata->at(index.row()).type;
case 1: return modeldata->at(index.row()).address;
case 2: return modeldata->at(index.row()).datetime;
case 3: return QVariant(QString::number(modeldata->at(index.row()).amount, 'f', 8) % " ZEC");
}
}
return QVariant();
}
QVariant TxTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::TextAlignmentRole && section == 3) return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::FontRole) {
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
return headers.at(section);
}
return QVariant();
}
QString TxTableModel::getTxId(int row) {
return modeldata->at(row).txid;
}

26
txtablemodel.h

@ -0,0 +1,26 @@
#ifndef STRINGSTABLEMODEL_H
#define STRINGSTABLEMODEL_H
#include "transactionitem.h"
#include "precompiled.h"
class TxTableModel: public QAbstractTableModel
{
public:
TxTableModel(QObject* parent, QList<TransactionItem>* addresses);
~TxTableModel();
QString getTxId(int row);
int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
QList<TransactionItem>* modeldata;
QList<QString> headers;
};
#endif // STRINGSTABLEMODEL_H

86
ui_about.h

@ -0,0 +1,86 @@
/********************************************************************************
** Form generated from reading UI file 'about.ui'
**
** Created by: Qt User Interface Compiler version 5.11.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_ABOUT_H
#define UI_ABOUT_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QTextEdit>
#include <QtWidgets/QVBoxLayout>
QT_BEGIN_NAMESPACE
class Ui_about
{
public:
QVBoxLayout *verticalLayout;
QTextEdit *textEdit;
QDialogButtonBox *buttonBox;
void setupUi(QDialog *about)
{
if (about->objectName().isEmpty())
about->setObjectName(QStringLiteral("about"));
about->resize(497, 448);
verticalLayout = new QVBoxLayout(about);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
textEdit = new QTextEdit(about);
textEdit->setObjectName(QStringLiteral("textEdit"));
textEdit->setReadOnly(true);
verticalLayout->addWidget(textEdit);
buttonBox = new QDialogButtonBox(about);
buttonBox->setObjectName(QStringLiteral("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
verticalLayout->addWidget(buttonBox);
retranslateUi(about);
QObject::connect(buttonBox, SIGNAL(accepted()), about, SLOT(accept()));
QObject::connect(buttonBox, SIGNAL(rejected()), about, SLOT(reject()));
QMetaObject::connectSlotsByName(about);
} // setupUi
void retranslateUi(QDialog *about)
{
about->setWindowTitle(QApplication::translate("about", "Dialog", nullptr));
textEdit->setHtml(QApplication::translate("about", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Copyright (c) 2018 Aditya Kulkarni. (MIT License)</p>\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Special thanks to:</p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">JSON for Modern C++ : <a href=\"https://nlohmann.github.io/json/\"><span style=\""
" text-decoration: underline; color:#007af4;\">https://nlohmann.github.io/json/</span></a></p>\n"
"<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">QR Code generator library Nayuki : <a href=\"https://www.nayuki.io/page/qr-code-generator-library\"><span style=\" text-decoration: underline; color:#007af4;\">https://www.nayuki.io/page/qr-code-ge\342\200\246</span></a></p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Made with QT : <a href=\"https://www.qt.io/\"><span style=\" text-decoration: underline; color:#007af4;\">https://www.qt.io/</span></a></p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">LICENSE:</p>\n"
"<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Permission is hereby granted, free of charge, "
"to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:</p>\n"
"<ul style=\"margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;\"><li style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</li>\n"
"<li style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">The Software is provided &quot;as is&quot;, without warranty of any kind, express or implied, including but not limited to the w"
"arranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the Software or the use or other dealings in the Software.</li></ul></body></html>", nullptr));
} // retranslateUi
};
namespace Ui {
class about: public Ui_about {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_ABOUT_H

130
ui_confirm.h

@ -0,0 +1,130 @@
/********************************************************************************
** Form generated from reading UI file 'confirm.ui'
**
** Created by: Qt User Interface Compiler version 5.11.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_CONFIRM_H
#define UI_CONFIRM_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QFrame>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QVBoxLayout>
QT_BEGIN_NAMESPACE
class Ui_confirm
{
public:
QVBoxLayout *verticalLayout;
QGroupBox *groupBox;
QVBoxLayout *verticalLayout_2;
QLabel *sendFrom;
QGroupBox *sendToAddrs;
QGridLayout *gridLayout;
QLabel *Addr1;
QLabel *Amt1;
QSpacerItem *verticalSpacer;
QFrame *line;
QLabel *label;
QDialogButtonBox *buttonBox;
void setupUi(QDialog *confirm)
{
if (confirm->objectName().isEmpty())
confirm->setObjectName(QStringLiteral("confirm"));
confirm->resize(429, 371);
verticalLayout = new QVBoxLayout(confirm);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
groupBox = new QGroupBox(confirm);
groupBox->setObjectName(QStringLiteral("groupBox"));
verticalLayout_2 = new QVBoxLayout(groupBox);
verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
sendFrom = new QLabel(groupBox);
sendFrom->setObjectName(QStringLiteral("sendFrom"));
sendFrom->setWordWrap(true);
verticalLayout_2->addWidget(sendFrom);
verticalLayout->addWidget(groupBox);
sendToAddrs = new QGroupBox(confirm);
sendToAddrs->setObjectName(QStringLiteral("sendToAddrs"));
gridLayout = new QGridLayout(sendToAddrs);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
Addr1 = new QLabel(sendToAddrs);
Addr1->setObjectName(QStringLiteral("Addr1"));
Addr1->setWordWrap(true);
gridLayout->addWidget(Addr1, 0, 0, 1, 1);
Amt1 = new QLabel(sendToAddrs);
Amt1->setObjectName(QStringLiteral("Amt1"));
Amt1->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
gridLayout->addWidget(Amt1, 0, 1, 1, 1);
verticalLayout->addWidget(sendToAddrs);
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout->addItem(verticalSpacer);
line = new QFrame(confirm);
line->setObjectName(QStringLiteral("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
verticalLayout->addWidget(line);
label = new QLabel(confirm);
label->setObjectName(QStringLiteral("label"));
verticalLayout->addWidget(label);
buttonBox = new QDialogButtonBox(confirm);
buttonBox->setObjectName(QStringLiteral("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
verticalLayout->addWidget(buttonBox);
retranslateUi(confirm);
QObject::connect(buttonBox, SIGNAL(accepted()), confirm, SLOT(accept()));
QObject::connect(buttonBox, SIGNAL(rejected()), confirm, SLOT(reject()));
QMetaObject::connectSlotsByName(confirm);
} // setupUi
void retranslateUi(QDialog *confirm)
{
confirm->setWindowTitle(QApplication::translate("confirm", "Confirm Transaction", nullptr));
groupBox->setTitle(QApplication::translate("confirm", "From", nullptr));
sendFrom->setText(QString());
sendToAddrs->setTitle(QApplication::translate("confirm", "To", nullptr));
Addr1->setText(QApplication::translate("confirm", "TextLabel", nullptr));
Amt1->setText(QApplication::translate("confirm", "TextLabel", nullptr));
label->setText(QApplication::translate("confirm", "Fees: 0.0001 ZEC", nullptr));
} // retranslateUi
};
namespace Ui {
class confirm: public Ui_confirm {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_CONFIRM_H

683
ui_mainwindow.h

@ -0,0 +1,683 @@
/********************************************************************************
** Form generated from reading UI file 'mainwindow.ui'
**
** Created by: Qt User Interface Compiler version 5.11.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_MAINWINDOW_H
#define UI_MAINWINDOW_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QFrame>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <QtWidgets/QMenuBar>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QRadioButton>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QStatusBar>
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QTableView>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_MainWindow
{
public:
QAction *actionExit;
QAction *actionAbout;
QAction *actionSettings;
QWidget *centralWidget;
QGridLayout *gridLayout_3;
QTabWidget *tabWidget;
QWidget *tab;
QGridLayout *gridLayout_2;
QHBoxLayout *horizontalLayout_5;
QGroupBox *groupBox;
QGridLayout *gridLayout;
QVBoxLayout *verticalLayout;
QHBoxLayout *horizontalLayout;
QLabel *label;
QLabel *balSheilded;
QHBoxLayout *horizontalLayout_2;
QLabel *label_2;
QLabel *balTransparent;
QFrame *line;
QHBoxLayout *horizontalLayout_3;
QLabel *label_3;
QLabel *balTotal;
QSpacerItem *verticalSpacer;
QLabel *unconfirmedWarning;
QGroupBox *groupBox_2;
QHBoxLayout *horizontalLayout_4;
QTableView *balancesTable;
QWidget *tab_2;
QVBoxLayout *verticalLayout_4;
QGroupBox *groupBox_4;
QVBoxLayout *verticalLayout_6;
QHBoxLayout *horizontalLayout_8;
QComboBox *inputsCombo;
QHBoxLayout *horizontalLayout_15;
QLabel *label_5;
QLineEdit *sendAddressBalance;
QGroupBox *groupBox_3;
QVBoxLayout *verticalLayout_3;
QScrollArea *sendToScrollArea;
QWidget *sendToWidgets;
QVBoxLayout *sendToLayout;
QGroupBox *verticalGroupBox;
QVBoxLayout *sendAddressLayout;
QHBoxLayout *horizontalLayout_12;
QLabel *label_4;
QLineEdit *Address1;
QHBoxLayout *horizontalLayout_13;
QLabel *label_6;
QLineEdit *Amount1;
QCheckBox *Max1;
QSpacerItem *horizontalSpacer_4;
QHBoxLayout *horizontalLayout_7;
QSpacerItem *horizontalSpacer_2;
QPushButton *addAddressButton;
QSpacerItem *horizontalSpacer_3;
QSpacerItem *verticalSpacer_2;
QGroupBox *groupBox_7;
QVBoxLayout *verticalLayout_10;
QHBoxLayout *horizontalLayout_14;
QLabel *label_7;
QLineEdit *lineEdit;
QSpacerItem *horizontalSpacer_5;
QHBoxLayout *horizontalLayout_6;
QSpacerItem *horizontalSpacer;
QPushButton *sendTransactionButton;
QPushButton *cancelSendButton;
QWidget *tab_3;
QVBoxLayout *verticalLayout_5;
QGroupBox *groupBox_5;
QVBoxLayout *verticalLayout_7;
QVBoxLayout *verticalLayout_8;
QGroupBox *groupBox_6;
QVBoxLayout *verticalLayout_9;
QHBoxLayout *horizontalLayout_9;
QRadioButton *rdioZAddr;
QRadioButton *rdioTAddr;
QHBoxLayout *horizontalLayout_10;
QComboBox *listRecieveAddresses;
QPushButton *btnRecieveNewAddr;
QHBoxLayout *horizontalLayout_11;
QPlainTextEdit *txtRecieve;
QLabel *qrcodeDisplay;
QWidget *tab_4;
QVBoxLayout *verticalLayout_2;
QTableView *transactionsTable;
QMenuBar *menuBar;
QMenu *menuBalance;
QMenu *menuHelp;
QStatusBar *statusBar;
void setupUi(QMainWindow *MainWindow)
{
if (MainWindow->objectName().isEmpty())
MainWindow->setObjectName(QStringLiteral("MainWindow"));
MainWindow->resize(838, 595);
actionExit = new QAction(MainWindow);
actionExit->setObjectName(QStringLiteral("actionExit"));
actionAbout = new QAction(MainWindow);
actionAbout->setObjectName(QStringLiteral("actionAbout"));
actionSettings = new QAction(MainWindow);
actionSettings->setObjectName(QStringLiteral("actionSettings"));
centralWidget = new QWidget(MainWindow);
centralWidget->setObjectName(QStringLiteral("centralWidget"));
gridLayout_3 = new QGridLayout(centralWidget);
gridLayout_3->setSpacing(6);
gridLayout_3->setContentsMargins(11, 11, 11, 11);
gridLayout_3->setObjectName(QStringLiteral("gridLayout_3"));
tabWidget = new QTabWidget(centralWidget);
tabWidget->setObjectName(QStringLiteral("tabWidget"));
tab = new QWidget();
tab->setObjectName(QStringLiteral("tab"));
gridLayout_2 = new QGridLayout(tab);
gridLayout_2->setSpacing(6);
gridLayout_2->setContentsMargins(11, 11, 11, 11);
gridLayout_2->setObjectName(QStringLiteral("gridLayout_2"));
horizontalLayout_5 = new QHBoxLayout();
horizontalLayout_5->setSpacing(6);
horizontalLayout_5->setObjectName(QStringLiteral("horizontalLayout_5"));
groupBox = new QGroupBox(tab);
groupBox->setObjectName(QStringLiteral("groupBox"));
groupBox->setMinimumSize(QSize(300, 0));
groupBox->setFlat(false);
gridLayout = new QGridLayout(groupBox);
gridLayout->setSpacing(6);
gridLayout->setContentsMargins(11, 11, 11, 11);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
verticalLayout = new QVBoxLayout();
verticalLayout->setSpacing(6);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
horizontalLayout = new QHBoxLayout();
horizontalLayout->setSpacing(6);
horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
label = new QLabel(groupBox);
label->setObjectName(QStringLiteral("label"));
horizontalLayout->addWidget(label);
balSheilded = new QLabel(groupBox);
balSheilded->setObjectName(QStringLiteral("balSheilded"));
balSheilded->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout->addWidget(balSheilded);
verticalLayout->addLayout(horizontalLayout);
horizontalLayout_2 = new QHBoxLayout();
horizontalLayout_2->setSpacing(6);
horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2"));
label_2 = new QLabel(groupBox);
label_2->setObjectName(QStringLiteral("label_2"));
horizontalLayout_2->addWidget(label_2);
balTransparent = new QLabel(groupBox);
balTransparent->setObjectName(QStringLiteral("balTransparent"));
balTransparent->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout_2->addWidget(balTransparent);
verticalLayout->addLayout(horizontalLayout_2);
line = new QFrame(groupBox);
line->setObjectName(QStringLiteral("line"));
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
verticalLayout->addWidget(line);
horizontalLayout_3 = new QHBoxLayout();
horizontalLayout_3->setSpacing(6);
horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3"));
label_3 = new QLabel(groupBox);
label_3->setObjectName(QStringLiteral("label_3"));
QFont font;
font.setBold(true);
font.setWeight(75);
label_3->setFont(font);
horizontalLayout_3->addWidget(label_3);
balTotal = new QLabel(groupBox);
balTotal->setObjectName(QStringLiteral("balTotal"));
balTotal->setFont(font);
balTotal->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
horizontalLayout_3->addWidget(balTotal);
verticalLayout->addLayout(horizontalLayout_3);
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout->addItem(verticalSpacer);
unconfirmedWarning = new QLabel(groupBox);
unconfirmedWarning->setObjectName(QStringLiteral("unconfirmedWarning"));
unconfirmedWarning->setStyleSheet(QStringLiteral("color: red;"));
verticalLayout->addWidget(unconfirmedWarning);
gridLayout->addLayout(verticalLayout, 0, 0, 1, 1);
horizontalLayout_5->addWidget(groupBox);
groupBox_2 = new QGroupBox(tab);
groupBox_2->setObjectName(QStringLiteral("groupBox_2"));
horizontalLayout_4 = new QHBoxLayout(groupBox_2);
horizontalLayout_4->setSpacing(6);
horizontalLayout_4->setContentsMargins(11, 11, 11, 11);
horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4"));
balancesTable = new QTableView(groupBox_2);
balancesTable->setObjectName(QStringLiteral("balancesTable"));
balancesTable->setSelectionMode(QAbstractItemView::SingleSelection);
balancesTable->setSelectionBehavior(QAbstractItemView::SelectRows);
balancesTable->setCornerButtonEnabled(false);
balancesTable->horizontalHeader()->setProperty("showSortIndicator", QVariant(false));
balancesTable->horizontalHeader()->setStretchLastSection(true);
balancesTable->verticalHeader()->setVisible(false);
horizontalLayout_4->addWidget(balancesTable);
horizontalLayout_5->addWidget(groupBox_2);
gridLayout_2->addLayout(horizontalLayout_5, 0, 0, 1, 1);
tabWidget->addTab(tab, QString());
tab_2 = new QWidget();
tab_2->setObjectName(QStringLiteral("tab_2"));
verticalLayout_4 = new QVBoxLayout(tab_2);
verticalLayout_4->setSpacing(6);
verticalLayout_4->setContentsMargins(11, 11, 11, 11);
verticalLayout_4->setObjectName(QStringLiteral("verticalLayout_4"));
groupBox_4 = new QGroupBox(tab_2);
groupBox_4->setObjectName(QStringLiteral("groupBox_4"));
verticalLayout_6 = new QVBoxLayout(groupBox_4);
verticalLayout_6->setSpacing(6);
verticalLayout_6->setContentsMargins(11, 11, 11, 11);
verticalLayout_6->setObjectName(QStringLiteral("verticalLayout_6"));
horizontalLayout_8 = new QHBoxLayout();
horizontalLayout_8->setSpacing(6);
horizontalLayout_8->setObjectName(QStringLiteral("horizontalLayout_8"));
inputsCombo = new QComboBox(groupBox_4);
inputsCombo->setObjectName(QStringLiteral("inputsCombo"));
horizontalLayout_8->addWidget(inputsCombo);
verticalLayout_6->addLayout(horizontalLayout_8);
horizontalLayout_15 = new QHBoxLayout();
horizontalLayout_15->setSpacing(6);
horizontalLayout_15->setObjectName(QStringLiteral("horizontalLayout_15"));
label_5 = new QLabel(groupBox_4);
label_5->setObjectName(QStringLiteral("label_5"));
horizontalLayout_15->addWidget(label_5);
sendAddressBalance = new QLineEdit(groupBox_4);
sendAddressBalance->setObjectName(QStringLiteral("sendAddressBalance"));
sendAddressBalance->setReadOnly(true);
horizontalLayout_15->addWidget(sendAddressBalance);
verticalLayout_6->addLayout(horizontalLayout_15);
verticalLayout_4->addWidget(groupBox_4);
groupBox_3 = new QGroupBox(tab_2);
groupBox_3->setObjectName(QStringLiteral("groupBox_3"));
verticalLayout_3 = new QVBoxLayout(groupBox_3);
verticalLayout_3->setSpacing(6);
verticalLayout_3->setContentsMargins(11, 11, 11, 11);
verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3"));
sendToScrollArea = new QScrollArea(groupBox_3);
sendToScrollArea->setObjectName(QStringLiteral("sendToScrollArea"));
sendToScrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
sendToScrollArea->setWidgetResizable(true);
sendToWidgets = new QWidget();
sendToWidgets->setObjectName(QStringLiteral("sendToWidgets"));
sendToWidgets->setGeometry(QRect(0, 0, 774, 276));
sendToLayout = new QVBoxLayout(sendToWidgets);
sendToLayout->setSpacing(6);
sendToLayout->setContentsMargins(11, 11, 11, 11);
sendToLayout->setObjectName(QStringLiteral("sendToLayout"));
verticalGroupBox = new QGroupBox(sendToWidgets);
verticalGroupBox->setObjectName(QStringLiteral("verticalGroupBox"));
sendAddressLayout = new QVBoxLayout(verticalGroupBox);
sendAddressLayout->setSpacing(6);
sendAddressLayout->setContentsMargins(11, 11, 11, 11);
sendAddressLayout->setObjectName(QStringLiteral("sendAddressLayout"));
horizontalLayout_12 = new QHBoxLayout();
horizontalLayout_12->setSpacing(6);
horizontalLayout_12->setObjectName(QStringLiteral("horizontalLayout_12"));
label_4 = new QLabel(verticalGroupBox);
label_4->setObjectName(QStringLiteral("label_4"));
horizontalLayout_12->addWidget(label_4);
Address1 = new QLineEdit(verticalGroupBox);
Address1->setObjectName(QStringLiteral("Address1"));
horizontalLayout_12->addWidget(Address1);
sendAddressLayout->addLayout(horizontalLayout_12);
horizontalLayout_13 = new QHBoxLayout();
horizontalLayout_13->setSpacing(6);
horizontalLayout_13->setObjectName(QStringLiteral("horizontalLayout_13"));
label_6 = new QLabel(verticalGroupBox);
label_6->setObjectName(QStringLiteral("label_6"));
horizontalLayout_13->addWidget(label_6);
Amount1 = new QLineEdit(verticalGroupBox);
Amount1->setObjectName(QStringLiteral("Amount1"));
Amount1->setBaseSize(QSize(200, 0));
horizontalLayout_13->addWidget(Amount1);
Max1 = new QCheckBox(verticalGroupBox);
Max1->setObjectName(QStringLiteral("Max1"));
horizontalLayout_13->addWidget(Max1);
horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_13->addItem(horizontalSpacer_4);
sendAddressLayout->addLayout(horizontalLayout_13);
sendToLayout->addWidget(verticalGroupBox);
horizontalLayout_7 = new QHBoxLayout();
horizontalLayout_7->setSpacing(6);
horizontalLayout_7->setObjectName(QStringLiteral("horizontalLayout_7"));
horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_7->addItem(horizontalSpacer_2);
addAddressButton = new QPushButton(sendToWidgets);
addAddressButton->setObjectName(QStringLiteral("addAddressButton"));
addAddressButton->setBaseSize(QSize(200, 0));
horizontalLayout_7->addWidget(addAddressButton);
horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_7->addItem(horizontalSpacer_3);
sendToLayout->addLayout(horizontalLayout_7);
verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
sendToLayout->addItem(verticalSpacer_2);
sendToScrollArea->setWidget(sendToWidgets);
verticalLayout_3->addWidget(sendToScrollArea);
verticalLayout_4->addWidget(groupBox_3);
groupBox_7 = new QGroupBox(tab_2);
groupBox_7->setObjectName(QStringLiteral("groupBox_7"));
verticalLayout_10 = new QVBoxLayout(groupBox_7);
verticalLayout_10->setSpacing(6);
verticalLayout_10->setContentsMargins(11, 11, 11, 11);
verticalLayout_10->setObjectName(QStringLiteral("verticalLayout_10"));
horizontalLayout_14 = new QHBoxLayout();
horizontalLayout_14->setSpacing(6);
horizontalLayout_14->setObjectName(QStringLiteral("horizontalLayout_14"));
label_7 = new QLabel(groupBox_7);
label_7->setObjectName(QStringLiteral("label_7"));
horizontalLayout_14->addWidget(label_7);
lineEdit = new QLineEdit(groupBox_7);
lineEdit->setObjectName(QStringLiteral("lineEdit"));
lineEdit->setReadOnly(true);
horizontalLayout_14->addWidget(lineEdit);
horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_14->addItem(horizontalSpacer_5);
verticalLayout_10->addLayout(horizontalLayout_14);
verticalLayout_4->addWidget(groupBox_7);
horizontalLayout_6 = new QHBoxLayout();
horizontalLayout_6->setSpacing(6);
horizontalLayout_6->setObjectName(QStringLiteral("horizontalLayout_6"));
horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_6->addItem(horizontalSpacer);
sendTransactionButton = new QPushButton(tab_2);
sendTransactionButton->setObjectName(QStringLiteral("sendTransactionButton"));
sendTransactionButton->setBaseSize(QSize(100, 0));
sendTransactionButton->setFlat(false);
horizontalLayout_6->addWidget(sendTransactionButton);
cancelSendButton = new QPushButton(tab_2);
cancelSendButton->setObjectName(QStringLiteral("cancelSendButton"));
cancelSendButton->setBaseSize(QSize(100, 0));
horizontalLayout_6->addWidget(cancelSendButton);
verticalLayout_4->addLayout(horizontalLayout_6);
tabWidget->addTab(tab_2, QString());
tab_3 = new QWidget();
tab_3->setObjectName(QStringLiteral("tab_3"));
verticalLayout_5 = new QVBoxLayout(tab_3);
verticalLayout_5->setSpacing(6);
verticalLayout_5->setContentsMargins(11, 11, 11, 11);
verticalLayout_5->setObjectName(QStringLiteral("verticalLayout_5"));
groupBox_5 = new QGroupBox(tab_3);
groupBox_5->setObjectName(QStringLiteral("groupBox_5"));
verticalLayout_7 = new QVBoxLayout(groupBox_5);
verticalLayout_7->setSpacing(6);
verticalLayout_7->setContentsMargins(11, 11, 11, 11);
verticalLayout_7->setObjectName(QStringLiteral("verticalLayout_7"));
verticalLayout_8 = new QVBoxLayout();
verticalLayout_8->setSpacing(6);
verticalLayout_8->setObjectName(QStringLiteral("verticalLayout_8"));
groupBox_6 = new QGroupBox(groupBox_5);
groupBox_6->setObjectName(QStringLiteral("groupBox_6"));
groupBox_6->setFlat(false);
groupBox_6->setCheckable(false);
verticalLayout_9 = new QVBoxLayout(groupBox_6);
verticalLayout_9->setSpacing(6);
verticalLayout_9->setContentsMargins(11, 11, 11, 11);
verticalLayout_9->setObjectName(QStringLiteral("verticalLayout_9"));
horizontalLayout_9 = new QHBoxLayout();
horizontalLayout_9->setSpacing(6);
horizontalLayout_9->setObjectName(QStringLiteral("horizontalLayout_9"));
rdioZAddr = new QRadioButton(groupBox_6);
rdioZAddr->setObjectName(QStringLiteral("rdioZAddr"));
horizontalLayout_9->addWidget(rdioZAddr);
rdioTAddr = new QRadioButton(groupBox_6);
rdioTAddr->setObjectName(QStringLiteral("rdioTAddr"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
sizePolicy.setVerticalStretch(0);
sizePolicy.setHeightForWidth(rdioTAddr->sizePolicy().hasHeightForWidth());
rdioTAddr->setSizePolicy(sizePolicy);
horizontalLayout_9->addWidget(rdioTAddr);
verticalLayout_9->addLayout(horizontalLayout_9);
horizontalLayout_10 = new QHBoxLayout();
horizontalLayout_10->setSpacing(6);
horizontalLayout_10->setObjectName(QStringLiteral("horizontalLayout_10"));
listRecieveAddresses = new QComboBox(groupBox_6);
listRecieveAddresses->setObjectName(QStringLiteral("listRecieveAddresses"));
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(listRecieveAddresses->sizePolicy().hasHeightForWidth());
listRecieveAddresses->setSizePolicy(sizePolicy1);
horizontalLayout_10->addWidget(listRecieveAddresses);
btnRecieveNewAddr = new QPushButton(groupBox_6);
btnRecieveNewAddr->setObjectName(QStringLiteral("btnRecieveNewAddr"));
horizontalLayout_10->addWidget(btnRecieveNewAddr);
verticalLayout_9->addLayout(horizontalLayout_10);
verticalLayout_8->addWidget(groupBox_6);
horizontalLayout_11 = new QHBoxLayout();
horizontalLayout_11->setSpacing(6);
horizontalLayout_11->setObjectName(QStringLiteral("horizontalLayout_11"));
txtRecieve = new QPlainTextEdit(groupBox_5);
txtRecieve->setObjectName(QStringLiteral("txtRecieve"));
txtRecieve->setReadOnly(true);
horizontalLayout_11->addWidget(txtRecieve);
qrcodeDisplay = new QLabel(groupBox_5);
qrcodeDisplay->setObjectName(QStringLiteral("qrcodeDisplay"));
QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Expanding);
sizePolicy2.setHorizontalStretch(0);
sizePolicy2.setVerticalStretch(0);
sizePolicy2.setHeightForWidth(qrcodeDisplay->sizePolicy().hasHeightForWidth());
qrcodeDisplay->setSizePolicy(sizePolicy2);
qrcodeDisplay->setStyleSheet(QStringLiteral("background-color: #fff"));
horizontalLayout_11->addWidget(qrcodeDisplay);
verticalLayout_8->addLayout(horizontalLayout_11);
verticalLayout_7->addLayout(verticalLayout_8);
verticalLayout_5->addWidget(groupBox_5);
tabWidget->addTab(tab_3, QString());
tab_4 = new QWidget();
tab_4->setObjectName(QStringLiteral("tab_4"));
verticalLayout_2 = new QVBoxLayout(tab_4);
verticalLayout_2->setSpacing(6);
verticalLayout_2->setContentsMargins(11, 11, 11, 11);
verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
transactionsTable = new QTableView(tab_4);
transactionsTable->setObjectName(QStringLiteral("transactionsTable"));
transactionsTable->setSelectionMode(QAbstractItemView::SingleSelection);
transactionsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
verticalLayout_2->addWidget(transactionsTable);
tabWidget->addTab(tab_4, QString());
gridLayout_3->addWidget(tabWidget, 0, 0, 1, 1);
MainWindow->setCentralWidget(centralWidget);
menuBar = new QMenuBar(MainWindow);
menuBar->setObjectName(QStringLiteral("menuBar"));
menuBar->setGeometry(QRect(0, 0, 838, 21));
menuBalance = new QMenu(menuBar);
menuBalance->setObjectName(QStringLiteral("menuBalance"));
menuHelp = new QMenu(menuBar);
menuHelp->setObjectName(QStringLiteral("menuHelp"));
MainWindow->setMenuBar(menuBar);
statusBar = new QStatusBar(MainWindow);
statusBar->setObjectName(QStringLiteral("statusBar"));
MainWindow->setStatusBar(statusBar);
QWidget::setTabOrder(tabWidget, inputsCombo);
QWidget::setTabOrder(inputsCombo, sendAddressBalance);
QWidget::setTabOrder(sendAddressBalance, sendToScrollArea);
QWidget::setTabOrder(sendToScrollArea, Address1);
QWidget::setTabOrder(Address1, Amount1);
QWidget::setTabOrder(Amount1, Max1);
QWidget::setTabOrder(Max1, addAddressButton);
QWidget::setTabOrder(addAddressButton, lineEdit);
QWidget::setTabOrder(lineEdit, sendTransactionButton);
QWidget::setTabOrder(sendTransactionButton, cancelSendButton);
QWidget::setTabOrder(cancelSendButton, balancesTable);
QWidget::setTabOrder(balancesTable, rdioZAddr);
QWidget::setTabOrder(rdioZAddr, rdioTAddr);
QWidget::setTabOrder(rdioTAddr, listRecieveAddresses);
QWidget::setTabOrder(listRecieveAddresses, btnRecieveNewAddr);
QWidget::setTabOrder(btnRecieveNewAddr, txtRecieve);
QWidget::setTabOrder(txtRecieve, transactionsTable);
menuBar->addAction(menuBalance->menuAction());
menuBar->addAction(menuHelp->menuAction());
menuBalance->addAction(actionSettings);
menuBalance->addSeparator();
menuBalance->addAction(actionExit);
menuHelp->addAction(actionAbout);
retranslateUi(MainWindow);
tabWidget->setCurrentIndex(1);
QMetaObject::connectSlotsByName(MainWindow);
} // setupUi
void retranslateUi(QMainWindow *MainWindow)
{
MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
actionExit->setText(QApplication::translate("MainWindow", "Exit", nullptr));
actionAbout->setText(QApplication::translate("MainWindow", "About", nullptr));
actionSettings->setText(QApplication::translate("MainWindow", "Settings", nullptr));
groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr));
label->setText(QApplication::translate("MainWindow", "Shielded", nullptr));
balSheilded->setText(QString());
label_2->setText(QApplication::translate("MainWindow", "Transparent", nullptr));
balTransparent->setText(QString());
label_3->setText(QApplication::translate("MainWindow", "Total", nullptr));
balTotal->setText(QString());
unconfirmedWarning->setText(QApplication::translate("MainWindow", "Some transactions are not yet confirmed", nullptr));
groupBox_2->setTitle(QApplication::translate("MainWindow", "Address Balances", nullptr));
tabWidget->setTabText(tabWidget->indexOf(tab), QApplication::translate("MainWindow", "Balance", nullptr));
groupBox_4->setTitle(QApplication::translate("MainWindow", "Pay From", nullptr));
label_5->setText(QApplication::translate("MainWindow", "Address Balance:", nullptr));
groupBox_3->setTitle(QApplication::translate("MainWindow", "Send To", nullptr));
verticalGroupBox->setTitle(QApplication::translate("MainWindow", "Recipient", nullptr));
label_4->setText(QApplication::translate("MainWindow", "Address", nullptr));
Address1->setPlaceholderText(QApplication::translate("MainWindow", "Address", nullptr));
label_6->setText(QApplication::translate("MainWindow", "Amount", nullptr));
Amount1->setPlaceholderText(QApplication::translate("MainWindow", "Amount", nullptr));
Max1->setText(QApplication::translate("MainWindow", "Maximum Available", nullptr));
addAddressButton->setText(QApplication::translate("MainWindow", "Add Address", nullptr));
groupBox_7->setTitle(QApplication::translate("MainWindow", "Fees", nullptr));
label_7->setText(QApplication::translate("MainWindow", "Fee", nullptr));
lineEdit->setText(QApplication::translate("MainWindow", "0.0001 ZEC", nullptr));
sendTransactionButton->setText(QApplication::translate("MainWindow", "Send", nullptr));
cancelSendButton->setText(QApplication::translate("MainWindow", "Cancel", nullptr));
tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("MainWindow", "Send", nullptr));
groupBox_5->setTitle(QApplication::translate("MainWindow", "Recieve Address", nullptr));
groupBox_6->setTitle(QApplication::translate("MainWindow", "Address Type", nullptr));
rdioZAddr->setText(QApplication::translate("MainWindow", "z-Addr", nullptr));
rdioTAddr->setText(QApplication::translate("MainWindow", "t-Addr", nullptr));
btnRecieveNewAddr->setText(QApplication::translate("MainWindow", "New Address", nullptr));
qrcodeDisplay->setText(QString());
tabWidget->setTabText(tabWidget->indexOf(tab_3), QApplication::translate("MainWindow", "Recieve", nullptr));
tabWidget->setTabText(tabWidget->indexOf(tab_4), QApplication::translate("MainWindow", "Transactions", nullptr));
menuBalance->setTitle(QApplication::translate("MainWindow", "File", nullptr));
menuHelp->setTitle(QApplication::translate("MainWindow", "Help", nullptr));
} // retranslateUi
};
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_MAINWINDOW_H

175
ui_settings.h

@ -0,0 +1,175 @@
/********************************************************************************
** Form generated from reading UI file 'settings.ui'
**
** Created by: Qt User Interface Compiler version 5.11.2
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_SETTINGS_H
#define UI_SETTINGS_H
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Settings
{
public:
QVBoxLayout *verticalLayout;
QTabWidget *tabWidget;
QWidget *tab;
QVBoxLayout *verticalLayout_3;
QVBoxLayout *verticalLayout_2;
QGroupBox *groupBox;
QGridLayout *gridLayout;
QLabel *label_3;
QLineEdit *rpcuser;
QLabel *label;
QLineEdit *hostname;
QLineEdit *port;
QLabel *label_4;
QLineEdit *rpcpassword;
QLabel *label_2;
QSpacerItem *verticalSpacer;
QWidget *tab_2;
QDialogButtonBox *buttonBox;
void setupUi(QDialog *Settings)
{
if (Settings->objectName().isEmpty())
Settings->setObjectName(QStringLiteral("Settings"));
Settings->resize(400, 300);
Settings->setModal(true);
verticalLayout = new QVBoxLayout(Settings);
verticalLayout->setObjectName(QStringLiteral("verticalLayout"));
tabWidget = new QTabWidget(Settings);
tabWidget->setObjectName(QStringLiteral("tabWidget"));
tab = new QWidget();
tab->setObjectName(QStringLiteral("tab"));
verticalLayout_3 = new QVBoxLayout(tab);
verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3"));
verticalLayout_2 = new QVBoxLayout();
verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2"));
groupBox = new QGroupBox(tab);
groupBox->setObjectName(QStringLiteral("groupBox"));
gridLayout = new QGridLayout(groupBox);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
gridLayout->setContentsMargins(10, -1, -1, -1);
label_3 = new QLabel(groupBox);
label_3->setObjectName(QStringLiteral("label_3"));
label_3->setMinimumSize(QSize(60, 0));
gridLayout->addWidget(label_3, 4, 0, 1, 1);
rpcuser = new QLineEdit(groupBox);
rpcuser->setObjectName(QStringLiteral("rpcuser"));
gridLayout->addWidget(rpcuser, 5, 0, 1, 1);
label = new QLabel(groupBox);
label->setObjectName(QStringLiteral("label"));
label->setMinimumSize(QSize(60, 0));
gridLayout->addWidget(label, 0, 0, 1, 1);
hostname = new QLineEdit(groupBox);
hostname->setObjectName(QStringLiteral("hostname"));
gridLayout->addWidget(hostname, 1, 0, 1, 1);
port = new QLineEdit(groupBox);
port->setObjectName(QStringLiteral("port"));
gridLayout->addWidget(port, 3, 0, 1, 1);
label_4 = new QLabel(groupBox);
label_4->setObjectName(QStringLiteral("label_4"));
label_4->setMinimumSize(QSize(60, 0));
gridLayout->addWidget(label_4, 6, 0, 1, 1);
rpcpassword = new QLineEdit(groupBox);
rpcpassword->setObjectName(QStringLiteral("rpcpassword"));
gridLayout->addWidget(rpcpassword, 7, 0, 1, 1);
label_2 = new QLabel(groupBox);
label_2->setObjectName(QStringLiteral("label_2"));
label_2->setMinimumSize(QSize(60, 0));
gridLayout->addWidget(label_2, 2, 0, 1, 1);
verticalLayout_2->addWidget(groupBox);
verticalLayout_3->addLayout(verticalLayout_2);
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout_3->addItem(verticalSpacer);
tabWidget->addTab(tab, QString());
tab_2 = new QWidget();
tab_2->setObjectName(QStringLiteral("tab_2"));
tabWidget->addTab(tab_2, QString());
verticalLayout->addWidget(tabWidget);
buttonBox = new QDialogButtonBox(Settings);
buttonBox->setObjectName(QStringLiteral("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
verticalLayout->addWidget(buttonBox);
QWidget::setTabOrder(tabWidget, hostname);
QWidget::setTabOrder(hostname, port);
QWidget::setTabOrder(port, rpcuser);
QWidget::setTabOrder(rpcuser, rpcpassword);
retranslateUi(Settings);
QObject::connect(buttonBox, SIGNAL(accepted()), Settings, SLOT(accept()));
QObject::connect(buttonBox, SIGNAL(rejected()), Settings, SLOT(reject()));
tabWidget->setCurrentIndex(0);
QMetaObject::connectSlotsByName(Settings);
} // setupUi
void retranslateUi(QDialog *Settings)
{
Settings->setWindowTitle(QApplication::translate("Settings", "Settings", nullptr));
groupBox->setTitle(QApplication::translate("Settings", "zcashd connection", nullptr));
label_3->setText(QApplication::translate("Settings", "RPC Username", nullptr));
label->setText(QApplication::translate("Settings", "Host", nullptr));
hostname->setPlaceholderText(QApplication::translate("Settings", "127.0.0.1", nullptr));
port->setPlaceholderText(QApplication::translate("Settings", "8232", nullptr));
label_4->setText(QApplication::translate("Settings", "RPC Password", nullptr));
label_2->setText(QApplication::translate("Settings", "Port", nullptr));
tabWidget->setTabText(tabWidget->indexOf(tab), QApplication::translate("Settings", "Connection", nullptr));
tabWidget->setTabText(tabWidget->indexOf(tab_2), QApplication::translate("Settings", "Options", nullptr));
} // retranslateUi
};
namespace Ui {
class Settings: public Ui_Settings {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_SETTINGS_H

9
unspentoutput.cpp

@ -0,0 +1,9 @@
#include "unspentoutput.h"
UnspentOutput::UnspentOutput(QString address, QString txid, QString amount, int confirmations)
{
this->address = address;
this->txid = txid;
this->amount = amount;
this->confirmations = confirmations;
}

18
unspentoutput.h

@ -0,0 +1,18 @@
#ifndef UNSPENTOUTPUT_H
#define UNSPENTOUTPUT_H
#include "precompiled.h"
class UnspentOutput
{
public:
UnspentOutput(QString address, QString txid, QString amount, int confirmations);
QString address;
QString txid;
QString amount;
int confirmations;
};
#endif // UNSPENTOUTPUT_H

70
zcash-qt-wallet.pro

@ -0,0 +1,70 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-10-05T09:54:45
#
#-------------------------------------------------
QT += core gui network
CONFIG += precompile_header
PRECOMPILED_HEADER = precompiled.h
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = zcash-qt-wallet
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
INCLUDEPATH += 3rdparty/
RESOURCES = application.qrc
MOC_DIR = bin
OBJECTS_DIR = bin
CONFIG += c++14
SOURCES += \
main.cpp \
mainwindow.cpp \
rpc.cpp \
balancestablemodel.cpp \
unspentoutput.cpp \
3rdparty/qrcode/BitBuffer.cpp \
3rdparty/qrcode/QrCode.cpp \
3rdparty/qrcode/QrSegment.cpp \
settings.cpp \
sendtab.cpp \
txtablemodel.cpp \
transactionitem.cpp
HEADERS += \
mainwindow.h \
precompiled.h \
rpc.h \
balancestablemodel.h \
unspentoutput.h \
3rdparty/qrcode/BitBuffer.hpp \
3rdparty/qrcode/QrCode.hpp \
3rdparty/qrcode/QrSegment.hpp \
3rdparty/json/json.hpp \
settings.h \
txtablemodel.h \
transactionitem.h
FORMS += \
mainwindow.ui \
settings.ui \
about.ui \
confirm.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
Loading…
Cancel
Save