Merge pull request #100 from strider-paff-shell/denio

Denio
This commit is contained in:
Denio
2020-04-09 20:11:08 +02:00
committed by GitHub
8 changed files with 579 additions and 758 deletions

1
.gitignore vendored
View File

@@ -40,3 +40,4 @@ silentdragonlite.pro.user.4.10-pre1
silentdragonlite silentdragonlite
silentdragonlite_plugin_import.cpp silentdragonlite_plugin_import.cpp
silentdragonlite_resource.rc silentdragonlite_resource.rc
SilentDragonLite

View File

@@ -6,85 +6,99 @@
#include "controller.h" #include "controller.h"
AddressBookModel::AddressBookModel(QTableView *parent) AddressBookModel::AddressBookModel(QTableView *parent) : QAbstractTableModel(parent)
: QAbstractTableModel(parent) { {
headers << tr("Label") << tr("Address"); headers << tr("Label") << tr("Address");
this->parent = parent; this->parent = parent;
loadData(); loadData();
} }
AddressBookModel::~AddressBookModel() { AddressBookModel::~AddressBookModel()
{
saveData(); saveData();
} }
void AddressBookModel::saveData() { void AddressBookModel::saveData()
{
// Save column positions // Save column positions
QSettings().setValue("addresstablegeometry", parent->horizontalHeader()->saveState()); QSettings().setValue(
"addresstablegeometry",
parent->horizontalHeader()->saveState()
);
} }
void AddressBookModel::loadData() { void AddressBookModel::loadData()
{
labels = AddressBook::getInstance()->getAllAddressLabels(); labels = AddressBook::getInstance()->getAllAddressLabels();
parent->horizontalHeader()->restoreState(
parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray()); QSettings().value(
"addresstablegeometry"
).toByteArray()
);
} }
void AddressBookModel::addNewLabel(QString label, QString addr) { void AddressBookModel::addNewLabel(QString label, QString addr)
{
//labels.push_back(QPair<QString, QString>(label, addr)); //labels.push_back(QPair<QString, QString>(label, addr));
AddressBook::getInstance()->addAddressLabel(label, addr); AddressBook::getInstance()->addAddressLabel(label, addr);
labels.clear(); labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels(); labels = AddressBook::getInstance()->getAllAddressLabels();
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1)); dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged(); layoutChanged();
} }
void AddressBookModel::removeItemAt(int row) { void AddressBookModel::removeItemAt(int row)
{
if (row >= labels.size()) if (row >= labels.size())
return; return;
AddressBook::getInstance()->removeAddressLabel(labels[row].first, labels[row].second); AddressBook::getInstance()->removeAddressLabel(labels[row].first, labels[row].second);
labels.clear(); labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels(); labels = AddressBook::getInstance()->getAllAddressLabels();
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1)); dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged(); layoutChanged();
} }
QPair<QString, QString> AddressBookModel::itemAt(int row) { QPair<QString, QString> AddressBookModel::itemAt(int row)
if (row >= labels.size()) return QPair<QString, QString>(); {
if (row >= labels.size())
return QPair<QString, QString>();
return labels.at(row); return labels.at(row);
} }
int AddressBookModel::rowCount(const QModelIndex&) const { int AddressBookModel::rowCount(const QModelIndex&) const
{
return labels.size(); return labels.size();
} }
int AddressBookModel::columnCount(const QModelIndex&) const { int AddressBookModel::columnCount(const QModelIndex&) const
{
return headers.size(); return headers.size();
} }
QVariant AddressBookModel::data(const QModelIndex &index, int role) const { QVariant AddressBookModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) { {
switch(index.column()) { if (role == Qt::DisplayRole)
{
switch(index.column())
{
case 0: return labels.at(index.row()).first; case 0: return labels.at(index.row()).first;
case 1: return labels.at(index.row()).second; case 1: return labels.at(index.row()).second;
} }
} }
return QVariant(); return QVariant();
} }
QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
return headers.at(section); return headers.at(section);
}
return QVariant(); return QVariant();
} }
@@ -93,28 +107,27 @@ QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation,
//=============== //===============
// AddressBook // AddressBook
//=============== //===============
void AddressBook::open(MainWindow* parent, QLineEdit* target) { void AddressBook::open(MainWindow* parent, QLineEdit* target)
{
QDialog d(parent); QDialog d(parent);
Ui_addressBook ab; Ui_addressBook ab;
ab.setupUi(&d); ab.setupUi(&d);
Settings::saveRestore(&d); Settings::saveRestore(&d);
QRegExpValidator v(QRegExp(Settings::labelRegExp), ab.label); QRegExpValidator v(QRegExp(Settings::labelRegExp), ab.label);
ab.label->setValidator(&v); ab.label->setValidator(&v);
AddressBookModel model(ab.addresses); AddressBookModel model(ab.addresses);
ab.addresses->setModel(&model); ab.addresses->setModel(&model);
// If there is no target, the we'll call the button "Ok", else "Pick" // If there is no target, the we'll call the button "Ok", else "Pick"
if (target != nullptr) { if (target != nullptr)
ab.buttonBox->button(QDialogButtonBox::Ok)->setText(QObject::tr("Pick")); ab.buttonBox->button(QDialogButtonBox::Ok)->setText(QObject::tr("Pick"));
}
// Connect the dialog's closing to updating the label address completor // Connect the dialog's closing to updating the label address completor
QObject::connect(&d, &QDialog::finished, [=] (auto) { parent->updateLabels(); }); QObject::connect(&d, &QDialog::finished, [=] (auto) { parent->updateLabels(); });
// If there is a target then make it the addr for the "Add to" button // If there is a target then make it the addr for the "Add to" button
if (target != nullptr && Settings::isValidAddress(target->text())) { if (target != nullptr && Settings::isValidAddress(target->text()))
{
ab.addr->setText(target->text()); ab.addr->setText(target->text());
ab.label->setFocus(); ab.label->setFocus();
} }
@@ -124,26 +137,37 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
auto addr = ab.addr->text().trimmed(); auto addr = ab.addr->text().trimmed();
QString newLabel = ab.label->text(); QString newLabel = ab.label->text();
if (addr.isEmpty() || newLabel.isEmpty()) { if (addr.isEmpty() || newLabel.isEmpty())
QMessageBox::critical(parent, QObject::tr("Address or Label Error"), {
QObject::tr("Address or Label cannot be empty"), QMessageBox::Ok); QMessageBox::critical(
parent,
QObject::tr("Address or Label Error"),
QObject::tr("Address or Label cannot be empty"),
QMessageBox::Ok
);
return; return;
} }
// Test if address is valid. // Test if address is valid.
if (!Settings::isValidAddress(addr)) { if (!Settings::isValidAddress(addr))
QMessageBox::critical(parent, QObject::tr("Address Format Error"), {
QObject::tr("%1 doesn't seem to be a valid hush address.") QMessageBox::critical(
.arg(addr), parent,
QMessageBox::Ok); QObject::tr("Address Format Error"),
QObject::tr("%1 doesn't seem to be a valid hush address.").arg(addr),
QMessageBox::Ok
);
return; return;
} }
// Don't allow duplicate address labels. // Don't allow duplicate address labels.
if (!getInstance()->getAddressForLabel(newLabel).isEmpty()) { if (!getInstance()->getAddressForLabel(newLabel).isEmpty())
QMessageBox::critical(parent, QObject::tr("Label Error"), {
QObject::tr("The label '%1' already exists. Please remove the existing label.") QMessageBox::critical(
.arg(newLabel), parent,
QMessageBox::Ok); QObject::tr("Label Error"),
QObject::tr("The label '%1' already exists. Please remove the existing label.").arg(newLabel),
QMessageBox::Ok
);
return; return;
} }
@@ -153,21 +177,30 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
// Import Button // Import Button
QObject::connect(ab.btnImport, &QPushButton::clicked, [&] () { QObject::connect(ab.btnImport, &QPushButton::clicked, [&] () {
// Get the import file name. // Get the import file name.
auto fileName = QFileDialog::getOpenFileUrl(&d, QObject::tr("Import Address Book"), QUrl(), auto fileName = QFileDialog::getOpenFileUrl(
"CSV file (*.csv)"); &d, QObject::tr("Import Address Book"),
QUrl(),
"CSV file (*.csv)"
);
if (fileName.isEmpty()) if (fileName.isEmpty())
return; return;
QFile file(fileName.toLocalFile()); QFile file(fileName.toLocalFile());
if (!file.open(QIODevice::ReadOnly)) { if (!file.open(QIODevice::ReadOnly))
QMessageBox::information(&d, QObject::tr("Unable to open file"), file.errorString()); {
QMessageBox::information(
&d,
QObject::tr("Unable to open file"),
file.errorString()
);
return; return;
} }
QTextStream in(&file); QTextStream in(&file);
QString line; QString line;
int numImported = 0; int numImported = 0;
while (in.readLineInto(&line)) { while (in.readLineInto(&line))
{
QStringList items = line.split(","); QStringList items = line.split(",");
if (items.size() != 2) if (items.size() != 2)
continue; continue;
@@ -180,8 +213,11 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
numImported++; numImported++;
} }
QMessageBox::information(&d, QObject::tr("Address Book Import Done"), QMessageBox::information(
QObject::tr("Imported %1 new Address book entries").arg(numImported)); &d,
QObject::tr("Address Book Import Done"),
QObject::tr("Imported %1 new Address book entries").arg(numImported)
);
}); });
auto fnSetTargetLabelAddr = [=] (QLineEdit* target, QString label, QString addr) { auto fnSetTargetLabelAddr = [=] (QLineEdit* target, QString label, QString addr) {
@@ -194,7 +230,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (!target) if (!target)
return; return;
if (index.row() < 0) return; if (index.row() < 0)
return;
QString lbl = model.itemAt(index.row()).first; QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second; QString addr = model.itemAt(index.row()).second;
@@ -206,20 +243,19 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
ab.addresses->setContextMenuPolicy(Qt::CustomContextMenu); ab.addresses->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ab.addresses, &QTableView::customContextMenuRequested, [&] (QPoint pos) { QObject::connect(ab.addresses, &QTableView::customContextMenuRequested, [&] (QPoint pos) {
QModelIndex index = ab.addresses->indexAt(pos); QModelIndex index = ab.addresses->indexAt(pos);
if (index.row() < 0)
if (index.row() < 0) return; return;
QString lbl = model.itemAt(index.row()).first; QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second; QString addr = model.itemAt(index.row()).second;
QMenu menu(parent); QMenu menu(parent);
if (target != nullptr) { if (target != nullptr)
menu.addAction("Pick", [&] () { menu.addAction("Pick", [&] () {
d.accept(); d.accept();
fnSetTargetLabelAddr(target, lbl, addr); fnSetTargetLabelAddr(target, lbl, addr);
}); });
}
menu.addAction(QObject::tr("Copy address"), [&] () { menu.addAction(QObject::tr("Copy address"), [&] () {
QGuiApplication::clipboard()->setText(addr); QGuiApplication::clipboard()->setText(addr);
@@ -248,27 +284,30 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
//============= //=============
// AddressBook singleton class // AddressBook singleton class
//============= //=============
AddressBook* AddressBook::getInstance() { AddressBook* AddressBook::getInstance()
{
if (!instance) if (!instance)
instance = new AddressBook(); instance = new AddressBook();
return instance; return instance;
} }
AddressBook::AddressBook() { AddressBook::AddressBook()
{
readFromStorage(); readFromStorage();
} }
void AddressBook::readFromStorage() { void AddressBook::readFromStorage()
{
QFile file(AddressBook::writeableFile()); QFile file(AddressBook::writeableFile());
if (file.exists()) { if (file.exists())
{
allLabels.clear(); allLabels.clear();
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file QDataStream in(&file); // read the data serialized from the file
QString version; QString version;
in >> version >> allLabels; in >> version >> allLabels;
file.close(); file.close();
} }
@@ -282,7 +321,8 @@ void AddressBook::readFromStorage() {
// } // }
} }
void AddressBook::writeToStorage() { void AddressBook::writeToStorage()
{
QFile file(AddressBook::writeableFile()); QFile file(AddressBook::writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate); file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file QDataStream out(&file); // we will serialize the data into the file
@@ -290,42 +330,44 @@ void AddressBook::writeToStorage() {
file.close(); file.close();
} }
QString AddressBook::writeableFile() { QString AddressBook::writeableFile()
{
auto filename = QStringLiteral("addresslabels.dat"); auto filename = QStringLiteral("addresslabels.dat");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists()) if (!dir.exists())
QDir().mkpath(dir.absolutePath()); QDir().mkpath(dir.absolutePath());
if (Settings::getInstance()->isTestnet()) { if (Settings::getInstance()->isTestnet())
return dir.filePath("testnet-" % filename); return dir.filePath("testnet-" % filename);
} else {
else
return dir.filePath(filename); return dir.filePath(filename);
}
} }
// Add a new address/label to the database // Add a new address/label to the database
void AddressBook::addAddressLabel(QString label, QString address) { void AddressBook::addAddressLabel(QString label, QString address)
{
Q_ASSERT(Settings::isValidAddress(address)); Q_ASSERT(Settings::isValidAddress(address));
// First, remove any existing label // First, remove any existing label
// Iterate over the list and remove the label/address // Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) { for (int i=0; i < allLabels.size(); i++)
if (allLabels[i].first == label) { if (allLabels[i].first == label)
removeAddressLabel(allLabels[i].first, allLabels[i].second); removeAddressLabel(allLabels[i].first, allLabels[i].second);
}
}
allLabels.push_back(QPair<QString, QString>(label, address)); allLabels.push_back(QPair<QString, QString>(label, address));
writeToStorage(); writeToStorage();
} }
// Remove a new address/label from the database // Remove a new address/label from the database
void AddressBook::removeAddressLabel(QString label, QString address) { void AddressBook::removeAddressLabel(QString label, QString address)
{
// Iterate over the list and remove the label/address // Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) { for (int i=0; i < allLabels.size(); i++)
if (allLabels[i].first == label && allLabels[i].second == address) { {
if (allLabels[i].first == label && allLabels[i].second == address)
{
allLabels.removeAt(i); allLabels.removeAt(i);
writeToStorage(); writeToStorage();
return; return;
@@ -333,10 +375,13 @@ void AddressBook::removeAddressLabel(QString label, QString address) {
} }
} }
void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel) { void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel)
{
// Iterate over the list and update the label/address // Iterate over the list and update the label/address
for (int i = 0; i < allLabels.size(); i++) { for (int i = 0; i < allLabels.size(); i++)
if (allLabels[i].first == oldlabel && allLabels[i].second == address) { {
if (allLabels[i].first == oldlabel && allLabels[i].second == address)
{
allLabels[i].first = newlabel; allLabels[i].first = newlabel;
writeToStorage(); writeToStorage();
return; return;
@@ -345,42 +390,46 @@ void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabe
} }
// Read all addresses // Read all addresses
const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels() { const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels()
if (allLabels.isEmpty()) { {
if (allLabels.isEmpty())
readFromStorage(); readFromStorage();
}
return allLabels; return allLabels;
} }
// Get the label for an address // Get the label for an address
QString AddressBook::getLabelForAddress(QString addr) { QString AddressBook::getLabelForAddress(QString addr)
for (auto i : allLabels) { {
for (auto i : allLabels)
if (i.second == addr) if (i.second == addr)
return i.first; return i.first;
}
return ""; return "";
} }
// Get the address for a label // Get the address for a label
QString AddressBook::getAddressForLabel(QString label) { QString AddressBook::getAddressForLabel(QString label)
for (auto i: allLabels) { {
for (auto i: allLabels)
if (i.first == label) if (i.first == label)
return i.second; return i.second;
}
return ""; return "";
} }
QString AddressBook::addLabelToAddress(QString addr) { QString AddressBook::addLabelToAddress(QString addr)
{
QString label = AddressBook::getInstance()->getLabelForAddress(addr); QString label = AddressBook::getInstance()->getLabelForAddress(addr);
if (!label.isEmpty()) if (!label.isEmpty())
return label + "/" + addr; return label + "/" + addr;
else else
return addr; return addr;
} }
QString AddressBook::addressFromAddressLabel(const QString& lblAddr) { QString AddressBook::addressFromAddressLabel(const QString& lblAddr)
{
return lblAddr.trimmed().split("/").last(); return lblAddr.trimmed().split("/").last();
} }

View File

@@ -2,29 +2,31 @@
#include "addressbook.h" #include "addressbook.h"
#include "settings.h" #include "settings.h"
AddressCombo::AddressCombo(QWidget* parent) : AddressCombo::AddressCombo(QWidget* parent): QComboBox(parent)
QComboBox(parent) { {}
}
QString AddressCombo::itemText(int i) { QString AddressCombo::itemText(int i)
{
QString txt = QComboBox::itemText(i); QString txt = QComboBox::itemText(i);
return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed()); return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed());
} }
QString AddressCombo::currentText() { QString AddressCombo::currentText()
{
QString txt = QComboBox::currentText(); QString txt = QComboBox::currentText();
return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed()); return AddressBook::addressFromAddressLabel(txt.split("(")[0].trimmed());
} }
void AddressCombo::setCurrentText(const QString& text) { void AddressCombo::setCurrentText(const QString& text)
for (int i=0; i < count(); i++) { {
if (itemText(i) == text) { for (int i=0; i < count(); i++)
if (itemText(i) == text)
QComboBox::setCurrentIndex(i); QComboBox::setCurrentIndex(i);
}
}
} }
void AddressCombo::addItem(const QString& text, CAmount bal) { void AddressCombo::addItem(const QString& text, CAmount bal)
{
QString txt = AddressBook::addLabelToAddress(text); QString txt = AddressBook::addLabelToAddress(text);
if (bal.toqint64() > 0) if (bal.toqint64() > 0)
txt = txt % "(" % bal.toDecimalhushString() % ")"; txt = txt % "(" % bal.toDecimalhushString() % ")";
@@ -32,7 +34,8 @@ void AddressCombo::addItem(const QString& text, CAmount bal) {
QComboBox::addItem(txt); QComboBox::addItem(txt);
} }
void AddressCombo::insertItem(int index, const QString& text, CAmount bal) { void AddressCombo::insertItem(int index, const QString& text, CAmount bal)
{
QString txt = AddressBook::addLabelToAddress(text) % QString txt = AddressBook::addLabelToAddress(text) %
"(" % bal.toDecimalhushString() % ")"; "(" % bal.toDecimalhushString() % ")";
QComboBox::insertItem(index, txt); QComboBox::insertItem(index, txt);

View File

@@ -3,9 +3,8 @@
#include "settings.h" #include "settings.h"
#include "camount.h" #include "camount.h"
BalancesTableModel::BalancesTableModel(QObject *parent) BalancesTableModel::BalancesTableModel(QObject *parent): QAbstractTableModel(parent)
: QAbstractTableModel(parent) { {}
}
void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QString> taddrs, void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QString> taddrs,
const QMap<QString, CAmount> balances, const QList<UnspentOutput> outputs) const QMap<QString, CAmount> balances, const QList<UnspentOutput> outputs)
@@ -29,21 +28,19 @@ void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QSt
modeldata = new QList<std::tuple<QString, CAmount>>(); modeldata = new QList<std::tuple<QString, CAmount>>();
std::for_each(balances.keyBegin(), balances.keyEnd(), [=, &anyz, &anyt] (auto keyIt) { std::for_each(balances.keyBegin(), balances.keyEnd(), [=, &anyz, &anyt] (auto keyIt) {
modeldata->push_back(std::make_tuple(keyIt, balances.value(keyIt))); modeldata->push_back(std::make_tuple(keyIt, balances.value(keyIt)));
if (Settings::isZAddress(keyIt)) { if (Settings::isZAddress(keyIt))
anyz = true; anyz = true;
} else if (Settings::isTAddress(keyIt)) {
else if (Settings::isTAddress(keyIt))
anyt = true; anyt = true;
}
}); });
// Add all addresses that have no balances, if there are no existing addresses // Add all addresses that have no balances, if there are no existing addresses
if (!anyz && zaddrs.length() > 0) { if (!anyz && zaddrs.length() > 0)
modeldata->push_back(std::make_tuple(zaddrs[0], CAmount::fromqint64(0))); modeldata->push_back(std::make_tuple(zaddrs[0], CAmount::fromqint64(0)));
}
if (!anyt && taddrs.length() > 0) { if (!anyt && taddrs.length() > 0)
modeldata->push_back(std::make_tuple(taddrs[0], CAmount::fromqint64(0))); modeldata->push_back(std::make_tuple(taddrs[0], CAmount::fromqint64(0)));
}
// And then update the data // And then update the data
dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1)); dataChanged(index(0, 0), index(modeldata->size()-1, columnCount(index(0,0))-1));
@@ -53,19 +50,17 @@ void BalancesTableModel::setNewData(const QList<QString> zaddrs, const QList<QSt
layoutChanged(); layoutChanged();
} }
BalancesTableModel::~BalancesTableModel() { BalancesTableModel::~BalancesTableModel()
{
delete modeldata; delete modeldata;
delete unspentOutputs; delete unspentOutputs;
} }
int BalancesTableModel::rowCount(const QModelIndex&) const int BalancesTableModel::rowCount(const QModelIndex&) const
{ {
if (modeldata == nullptr) { if (modeldata == nullptr)
if (loading) return (loading) ? 1: 0;
return 1;
else
return 0;
}
return modeldata->size(); return modeldata->size();
} }
@@ -76,25 +71,31 @@ int BalancesTableModel::columnCount(const QModelIndex&) const
QVariant BalancesTableModel::data(const QModelIndex &index, int role) const QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
{ {
if (loading) { if (loading)
if (role == Qt::DisplayRole) return (role == Qt::DisplayRole) ? "Loading..." : QVariant();
/*if (role == Qt::DisplayRole)
return "Loading..."; return "Loading...";
else else
return QVariant(); return QVariant();*/
}
if (role == Qt::TextAlignmentRole && index.column() == 1) return QVariant(Qt::AlignRight | Qt::AlignVCenter); if (role == Qt::TextAlignmentRole && index.column() == 1)
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
if (role == Qt::ForegroundRole) { if (role == Qt::ForegroundRole) {
// If any of the UTXOs for this address has zero confirmations, paint it in red // 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())); const auto& addr = std::get<0>(modeldata->at(index.row()));
for (auto unconfirmedOutput : *unspentOutputs) { for (auto unconfirmedOutput : *unspentOutputs)
if (unconfirmedOutput.address == addr && {
(!unconfirmedOutput.spendable || unconfirmedOutput.pending)) { if (
unconfirmedOutput.address == addr &&
(!unconfirmedOutput.spendable || unconfirmedOutput.pending)
)
{
QBrush b; QBrush b;
b.setColor(Qt::red); b.setColor(Qt::red);
return b; return b;
} }
} }
// Else, just return the default brush // Else, just return the default brush
@@ -103,17 +104,21 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
return b; return b;
} }
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole)
switch (index.column()) { {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row()))); switch (index.column())
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString(); {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
} }
} }
if(role == Qt::ToolTipRole) { if(role == Qt::ToolTipRole)
switch (index.column()) { {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row()))); switch (index.column())
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString(); {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return std::get<1>(modeldata->at(index.row())).toDecimalhushString();
} }
} }
@@ -123,11 +128,13 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation, int role) const QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{ {
if (role == Qt::TextAlignmentRole && section == 1) { if (role == Qt::TextAlignmentRole && section == 1)
{
return QVariant(Qt::AlignRight | Qt::AlignVCenter); return QVariant(Qt::AlignRight | Qt::AlignVCenter);
} }
if (role == Qt::FontRole) { if (role == Qt::FontRole)
{
QFont f; QFont f;
f.setBold(true); f.setBold(true);
return f; return f;
@@ -136,13 +143,16 @@ QVariant BalancesTableModel::headerData(int section, Qt::Orientation orientation
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
if (orientation == Qt::Horizontal) { if (orientation == Qt::Horizontal)
switch (section) { {
case 0: return tr("Address"); switch (section)
case 1: return tr("Amount"); {
default: return QVariant(); case 0: return tr("Address");
case 1: return tr("Amount");
default: return QVariant();
} }
} }
return QVariant(); return QVariant();
} }

View File

@@ -1,204 +1,230 @@
#include "camount.h" #include "camount.h"
#include "settings.h" #include "settings.h"
#include "precompiled.h" #include "precompiled.h"
const int NUMPLACES = 8; const int NUMPLACES = 8;
const qint64 COIN = 100000000; const qint64 COIN = 100000000;
double CAmount::toDecimalDouble() const { double CAmount::toDecimalDouble() const
{
return static_cast<double>(this->amount) / COIN; return static_cast<double>(this->amount) / COIN;
} }
QString CAmount::toDecimalString() const { QString CAmount::toDecimalString() const
if (amount < 0) { {
if (amount < 0)
{
CAmount negative(-1 * this->amount); CAmount negative(-1 * this->amount);
return "-" + negative.toDecimalString(); return "-" + negative.toDecimalString();
} }
int wholePart = amount / COIN; int wholePart = amount / COIN;
int decimalPart = amount % COIN; int decimalPart = amount % COIN;
QString r = QString::number(wholePart); QString r = QString::number(wholePart);
if (decimalPart > 0) { if (decimalPart > 0)
{
QString decimalPartStr = QString::number(decimalPart); QString decimalPartStr = QString::number(decimalPart);
r = r + "." + decimalPartStr.rightJustified(NUMPLACES, '0'); r = r + "." + decimalPartStr.rightJustified(NUMPLACES, '0');
// Trim tailing 0s // Trim tailing 0s
while (r.right(1) == "0") { while (r.right(1) == "0")
r = r.left(r.length() - 1); r = r.left(r.length() - 1);
}
} }
return r; return r;
} }
QString CAmount::toDecimalUSDString() const { double CAmount::getDblAmount() const
double dblAmount = static_cast<double>(this->amount) / COIN; {
return static_cast<double>(this->amount) / COIN;
}
QString CAmount::toDecimalUSDString() const
{
double price = Settings::getInstance()->getZECPrice(); double price = Settings::getInstance()->getZECPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalEURString() const { QString CAmount::toDecimalEURString() const
double dblAmount = static_cast<double>(this->amount) / COIN; {
double price = Settings::getInstance()->getEURPrice(); double price = Settings::getInstance()->getEURPrice();
return QLocale(QLocale::German).toString(this->getDblAmount() * price, 'f', 2) + "";
return QLocale(QLocale::German).toString(dblAmount*price, 'f', 2) + "";
} }
QString CAmount::toDecimalBTCString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalBTCString() const
{
double price = Settings::getInstance()->getBTCPrice(); double price = Settings::getInstance()->getBTCPrice();
return "BTC " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 9);
return "BTC " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 9);
} }
QString CAmount::toDecimalCNYString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalCNYString() const
{
double price = Settings::getInstance()->getCNYPrice(); double price = Settings::getInstance()->getCNYPrice();
return "¥ /元 " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "¥ /元 " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalRUBString() const { QString CAmount::toDecimalRUBString() const
double dblAmount = static_cast<double>(this->amount) / COIN; {
double price = Settings::getInstance()->getRUBPrice(); double price = Settings::getInstance()->getRUBPrice();
return "" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalCADString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalCADString() const
{
double price = Settings::getInstance()->getCADPrice(); double price = Settings::getInstance()->getCADPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalSGDString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalSGDString() const
{
double price = Settings::getInstance()->getSGDPrice(); double price = Settings::getInstance()->getSGDPrice();
return "$ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "$ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalCHFString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalCHFString() const
{
double price = Settings::getInstance()->getCHFPrice(); double price = Settings::getInstance()->getCHFPrice();
return "CHF " + QLocale(QLocale::German).toString(this->getDblAmount() * price, 'f', 2);
return "CHF " + QLocale(QLocale::German).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalINRString() const {
double dblAmount = static_cast<double>(this->amount) / COIN; QString CAmount::toDecimalINRString() const
{
double price = Settings::getInstance()->getINRPrice(); double price = Settings::getInstance()->getINRPrice();
return "" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalGBPString() const { QString CAmount::toDecimalGBPString() const
double dblAmount = static_cast<double>(this->amount) / COIN; {
double price = Settings::getInstance()->getGBPPrice(); double price = Settings::getInstance()->getGBPPrice();
return "£ " + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return "£ " + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalAUDString() const { QString CAmount::toDecimalAUDString() const
double dblAmount = static_cast<double>(this->amount) / COIN; {
double price = Settings::getInstance()->getAUDPrice(); double price = Settings::getInstance()->getAUDPrice();
return " $" + QLocale(QLocale::English).toString(this->getDblAmount() * price, 'f', 2);
return " $" + QLocale(QLocale::English).toString(dblAmount*price, 'f', 2);
} }
QString CAmount::toDecimalhushString() const { QString CAmount::toDecimalhushString() const
{
return this->toDecimalString() % " " % Settings::getTokenName(); return this->toDecimalString() % " " % Settings::getTokenName();
} }
QString CAmount::toDecimalhushUSDString() const { QString CAmount::toDecimalhushUSDString() const
{
auto usdString = this->toDecimalUSDString(); auto usdString = this->toDecimalUSDString();
if (!usdString.isEmpty()) if (!usdString.isEmpty())
return this->toDecimalhushString() % " (" % usdString % ")"; return this->toDecimalhushString() % " (" % usdString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushEURString() const { QString CAmount::toDecimalhushEURString() const
{
auto eurString = this->toDecimalEURString(); auto eurString = this->toDecimalEURString();
if (!eurString.isEmpty()) if (!eurString.isEmpty())
return this->toDecimalhushString() % " (" % eurString % ")"; return this->toDecimalhushString() % " (" % eurString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushBTCString() const { QString CAmount::toDecimalhushBTCString() const
{
auto btcString = this->toDecimalBTCString(); auto btcString = this->toDecimalBTCString();
if (!btcString.isEmpty()) if (!btcString.isEmpty())
return this->toDecimalhushString() % " (" % btcString % ")"; return this->toDecimalhushString() % " (" % btcString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushCNYString() const { QString CAmount::toDecimalhushCNYString() const
{
auto cnyString = this->toDecimalCNYString(); auto cnyString = this->toDecimalCNYString();
if (!cnyString.isEmpty()) if (!cnyString.isEmpty())
return this->toDecimalhushString() % " (" % cnyString % ")"; return this->toDecimalhushString() % " (" % cnyString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushRUBString() const { QString CAmount::toDecimalhushRUBString() const
{
auto rubString = this->toDecimalRUBString(); auto rubString = this->toDecimalRUBString();
if (!rubString.isEmpty()) if (!rubString.isEmpty())
return this->toDecimalhushString() % " (" % rubString % ")"; return this->toDecimalhushString() % " (" % rubString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushCADString() const { QString CAmount::toDecimalhushCADString() const
{
auto cadString = this->toDecimalCADString(); auto cadString = this->toDecimalCADString();
if (!cadString.isEmpty()) if (!cadString.isEmpty())
return this->toDecimalhushString() % " (" % cadString % ")"; return this->toDecimalhushString() % " (" % cadString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushSGDString() const { QString CAmount::toDecimalhushSGDString() const
{
auto sgdString = this->toDecimalSGDString(); auto sgdString = this->toDecimalSGDString();
if (!sgdString.isEmpty()) if (!sgdString.isEmpty())
return this->toDecimalhushString() % " (" % sgdString % ")"; return this->toDecimalhushString() % " (" % sgdString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushCHFString() const { QString CAmount::toDecimalhushCHFString() const
{
auto chfString = this->toDecimalCHFString(); auto chfString = this->toDecimalCHFString();
if (!chfString.isEmpty()) if (!chfString.isEmpty())
return this->toDecimalhushString() % " (" % chfString % ")"; return this->toDecimalhushString() % " (" % chfString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushINRString() const { QString CAmount::toDecimalhushINRString() const
{
auto inrString = this->toDecimalINRString(); auto inrString = this->toDecimalINRString();
if (!inrString.isEmpty()) if (!inrString.isEmpty())
return this->toDecimalhushString() % " (" % inrString % ")"; return this->toDecimalhushString() % " (" % inrString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushGBPString() const { QString CAmount::toDecimalhushGBPString() const
{
auto gbpString = this->toDecimalGBPString(); auto gbpString = this->toDecimalGBPString();
if (!gbpString.isEmpty()) if (!gbpString.isEmpty())
return this->toDecimalhushString() % " (" % gbpString % ")"; return this->toDecimalhushString() % " (" % gbpString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
QString CAmount::toDecimalhushAUDString() const { QString CAmount::toDecimalhushAUDString() const
{
auto audString = this->toDecimalAUDString(); auto audString = this->toDecimalAUDString();
if (!audString.isEmpty()) if (!audString.isEmpty())
return this->toDecimalhushString() % " (" % audString % ")"; return this->toDecimalhushString() % " (" % audString % ")";
else else
return this->toDecimalhushString(); return this->toDecimalhushString();
} }
CAmount CAmount::fromDecimalString(QString decimalString) { CAmount CAmount::fromDecimalString(QString decimalString)
{
auto amtParts = decimalString.split("."); auto amtParts = decimalString.split(".");
qint64 r = amtParts[0].toULongLong() * COIN; qint64 r = amtParts[0].toULongLong() * COIN;
if (amtParts.length() == 2) { if (amtParts.length() == 2)
{
auto trailingZeros = QString("0").repeated(NUMPLACES - amtParts[1].length()); auto trailingZeros = QString("0").repeated(NUMPLACES - amtParts[1].length());
r += QString(amtParts[1] + trailingZeros).toULongLong(); r += QString(amtParts[1] + trailingZeros).toULongLong();
} }

View File

@@ -26,6 +26,7 @@ public:
double toDecimalDouble() const; double toDecimalDouble() const;
QString toDecimalString() const; QString toDecimalString() const;
double getDblAmount() const;
QString toDecimalUSDString() const; QString toDecimalUSDString() const;
QString toDecimalEURString() const; QString toDecimalEURString() const;
QString toDecimalBTCString() const; QString toDecimalBTCString() const;

View File

@@ -5,42 +5,47 @@
#include "firsttimewizard.h" #include "firsttimewizard.h"
#include "ui_createhushconfdialog.h" #include "ui_createhushconfdialog.h"
#include "controller.h" #include "controller.h"
#include "../lib/silentdragonlitelib.h" #include "../lib/silentdragonlitelib.h"
#include "precompiled.h" #include "precompiled.h"
using json = nlohmann::json; using json = nlohmann::json;
ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc) { ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
{
this->main = main; this->main = main;
this->rpc = rpc; this->rpc = rpc;
d = new QDialog(main); d = new QDialog(main);
connD = new Ui_ConnectionDialog(); connD = new Ui_ConnectionDialog();
connD->setupUi(d); connD->setupUi(d);
QPixmap logo(":/img/res/logobig.gif"); QPixmap logo(":/img/res/logobig.gif");
connD->topIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation)); connD->topIcon->setBasePixmap(
logo.scaled(
256,
256,
Qt::KeepAspectRatio,
Qt::SmoothTransformation
)
);
isSyncing = new QAtomicInteger<bool>(); isSyncing = new QAtomicInteger<bool>();
} }
ConnectionLoader::~ConnectionLoader() { ConnectionLoader::~ConnectionLoader()
{
delete isSyncing; delete isSyncing;
delete connD; delete connD;
delete d; delete d;
} }
void ConnectionLoader::loadConnection() { void ConnectionLoader::loadConnection()
{
QTimer::singleShot(1, [=]() { this->doAutoConnect(); }); QTimer::singleShot(1, [=]() { this->doAutoConnect(); });
if (!Settings::getInstance()->isHeadless()) if (!Settings::getInstance()->isHeadless())
d->exec(); d->exec();
} }
void ConnectionLoader::doAutoConnect() { void ConnectionLoader::doAutoConnect()
{
qDebug() << "Doing autoconnect"; qDebug() << "Doing autoconnect";
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig()); auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
config->dangerous = true; config->dangerous = true;
config->server = Settings::getInstance()->getSettings().server; config->server = Settings::getInstance()->getSettings().server;
@@ -49,16 +54,24 @@ void ConnectionLoader::doAutoConnect() {
main->logger->write(QObject::tr("Attempting to initialize library with ") + config->server); main->logger->write(QObject::tr("Attempting to initialize library with ") + config->server);
// Check to see if there's an existing wallet // Check to see if there's an existing wallet
if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str())) { if (litelib_wallet_exists(Settings::getDefaultChainName().toStdString().c_str()))
{
main->logger->write(QObject::tr("Using existing wallet.")); main->logger->write(QObject::tr("Using existing wallet."));
char* resp = litelib_initialize_existing(config->dangerous, config->server.toStdString().c_str()); char* resp = litelib_initialize_existing(
config->dangerous,
config->server.toStdString().c_str()
);
QString response = litelib_process_response(resp); QString response = litelib_process_response(resp);
if (response.toUpper().trimmed() != "OK") { if (response.toUpper().trimmed() != "OK")
{
showError(response); showError(response);
return; return;
} }
} else {
}
else
{
main->logger->write(QObject::tr("Create/restore wallet.")); main->logger->write(QObject::tr("Create/restore wallet."));
createOrRestore(config->dangerous, config->server); createOrRestore(config->dangerous, config->server);
d->show(); d->show();
@@ -72,7 +85,6 @@ void ConnectionLoader::doAutoConnect() {
// If success, set the connection // If success, set the connection
main->logger->write("Connection is online."); main->logger->write("Connection is online.");
connection->setInfo(reply); connection->setInfo(reply);
isSyncing = new QAtomicInteger<bool>(); isSyncing = new QAtomicInteger<bool>();
isSyncing->store(true); isSyncing->store(true);
@@ -80,10 +92,8 @@ void ConnectionLoader::doAutoConnect() {
syncTimer = new QTimer(main); syncTimer = new QTimer(main);
connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) { connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) {
isSyncing->store(false); isSyncing->store(false);
// Cancel the timer // Cancel the timer
syncTimer->deleteLater(); syncTimer->deleteLater();
// When sync is done, set the connection // When sync is done, set the connection
this->doRPCSetConnection(connection); this->doRPCSetConnection(connection);
}); });
@@ -94,10 +104,13 @@ void ConnectionLoader::doAutoConnect() {
if (isSyncing != nullptr && isSyncing->load()) { if (isSyncing != nullptr && isSyncing->load()) {
// Get the sync status // Get the sync status
connection->doRPC("syncstatus", "", [=](json reply) { connection->doRPC("syncstatus", "", [=](json reply) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end()) { if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end())
{
qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>(); qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>();
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>(); qint64 total = reply["total_blocks"].get<json::number_unsigned_t>();
me->showInformation("Synced " + QString::number(synced) + " / " + QString::number(total)); me->showInformation(
"Synced " + QString::number(synced) + " / " + QString::number(total)
);
} }
}, },
[=](QString err) { [=](QString err) {
@@ -114,104 +127,110 @@ void ConnectionLoader::doAutoConnect() {
}); });
} }
void ConnectionLoader::createOrRestore(bool dangerous, QString server) { void ConnectionLoader::createOrRestore(bool dangerous, QString server)
{
// Close the startup dialog, since we'll be showing the wizard // Close the startup dialog, since we'll be showing the wizard
d->hide(); d->hide();
// Create a wizard // Create a wizard
FirstTimeWizard wizard(dangerous, server); FirstTimeWizard wizard(dangerous, server);
wizard.exec(); wizard.exec();
} }
void ConnectionLoader::doRPCSetConnection(Connection* conn) { void ConnectionLoader::doRPCSetConnection(Connection* conn)
{
qDebug() << "Connectionloader finished, setting connection"; qDebug() << "Connectionloader finished, setting connection";
rpc->setConnection(conn); rpc->setConnection(conn);
d->accept(); d->accept();
QTimer::singleShot(1, [=]() { delete this; }); QTimer::singleShot(1, [=]() { delete this; });
} }
Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config) { Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config)
{
return new Connection(main, config); return new Connection(main, config);
} }
// Update the UI with the status // Update the UI with the status
void ConnectionLoader::showInformation(QString info, QString detail) { void ConnectionLoader::showInformation(QString info, QString detail)
{
connD->status->setText(info); connD->status->setText(info);
connD->statusDetail->setText(detail); connD->statusDetail->setText(detail);
} }
/** /**
* Show error will close the loading dialog and show an error. * Show error will close the loading dialog and show an error.
*/ */
void ConnectionLoader::showError(QString explanation) { void ConnectionLoader::showError(QString explanation)
{
rpc->noConnection(); rpc->noConnection();
QMessageBox::critical(
QMessageBox::critical(main, QObject::tr("Connection Error"), explanation, QMessageBox::Ok); main,
QObject::tr("Connection Error"),
explanation,
QMessageBox::Ok
);
d->close(); d->close();
} }
QString litelib_process_response(char* resp) { QString litelib_process_response(char* resp)
{
char* resp_copy = new char[strlen(resp) + 1]; char* resp_copy = new char[strlen(resp) + 1];
strcpy(resp_copy, resp); //a safer version of strcpy
strncpy(resp_copy, resp, strlen(resp)+1);
litelib_rust_free_string(resp); litelib_rust_free_string(resp);
QString reply = QString::fromStdString(resp_copy); QString reply = QString::fromStdString(resp_copy);
memset(resp_copy, '-', strlen(resp_copy)); memset(resp_copy, '-', strlen(resp_copy));
delete[] resp_copy; delete[] resp_copy;
return reply; return reply;
} }
/*********************************************************************************** /***********************************************************************************
* Connection, Executor and Callback Class * Connection, Executor and Callback Class
************************************************************************************/ ************************************************************************************/
void Executor::run() { void Executor::run()
{
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str()); char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
//qDebug() << "RPC Reply=" << reply; //qDebug() << "RPC Reply=" << reply;
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); auto parsed = json::parse(
if (parsed.is_discarded() || parsed.is_null()) { reply.toStdString().c_str(),
nullptr,
false
);
if (parsed.is_discarded() || parsed.is_null())
emit handleError(reply); emit handleError(reply);
} else {
else
emit responseReady(parsed); emit responseReady(parsed);
}
} }
void Callback::processRPCCallback(json resp) { void Callback::processRPCCallback(json resp)
{
this->cb(resp); this->cb(resp);
// Destroy self // Destroy self
delete this; delete this;
} }
void Callback::processError(QString resp) { void Callback::processError(QString resp)
{
this->errCb(resp); this->errCb(resp);
// Destroy self // Destroy self
delete this; delete this;
} }
Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf) { Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf)
{
this->config = conf; this->config = conf;
this->main = m; this->main = m;
// Register the JSON type as a type that can be passed between signals and slots. // Register the JSON type as a type that can be passed between signals and slots.
qRegisterMetaType<json>("json"); qRegisterMetaType<json>("json");
} }
void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb, void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb, const std::function<void(QString)>& errCb)
const std::function<void(QString)>& errCb) { {
if (shutdownInProgress) { if (shutdownInProgress)
// Ignoring RPC because shutdown in progress // Ignoring RPC because shutdown in progress
return; return;
}
//qDebug() << "Doing RPC: " << cmd; //qDebug() << "Doing RPC: " << cmd;
@@ -223,24 +242,27 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
QObject::connect(runner, &Executor::responseReady, c, &Callback::processRPCCallback); QObject::connect(runner, &Executor::responseReady, c, &Callback::processRPCCallback);
QObject::connect(runner, &Executor::handleError, c, &Callback::processError); QObject::connect(runner, &Executor::handleError, c, &Callback::processError);
QThreadPool::globalInstance()->start(runner); QThreadPool::globalInstance()->start(runner);
} }
void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb) { void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb)
{
doRPC(cmd, args, cb, [=] (QString err) { doRPC(cmd, args, cb, [=] (QString err) {
this->showTxError(err); this->showTxError(err);
}); });
} }
void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb) { void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb)
{
doRPC(cmd, args, cb, [=] (auto) { doRPC(cmd, args, cb, [=] (auto) {
// Ignored error handling // Ignored error handling
}); });
} }
void Connection::showTxError(const QString& error) { void Connection::showTxError(const QString& error)
if (error.isNull()) return; {
if (error.isNull())
return;
// Prevent multiple dialog boxes from showing, because they're all called async // Prevent multiple dialog boxes from showing, because they're all called async
static bool shown = false; static bool shown = false;
@@ -248,14 +270,19 @@ void Connection::showTxError(const QString& error) {
return; return;
shown = true; shown = true;
QMessageBox::critical(main, QObject::tr("Transaction Error"), QObject::tr("There was an error sending the transaction. The error was:") + "\n\n" QMessageBox::critical(
+ error, QMessageBox::StandardButton::Ok); main,
QObject::tr("Transaction Error"),
QObject::tr("There was an error sending the transaction. The error was:") + "\n\n" + error,
QMessageBox::StandardButton::Ok
);
shown = false; shown = false;
} }
/** /**
* Prevent all future calls from going through * Prevent all future calls from going through
*/ */
void Connection::shutdown() { void Connection::shutdown()
{
shutdownInProgress = true; shutdownInProgress = true;
} }

View File

@@ -9,7 +9,8 @@
using json = nlohmann::json; using json = nlohmann::json;
Controller::Controller(MainWindow* main) { Controller::Controller(MainWindow* main)
{
auto cl = new ConnectionLoader(main, this); auto cl = new ConnectionLoader(main, this);
// Execute the load connection async, so we can set up the rest of RPC properly. // Execute the load connection async, so we can set up the rest of RPC properly.
@@ -49,24 +50,24 @@ Controller::Controller(MainWindow* main) {
zrpc = new LiteInterface(); zrpc = new LiteInterface();
} }
Controller::~Controller() { Controller::~Controller()
{
delete timer; delete timer;
delete txTimer; delete txTimer;
delete transactionsTableModel; delete transactionsTableModel;
delete balancesTableModel; delete balancesTableModel;
delete model; delete model;
delete zrpc; delete zrpc;
} }
// Called when a connection to hushd is available. // Called when a connection to hushd is available.
void Controller::setConnection(Connection* c) { void Controller::setConnection(Connection* c)
if (c == nullptr) return; {
if (c == nullptr)
return;
this->zrpc->setConnection(c); this->zrpc->setConnection(c);
ui->statusBar->showMessage(""); ui->statusBar->showMessage("");
// If we're allowed to get the Hush Price, get the prices // If we're allowed to get the Hush Price, get the prices
@@ -81,473 +82,152 @@ void Controller::setConnection(Connection* c) {
// where we need to immediately refresh // where we need to immediately refresh
refresh(true); refresh(true);
// Create Sietch zdust addr at startup. // Create Sietch zdust addr at startup.
zrpc->createNewSietchZaddr( [=] (json reply) { for(uint8_t i = 0; i < 10; i++)
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt"); {
QFile file(path); zrpc->createNewSietchZaddr( [=] (json reply) {
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]); QString path = "";
if(!file.open(QIODevice::WriteOnly)){ if(i > 0)
file.close(); path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
} else {
QTextStream out(&file); out << zdust.toUtf8(); else
file.close(); path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly))
{
file.close();
}
else
{
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
});
} }
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
} }
// Build the RPC JSON Parameters for this tx // Build the RPC JSON Parameters for this tx
void Controller::fillTxJsonParams(json& allRecepients, Tx tx) { void Controller::fillTxJsonParams(json& allRecepients, Tx tx)
{
Q_ASSERT(allRecepients.is_array()); Q_ASSERT(allRecepients.is_array());
// Construct the JSON params // Construct the JSON params
json rec = json::object(); json rec = json::object();
json dust = json::object();
json dust1 = json::object();
json dust2 = json::object();
json dust3 = json::object();
json dust4 = json::object();
json dust5 = json::object();
json dust6 = json::object();
json dust7 = json::object();
json dust8 = json::object();
json dust9 = json::object();
// Create Sietch zdust addr again to not use it twice. //creating the JSON dust parameters in a std::vector to iterate over there during tx
zrpc->createNewSietchZaddr( [=] (json reply) { std::vector<json> dust(10);
dust.resize(10, json::object());
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) { // Create Sietch zdust addr again to not use it twice.
for(uint8_t i = 0; i < 10; i++)
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt"); {
QFile file(path); zrpc->createNewSietchZaddr( [=] (json reply) {
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]); QString path = "";
if(!file.open(QIODevice::WriteOnly)){ if(i > 0)
file.close(); path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
zrpc->createNewSietchZaddr( [=] (json reply) {
QString path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile file(path);
QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
if(!file.open(QIODevice::WriteOnly)){
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
// Set sietch zdust addr to json.
QString path= (QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)) + QString("/Sietch.txt");
QFile inputFile(path);
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QString line = in.readLine();
dust["address"] = line.toStdString();
}
inputFile.close();
}
QString path1= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch1.txt");
QFile inputFile1(path1);
if (inputFile1.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile1);
while (!in.atEnd())
{
QString line = in.readLine();
QString zdust = line;
dust1["address"] = zdust.toStdString();
}
inputFile1.close();
}
QString path2= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch2.txt");
QFile inputFile2(path2);
if (inputFile2.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile2);
while (!in.atEnd())
{
QString line = in.readLine();
dust2["address"] = line.toStdString();
}
inputFile2.close();
}
QString path3= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch3.txt");
QFile inputFile3(path3);
if (inputFile3.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile3);
while (!in.atEnd())
{
QString line = in.readLine();
dust3["address"] = line.toStdString();
}
inputFile3.close();
}
QString path4= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch4.txt");
QFile inputFile4(path4);
if (inputFile4.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile4);
while (!in.atEnd())
{
QString line = in.readLine();
dust4["address"] = line.toStdString();
}
inputFile4.close();
}
QString path5= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch5.txt");
QFile inputFile5(path5);
if (inputFile5.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile5);
while (!in.atEnd())
{
QString line = in.readLine();
dust5["address"] = line.toStdString();
}
inputFile5.close();
}
QString path6= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch6.txt");
QFile inputFile6(path6);
if (inputFile6.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile6);
while (!in.atEnd())
{
QString line = in.readLine();
dust6["address"] = line.toStdString();
}
inputFile6.close();
}
QString path7= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch7.txt");
QFile inputFile7(path7);
if (inputFile7.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile7);
while (!in.atEnd())
{
QString line = in.readLine();
dust7["address"] = line.toStdString();
}
inputFile7.close();
}
QString path8= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch8.txt");
QFile inputFile8(path8);
if (inputFile8.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile8);
while (!in.atEnd())
{
QString line = in.readLine();
dust8["address"] = line.toStdString();
}
inputFile.close();
}
QString path9= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch9.txt");
QFile inputFile9(path9);
if (inputFile9.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile9);
while (!in.atEnd())
{
QString line = in.readLine();
dust9["address"] = line.toStdString();
}
inputFile9.close();
}
// Dust amt/memo, construct the JSON
dust["amount"] = 0;
dust["memo"] = "";
dust1["amount"] = 0;
dust1["memo"] = "";
dust2["amount"] = 0;
dust2["memo"] = "";
dust3["amount"] = 0;
dust3["memo"] = "";
dust4["amount"] = 0;
dust4["memo"] = "";
dust5["amount"] = 0;
dust5["memo"] = "";
dust6["amount"] = 0;
dust6["memo"] = "";
dust7["amount"] = 0;
dust7["memo"] = "";
dust8["amount"] = 0;
dust8["memo"] = "";
dust9["amount"] = 0;
dust9["memo"] = "";
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++) {
auto toAddr = tx.toAddrs[i];
rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount.toqint64();
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString();
allRecepients.push_back(rec) ;
}
int decider = qrand() % ((100 + 1)-1)+ 1;// random int between 1 and 100
//50% chance of adding another zdust, shuffle.
if(decider % 4 == 3) { else
allRecepients.insert(std::begin(allRecepients),{dust,dust1,dust2,dust3,dust4,dust5,dust6,dust7,dust8}) ; path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
QFile file(path);
}else { QString zdust = QString::fromStdString(reply.get<json::array_t>()[0]);
allRecepients.insert(std::begin(allRecepients),{dust,dust1,dust2,dust3,dust4,dust5,dust6,dust7,dust8,dust9}) ; if(!file.open(QIODevice::WriteOnly))
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device()); {
file.close();
} else {
QTextStream out(&file); out << zdust.toUtf8();
file.close();
}
} );
}
// Set sietch zdust addr to json.
for(uint8_t i = 0; i < 10; i++)
{
QString path = "";
if(i > 0)
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch") + QString(i) + QString(".txt");
else
path= QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QString("/Sietch.txt");
QFile inputFile(path);
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QString line = in.readLine();
dust.at(i)["address"] = line.toStdString();
}
inputFile.close();
} }
}
// Dust amt/memo, construct the JSON
for(uint8_t i = 0; i < 10; i++)
{
printf("Setting amount and memo to 0 for dust%i \n", i);
dust.at(i)["amount"] = 0;
dust.at(i)["memo"] = "";
}
// For each addr/amt/memo, construct the JSON and also build the confirm dialog box
for (int i=0; i < tx.toAddrs.size(); i++)
{
auto toAddr = tx.toAddrs[i];
rec["address"] = toAddr.addr.toStdString();
rec["amount"] = toAddr.amount.toqint64();
if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty())
rec["memo"] = toAddr.memo.toStdString();
allRecepients.push_back(rec) ;
}
int decider = qrand() % ((100 + 1)-1)+ 1;// random int between 1 and 100
//50% chance of adding another zdust, shuffle.
if(decider % 4 == 3)
allRecepients.insert(std::begin(allRecepients), {
dust.at(0),
dust.at(1),
dust.at(2),
dust.at(3),
dust.at(4),
dust.at(5),
dust.at(6),
dust.at(7),
dust.at(8)
}) ;
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
else
allRecepients.insert(std::begin(allRecepients), {
dust.at(0),
dust.at(1),
dust.at(2),
dust.at(3),
dust.at(4),
dust.at(5),
dust.at(6),
dust.at(7),
dust.at(8),
dust.at(9)
});
// std::shuffle(allRecepients.begin(),allRecepients.end(),std::random_device());
} }
void Controller::noConnection() { void Controller::noConnection()
{
QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
main->statusIcon->setPixmap(i.pixmap(16, 16)); main->statusIcon->setPixmap(i.pixmap(16, 16));
main->statusIcon->setToolTip(""); main->statusIcon->setToolTip("");
@@ -576,21 +256,23 @@ void Controller::noConnection() {
} }
/// This will refresh all the balance data from hushd /// This will refresh all the balance data from hushd
void Controller::refresh(bool force) { void Controller::refresh(bool force)
{
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
getInfoThenRefresh(force); getInfoThenRefresh(force);
} }
void Controller::processInfo(const json& info) { void Controller::processInfo(const json& info)
{
// Testnet? // Testnet?
QString chainName; QString chainName;
if (!info["chain_name"].is_null()) { if (!info["chain_name"].is_null())
{
chainName = QString::fromStdString(info["chain_name"].get<json::string_t>()); chainName = QString::fromStdString(info["chain_name"].get<json::string_t>());
Settings::getInstance()->setTestnet(chainName == "test"); Settings::getInstance()->setTestnet(chainName == "test");
}; }
QString version = QString::fromStdString(info["version"].get<json::string_t>()); QString version = QString::fromStdString(info["version"].get<json::string_t>());
Settings::getInstance()->sethushdVersion(version); Settings::getInstance()->sethushdVersion(version);
@@ -600,7 +282,8 @@ void Controller::processInfo(const json& info) {
main->disableRecurring(); main->disableRecurring();
} }
void Controller::getInfoThenRefresh(bool force) { void Controller::getInfoThenRefresh(bool force)
{
if (!zrpc->haveConnection()) if (!zrpc->haveConnection())
return noConnection(); return noConnection();
@@ -608,38 +291,59 @@ void Controller::getInfoThenRefresh(bool force) {
zrpc->fetchInfo([=] (const json& reply) { zrpc->fetchInfo([=] (const json& reply) {
prevCallSucceeded = true; prevCallSucceeded = true;
int curBlock = reply["latest_block_height"].get<json::number_integer_t>(); int curBlock = reply["latest_block_height"].get<json::number_integer_t>();
int longestchain = reply["longestchain"].get<json::number_integer_t>(); int longestchain = reply["longestchain"].get<json::number_integer_t>();
int notarized = reply["notarized"].get<json::number_integer_t>(); int notarized = reply["notarized"].get<json::number_integer_t>();
int difficulty = reply["difficulty"].get<json::number_integer_t>(); int difficulty = reply["difficulty"].get<json::number_integer_t>();
int blocks_until_halving= 340000 - curBlock; int blocks_until_halving= 340000 - curBlock;
int halving_days = int halving_days = (blocks_until_halving * 150) / (60*60*24) ;
(blocks_until_halving * 150) / (60*60*24) ;
bool doUpdate = force || (model->getLatestBlock() != curBlock); bool doUpdate = force || (model->getLatestBlock() != curBlock);
model->setLatestBlock(curBlock); model->setLatestBlock(curBlock);
if (
if (Settings::getInstance()->get_currency_name() == "EUR" || Settings::getInstance()->get_currency_name() == "CHF" || Settings::getInstance()->get_currency_name() == "RUB") { Settings::getInstance()->get_currency_name() == "EUR" ||
ui->blockHeight->setText("Block: " + QLocale(QLocale::German).toString(curBlock)); Settings::getInstance()->get_currency_name() == "CHF" ||
ui->last_notarized->setText("Block: " + QLocale(QLocale::German).toString(notarized)); Settings::getInstance()->get_currency_name() == "RUB"
ui->longestchain->setText("Block: " + QLocale(QLocale::German).toString(longestchain)); )
ui->difficulty->setText(QLocale(QLocale::German).toString(difficulty)); {
ui->halvingTime->setText((QLocale(QLocale::German).toString(blocks_until_halving)) + " Blocks or , " + (QLocale(QLocale::German).toString(halving_days) + " days" )); ui->blockHeight->setText(
"Block: " + QLocale(QLocale::German).toString(curBlock)
);
ui->last_notarized->setText(
"Block: " + QLocale(QLocale::German).toString(notarized)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::German).toString(longestchain)
);
ui->difficulty->setText(
QLocale(QLocale::German).toString(difficulty)
);
ui->halvingTime->setText(
(QLocale(QLocale::German).toString(blocks_until_halving)) +
" Blocks or , " + (QLocale(QLocale::German).toString(halving_days) + " days" )
);
} }
else { else
ui->blockHeight->setText("Block: " + QLocale(QLocale::English).toString(curBlock)); {
ui->last_notarized->setText("Block: " + QLocale(QLocale::English).toString(notarized)); ui->blockHeight->setText(
ui->longestchain->setText("Block: " + QLocale(QLocale::English).toString(longestchain)); "Block: " + QLocale(QLocale::English).toString(curBlock)
ui->difficulty->setText(QLocale(QLocale::English).toString(difficulty)); );
ui->halvingTime->setText((QLocale(QLocale::English).toString(blocks_until_halving)) + " Blocks or , " + (QLocale(QLocale::English).toString(halving_days) + " days" )); ui->last_notarized->setText(
"Block: " + QLocale(QLocale::English).toString(notarized)
);
ui->longestchain->setText(
"Block: " + QLocale(QLocale::English).toString(longestchain)
);
ui->difficulty->setText(
QLocale(QLocale::English).toString(difficulty)
);
ui->halvingTime->setText(
(QLocale(QLocale::English).toString(blocks_until_halving)) +
" Blocks or , " + (QLocale(QLocale::English).toString(halving_days) + " days" )
);
} }
ui->Version->setText(QString::fromStdString(reply["version"].get<json::string_t>())); ui->Version->setText(QString::fromStdString(reply["version"].get<json::string_t>()));
ui->Vendor->setText(QString::fromStdString(reply["vendor"].get<json::string_t>())); ui->Vendor->setText(QString::fromStdString(reply["vendor"].get<json::string_t>()));
main->logger->write(QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false") ); main->logger->write(QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false") );
// Connected, so display checkmark. // Connected, so display checkmark.