Compare commits

...

15 Commits

Author SHA1 Message Date
adityapk00 7139de3f9a Update windows installer logos 5 years ago
adityapk00 6348bc09bd Merge branch 'master' into recurring 5 years ago
adityapk00 93ac8d11df Wire up dialog 5 years ago
adityapk00 7e7eb909b9 merge master 5 years ago
adityapk00 9eaeda27b6 Address view model 5 years ago
adityapk00 f2425f41b2 Refactor 5 years ago
adityapk00 dd71b8e261 Add recurring payments to file 5 years ago
adityapk00 1cb12cfd96 recurring item serialization 5 years ago
adityapk00 de5c3de7e0 Fix check state 5 years ago
adityapk00 d26831363b USD/ZEC switch 5 years ago
adityapk00 a3aace1777 Add history to recurring payments 5 years ago
adityapk00 4aa63a3db2 Make singleton 5 years ago
adityapk00 6cb2f34c72 Update RPI at confirm 5 years ago
adityapk00 25072c010e Add to confirm dialog 5 years ago
adityapk00 107a46ebe9 Save created recurring info 5 years ago
  1. BIN
      res/wxsbanner.bmp
  2. BIN
      res/wxsdialog.bmp
  3. 6
      src/addressbook.h
  4. 2
      src/balancestablemodel.cpp
  5. 16
      src/confirm.ui
  6. 12
      src/mainwindow.cpp
  7. 8
      src/mainwindow.h
  8. 10
      src/mainwindow.ui
  9. 304
      src/recurring.cpp
  10. 86
      src/recurring.h
  11. 6
      src/recurringdialog.ui
  12. 3
      src/rpc.cpp
  13. 93
      src/sendtab.cpp
  14. 16
      src/settings.cpp
  15. 4
      src/settings.h
  16. 2
      src/txtablemodel.cpp

BIN
res/wxsbanner.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

BIN
res/wxsdialog.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 KiB

After

Width:  |  Height:  |  Size: 451 KiB

6
src/addressbook.h

@ -10,9 +10,9 @@ class AddressBookModel : public QAbstractTableModel {
public:
AddressBookModel(QTableView* parent);
~AddressBookModel();
void addNewLabel(QString label, QString addr);
void removeItemAt(int row);
void addNewLabel(QString label, QString addr);
void removeItemAt(int row);
QPair<QString, QString> itemAt(int row);
int rowCount(const QModelIndex &parent) const;

2
src/balancestablemodel.cpp

@ -94,7 +94,7 @@ QVariant BalancesTableModel::data(const QModelIndex &index, int role) const
if(role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return AddressBook::addLabelToAddress(std::get<0>(modeldata->at(index.row())));
case 1: return Settings::getUSDFormat(std::get<1>(modeldata->at(index.row())));
case 1: return Settings::getUSDFromZecAmount(std::get<1>(modeldata->at(index.row())));
}
}

16
src/confirm.ui

@ -133,6 +133,22 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="grpRecurring">
<property name="title">
<string>Recurring Payment</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="lblRecurringDesc">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

12
src/mainwindow.cpp

@ -45,6 +45,10 @@ MainWindow::MainWindow(QWidget *parent) :
rpc->checkForUpdate(false);
});
QObject::connect(ui->action_Recurring_Payments, &QAction::triggered, [=]() {
Recurring::getInstance()->showRecurringDialog();
});
// Pay Zcash URI
QObject::connect(ui->actionPay_URI, &QAction::triggered, this, &MainWindow::payZcashURI);
@ -566,7 +570,7 @@ void MainWindow::addressBook() {
void MainWindow::donate() {
// Set up a donation to me :)
removeExtraAddresses();
clearSendForm();
ui->Address1->setText(Settings::getDonationAddr(
Settings::getInstance()->isSaplingAddress(ui->inputsCombo->currentText())));
@ -794,7 +798,7 @@ void MainWindow::payZcashURI() {
}
// Now, set the fields on the send tab
removeExtraAddresses();
clearSendForm();
ui->Address1->setText(addr);
ui->Address1->setCursorPosition(0);
ui->Amount1->setText(QString::number(amount));
@ -997,7 +1001,7 @@ void MainWindow::setupBalancesTab() {
// If there's a to address, add that as well
if (!to.isEmpty()) {
// Remember to clear any existing address fields, because we are creating a new transaction.
this->removeExtraAddresses();
this->clearSendForm();
ui->Address1->setText(to);
}
@ -1415,6 +1419,8 @@ MainWindow::~MainWindow()
delete rpc;
delete labelCompleter;
delete sendTxRecurringInfo;
delete loadingMovie;
delete logger;

8
src/mainwindow.h

@ -2,7 +2,9 @@
#define MAINWINDOW_H
#include "precompiled.h"
#include "logger.h"
#include "recurring.h"
// Forward declare to break circular dependency.
class RPC;
@ -78,10 +80,10 @@ private:
void setupSettingsModal();
void setupStatusBar();
void removeExtraAddresses();
void clearSendForm();
Tx createTxFromSendPage();
bool confirmTx(Tx tx);
bool confirmTx(Tx tx, RecurringPaymentInfo* rpi);
void turnstileDoMigration(QString fromAddr = "");
void turnstileProgress();
@ -123,6 +125,8 @@ private:
RPC* rpc = nullptr;
QCompleter* labelCompleter = nullptr;
RecurringPaymentInfo* sendTxRecurringInfo = nullptr;
QMovie* loadingMovie;
};

10
src/mainwindow.ui

@ -346,8 +346,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>920</width>
<height>301</height>
<width>928</width>
<height>353</height>
</rect>
</property>
<layout class="QVBoxLayout" name="sendToLayout">
@ -1069,6 +1069,7 @@
</property>
<addaction name="action_Address_Book"/>
<addaction name="actionSettings"/>
<addaction name="action_Recurring_Payments"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menu_Edit"/>
@ -1161,6 +1162,11 @@
<string>Ctrl+M</string>
</property>
</action>
<action name="action_Recurring_Payments">
<property name="text">
<string>&amp;Recurring Payments</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

304
src/recurring.cpp

@ -4,8 +4,96 @@
#include "rpc.h"
#include "settings.h"
#include "ui_newrecurring.h"
#include "ui_recurringdialog.h"
void Recurring::showEditDialog(QWidget* parent, MainWindow* main, Tx tx) {
QString schedule_desc(Schedule s) {
switch (s) {
case Schedule::DAY: return "day";
case Schedule::WEEK: return "week";
case Schedule::MONTH: return "month";
case Schedule::YEAR: return "year";
default: return "none";
}
}
RecurringPaymentInfo RecurringPaymentInfo::fromJson(QJsonObject j) {
RecurringPaymentInfo r;
r.hashid = j["hash"].toString();
r.desc = j["desc"].toString();
r.fromAddr = j["from"].toString();
r.toAddr = j["to"].toString();
r.amt = j["amt"].toString().toDouble();
r.memo = j["memo"].toString();
r.currency = j["currency"].toString();
r.schedule = (Schedule)j["schedule"].toInt();
r.frequency = j["frequency"].toInt();
r.numPayments = j["numpayments"].toInt();
r.startDate = QDateTime::fromSecsSinceEpoch(j["startdate"].toString().toLongLong());
r.completedPayments = j["completed"].toInt();
r.history = QList<HistoryItem>();
for (auto h : j["history"].toArray()) {
HistoryItem item;
item.paymentNumber = h.toObject()["paymentnumber"].toInt();
item.date = QDateTime::fromSecsSinceEpoch(h.toObject()["date"].toString().toLongLong());
item.txid = h.toObject()["txid"].toString();
item.status = h.toObject()["status"].toString();
r.history.append(item);
}
return r;
}
void RecurringPaymentInfo::updateHash() {
auto val = getScheduleDescription() + fromAddr + toAddr;
hashid = QString(QCryptographicHash::hash(val.toUtf8(), QCryptographicHash::Sha256).toHex());
}
QJsonObject RecurringPaymentInfo::toJson() {
QJsonArray historyJson;
for (auto h : history) {
historyJson.append(QJsonObject{
{"paymentnumber", h.paymentNumber},
{"date", QString::number(h.date.toSecsSinceEpoch())},
{"txid", h.txid},
{"status", h.status}
});
}
auto j = QJsonObject{
{"hash", hashid},
{"desc", desc},
{"from", fromAddr},
{"to", toAddr},
{"amt", Settings::getDecimalString(amt)},
{"memo", memo},
{"currency", currency},
{"schedule", (int)schedule},
{"frequency", frequency},
{"numpayments", numPayments},
{"startdate", QString::number(startDate.toSecsSinceEpoch())},
{"completed", completedPayments},
{"history", historyJson}
};
return j;
}
QString RecurringPaymentInfo::getAmountPretty() {
return currency == "USD" ? Settings::getUSDFormat(amt) : Settings::getZECDisplayFormat(amt);
}
QString RecurringPaymentInfo::getScheduleDescription() {
return "Pay " % getAmountPretty()
% " every " % schedule_desc(schedule) % ", starting " % startDate.toString("yyyy-MMM-dd")
% ", for " % QString::number(numPayments) % " payments";
}
// Returns a new Recurring payment info, created from the Tx.
// The caller needs to take ownership of the returned object.
RecurringPaymentInfo* Recurring::getNewRecurringFromTx(QWidget* parent, MainWindow* main, Tx tx, RecurringPaymentInfo* rpi) {
Ui_newRecurringDialog ui;
QDialog d(parent);
ui.setupUi(&d);
@ -21,28 +109,228 @@ void Recurring::showEditDialog(QWidget* parent, MainWindow* main, Tx tx) {
ui.cmbFromAddress->setCurrentText(tx.fromAddr);
ui.cmbFromAddress->setEnabled(false);
}
ui.cmbCurrency->addItem(Settings::getTokenName());
ui.cmbCurrency->addItem("USD");
ui.cmbCurrency->addItem(Settings::getTokenName());
if (tx.toAddrs.length() > 0) {
ui.txtToAddr->setText(tx.toAddrs[0].addr);
ui.txtToAddr->setEnabled(false);
ui.txtAmt->setText(Settings::getDecimalString(tx.toAddrs[0].amount));
// Default is USD
ui.txtAmt->setText(Settings::getUSDFromZecAmount(tx.toAddrs[0].amount));
ui.txtAmt->setEnabled(false);
ui.txtMemo->setPlainText(tx.toAddrs[0].txtMemo);
ui.txtMemo->setEnabled(false);
}
ui.cmbSchedule->addItem("Every Day", QVariant(Schedule::DAY));
ui.cmbSchedule->addItem("Every Week", QVariant(Schedule::WEEK));
ui.cmbSchedule->addItem("Every Month", QVariant(Schedule::MONTH));
ui.cmbSchedule->addItem("Every Year", QVariant(Schedule::YEAR));
// Wire up ZEC/USD toggle
QObject::connect(ui.cmbCurrency, QOverload<const QString&>::of(&QComboBox::currentIndexChanged), [&](QString c) {
if (tx.toAddrs.length() < 1)
return;
if (c == "USD") {
ui.txtAmt->setText(Settings::getUSDFromZecAmount(tx.toAddrs[0].amount));
}
else {
ui.txtAmt->setText(Settings::getDecimalString(tx.toAddrs[0].amount));
}
});
for (int i = Schedule::DAY; i <= Schedule::YEAR; i++) {
ui.cmbSchedule->addItem("Every " + schedule_desc((Schedule)i), QVariant(i));
}
QObject::connect(ui.cmbSchedule, QOverload<int>::of(&QComboBox::currentIndexChanged), [&](int) {
ui.lblNextPayment->setText(getNextPaymentDate((Schedule)ui.cmbSchedule->currentData().toInt()).toString("yyyy-MMM-dd"));
});
ui.lblNextPayment->setText(getNextPaymentDate((Schedule)ui.cmbSchedule->currentData().toInt()).toString("yyyy-MMM-dd"));
ui.txtNumPayments->setText("10");
// If an existing RecurringPaymentInfo was passed in, set the UI values appropriately
if (rpi != nullptr) {
ui.txtDesc->setText(rpi->desc);
ui.txtToAddr->setText(rpi->toAddr);
ui.txtMemo->setPlainText(rpi->memo);
ui.cmbCurrency->setCurrentText(rpi->currency);
ui.txtAmt->setText(rpi->getAmountPretty());
ui.cmbFromAddress->setCurrentText(rpi->fromAddr);
ui.txtNumPayments->setText(QString::number(rpi->numPayments));
ui.cmbSchedule->setCurrentIndex(rpi->schedule);
}
ui.txtDesc->setFocus();
if (d.exec() == QDialog::Accepted) {
// Construct a new Object and return it
auto r = new RecurringPaymentInfo();
r->desc = ui.txtDesc->text();
r->currency = ui.cmbCurrency->currentText();
r->numPayments = ui.txtNumPayments->text().toInt();
r->schedule = (Schedule)ui.cmbSchedule->currentData().toInt();
r->startDate = QDateTime::currentDateTime();
updateInfoWithTx(r, tx);
return r;
}
else {
return nullptr;
}
}
void Recurring::updateInfoWithTx(RecurringPaymentInfo* r, Tx tx) {
r->toAddr = tx.toAddrs[0].addr;
r->memo = tx.toAddrs[0].txtMemo;
r->fromAddr = tx.fromAddr;
if (r->currency.isEmpty() || r->currency == "USD") {
r->currency = "USD";
r->amt = tx.toAddrs[0].amount * Settings::getInstance()->getZECPrice();
}
else {
r->currency = Settings::getTokenName();
r->amt = tx.toAddrs[0].amount;
}
r->updateHash();
}
QDateTime Recurring::getNextPaymentDate(Schedule s) {
auto nextDate = QDateTime::currentDateTime();
switch (s) {
case Schedule::DAY: nextDate = nextDate.addDays(1); break;
case Schedule::WEEK: nextDate = nextDate.addDays(7); break;
case Schedule::MONTH: nextDate = nextDate.addMonths(1); break;
case Schedule::YEAR: nextDate = nextDate.addYears(1); break;
}
return nextDate;
}
QString Recurring::writeableFile() {
auto filename = QStringLiteral("recurringpayments.json");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
if (!dir.exists())
QDir().mkpath(dir.absolutePath());
if (Settings::getInstance()->isTestnet()) {
return dir.filePath("testnet-" % filename);
}
else {
return dir.filePath(filename);
}
}
void Recurring::addRecurringInfo(const RecurringPaymentInfo& rpi) {
if (payments.contains(rpi.hashid)) {
payments.remove(rpi.hashid);
}
payments.insert(rpi.hashid, rpi);
writeToStorage();
}
void Recurring::readFromFile() {
QFile file(writeableFile());
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
auto jsondoc = QJsonDocument::fromJson(in.readAll().toUtf8());
for (auto k : jsondoc.array()) {
auto p = RecurringPaymentInfo::fromJson(k.toObject());
p.updateHash();
payments.insert(p.hashid, p);
}
}
void Recurring::writeToStorage() {
QFile file(writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QJsonArray arr;
for (auto k : payments.keys()) {
arr.append(payments[k].toJson());
}
QTextStream out(&file);
out << QJsonDocument(arr).toJson();
file.close();
}
Recurring* Recurring::getInstance() {
if (!instance) {
instance = new Recurring();
instance->readFromFile();
}
return instance;
}
// Singleton
Recurring* Recurring::instance = nullptr;
void Recurring::showRecurringDialog() {
Ui_RecurringDialog rd;
QDialog d;
rd.setupUi(&d);
Settings::saveRestore(&d);
auto model = new RecurringListViewModel(rd.tableView);
rd.tableView->setModel(model);
d.exec();
delete model;
}
RecurringListViewModel::RecurringListViewModel(QTableView* parent) {
this->parent = parent;
headers << tr("Amount") << tr("Schedule") << tr("Payments Left") << tr("To");
}
int RecurringListViewModel::rowCount(const QModelIndex &parent) const {
return Recurring::getInstance()->getAsList().size();
}
int RecurringListViewModel::columnCount(const QModelIndex &parent) const {
return headers.size();
}
QVariant RecurringListViewModel::data(const QModelIndex &index, int role) const {
auto rpi = Recurring::getInstance()->getAsList().at(index.row());
if (role == Qt::DisplayRole) {
switch (index.column()) {
case 0: return rpi.getAmountPretty();
case 1: return tr("Every ") + schedule_desc(rpi.schedule);
case 2: return rpi.numPayments - rpi.completedPayments;
case 3: return rpi.toAddr;
//case 4: return Recurring::getNextPaymentDate(rpi.)
}
}
return QVariant();
}
QVariant RecurringListViewModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (role == Qt::FontRole) {
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
return headers.at(section);
}
return QVariant();
}

86
src/recurring.h

@ -2,8 +2,10 @@
#define RECURRING_H
#include "precompiled.h"
#include "settings.h"
#include "mainwindow.h"
class MainWindow;
struct Tx;
enum Schedule {
DAY = 1,
@ -12,25 +14,83 @@ enum Schedule {
YEAR
};
QString schedule_desc(Schedule s);
struct RecurringPaymentInfo {
QString desc;
QString fromAddr;
QString toAddr;
double amt;
QString currency;
Schedule schedule;
int numPayments;
long startBlock;
int completedPayments;
QString hashid;
QString desc;
QString fromAddr;
QString toAddr;
double amt;
QString memo;
QString currency;
Schedule schedule;
int frequency;
int numPayments;
QDateTime startDate;
int completedPayments;
struct HistoryItem {
int paymentNumber;
QDateTime date;
QString txid;
QString status;
};
QList<HistoryItem> history;
void updateHash();
QString getScheduleDescription();
QJsonObject toJson();
QString getAmountPretty();
static RecurringPaymentInfo fromJson(QJsonObject j);
};
class Recurring
{
public:
Recurring();
static Recurring* getInstance();
RecurringPaymentInfo* getNewRecurringFromTx(QWidget* parent, MainWindow* main, Tx tx, RecurringPaymentInfo* rpi);
void updateInfoWithTx(RecurringPaymentInfo* r, Tx tx);
QString writeableFile();
void readFromFile();
static void showRecurringDialog();
static QDateTime getNextPaymentDate(Schedule s);
void addRecurringInfo(const RecurringPaymentInfo& rpi);
void writeToStorage();
QList<RecurringPaymentInfo> getAsList() { return payments.values(); }
private:
Recurring() = default;
QMap<QString, RecurringPaymentInfo> payments;
static Recurring* instance;
};
class RecurringListViewModel : public QAbstractTableModel {
public:
RecurringListViewModel(QTableView* parent);
~RecurringListViewModel() = default;
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;
static void showEditDialog(QWidget* parent, MainWindow* main, Tx tx);
private:
QTableView* parent;
QStringList headers;
};
#endif // RECURRING_H

6
src/recurringdialog.ui

@ -15,7 +15,11 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableView" name="tableView"/>
<widget class="QTableView" name="tableView">
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">

3
src/rpc.cpp

@ -632,7 +632,7 @@ void RPC::getInfoThenRefresh(bool force) {
")";
main->statusLabel->setText(statusText);
auto zecPrice = Settings::getUSDFormat(1);
auto zecPrice = Settings::getUSDFromZecAmount(1);
QString tooltip;
if (connections > 0) {
tooltip = QObject::tr("Connected to zcashd");
@ -748,6 +748,7 @@ void RPC::refreshBalances() {
ui->balTransparent->setText(Settings::getZECDisplayFormat(balT));
ui->balTotal ->setText(Settings::getZECDisplayFormat(balTotal));
ui->balSheilded ->setToolTip(Settings::getUSDFormat(balZ));
ui->balTransparent->setToolTip(Settings::getUSDFormat(balT));
ui->balTotal ->setToolTip(Settings::getUSDFormat(balTotal));

93
src/sendtab.cpp

@ -61,7 +61,7 @@ void MainWindow::setupSendTab() {
// Disable custom fees if settings say no
ui->minerFeeAmt->setReadOnly(!Settings::getInstance()->getAllowCustomFees());
QObject::connect(ui->minerFeeAmt, &QLineEdit::textChanged, [=](auto txt) {
ui->lblMinerFeeUSD->setText(Settings::getUSDFormat(txt.toDouble()));
ui->lblMinerFeeUSD->setText(Settings::getUSDFromZecAmount(txt.toDouble()));
});
ui->minerFeeAmt->setText(Settings::getDecimalString(Settings::getMinerFee()));
@ -69,7 +69,7 @@ void MainWindow::setupSendTab() {
QObject::connect(ui->tabWidget, &QTabWidget::currentChanged, [=] (int pos) {
if (pos == 1) {
QString txt = ui->minerFeeAmt->text();
ui->lblMinerFeeUSD->setText(Settings::getUSDFormat(txt.toDouble()));
ui->lblMinerFeeUSD->setText(Settings::getUSDFromZecAmount(txt.toDouble()));
}
});
//Fees validator
@ -84,30 +84,42 @@ void MainWindow::setupSendTab() {
// Recurring button
QObject::connect(ui->chkRecurring, &QCheckBox::stateChanged, [=] (int checked) {
if (checked) {
ui->btnRecurSchedule->setEnabled(true);
ui->btnRecurSchedule->setEnabled(true);
// If this is the first time the button is checked, open the edit schedule dialog
if (sendTxRecurringInfo == nullptr) {
ui->btnRecurSchedule->click();
}
} else {
ui->btnRecurSchedule->setEnabled(false);
ui->lblRecurDesc->setText("");
}
});
// Recurring schedule button
QObject::connect(ui->btnRecurSchedule, &QPushButton::clicked, this, &MainWindow::editSchedule);
// Hide the recurring section for now
ui->chkRecurring->setVisible(false);
ui->lblRecurDesc->setVisible(false);
ui->btnRecurSchedule->setVisible(false);
// Set the default state for the whole page
removeExtraAddresses();
clearSendForm();
}
void MainWindow::editSchedule() {
// Open the edit schedule dialog
Recurring::showEditDialog(this, this, createTxFromSendPage());
RecurringPaymentInfo* recurringInfo = Recurring::getInstance()->getNewRecurringFromTx(this, this,
createTxFromSendPage(), this->sendTxRecurringInfo);
if (recurringInfo == nullptr) {
// User pressed cancel.
// If there is no existing recurring info, uncheck the recurring box
if (sendTxRecurringInfo == nullptr) {
ui->chkRecurring->setCheckState(Qt::Unchecked);
}
}
else {
delete this->sendTxRecurringInfo;
this->sendTxRecurringInfo = recurringInfo;
ui->lblRecurDesc->setText(recurringInfo->getScheduleDescription());
}
}
void MainWindow::updateLabelsAutoComplete() {
@ -190,7 +202,7 @@ void MainWindow::inputComboTextChanged(int index) {
auto balFmt = Settings::getZECDisplayFormat(bal);
ui->sendAddressBalance->setText(balFmt);
ui->sendAddressBalanceUSD->setText(Settings::getUSDFormat(bal));
ui->sendAddressBalanceUSD->setText(Settings::getUSDFromZecAmount(bal));
}
@ -295,7 +307,13 @@ void MainWindow::addressChanged(int itemNumber, const QString& text) {
void MainWindow::amountChanged(int item, const QString& text) {
auto usd = ui->sendToWidgets->findChild<QLabel*>(QString("AmtUSD") % QString::number(item));
usd->setText(Settings::getUSDFormat(text.toDouble()));
usd->setText(Settings::getUSDFromZecAmount(text.toDouble()));
// If there is a recurring payment, update the info there as well
if (sendTxRecurringInfo != nullptr) {
Recurring::getInstance()->updateInfoWithTx(sendTxRecurringInfo, createTxFromSendPage());
ui->lblRecurDesc->setText(sendTxRecurringInfo->getScheduleDescription());
}
}
void MainWindow::setMemoEnabled(int number, bool enabled) {
@ -380,7 +398,7 @@ void MainWindow::memoButtonClicked(int number, bool includeReplyTo) {
}
}
void MainWindow::removeExtraAddresses() {
void MainWindow::clearSendForm() {
// The last one is a spacer, so ignore that
int totalItems = ui->sendToWidgets->children().size() - 2;
@ -413,6 +431,8 @@ void MainWindow::removeExtraAddresses() {
ui->chkRecurring->setCheckState(Qt::Unchecked);
ui->btnRecurSchedule->setEnabled(false);
ui->lblRecurDesc->setText("");
delete sendTxRecurringInfo;
sendTxRecurringInfo = nullptr;
}
void MainWindow::maxAmountChecked(int checked) {
@ -513,7 +533,7 @@ Tx MainWindow::createTxFromSendPage() {
return tx;
}
bool MainWindow::confirmTx(Tx tx) {
bool MainWindow::confirmTx(Tx tx, RecurringPaymentInfo* rpi) {
auto fnSplitAddressForWrap = [=] (const QString& a) -> QString {
if (!a.startsWith("z")) return a;
@ -522,6 +542,11 @@ bool MainWindow::confirmTx(Tx tx) {
return splitted;
};
// Update the recurring info with the latest Tx
if (rpi != nullptr) {
Recurring::getInstance()->updateInfoWithTx(rpi, tx);
rpi->updateHash();
}
// Show a confirmation dialog
QDialog d(this);
@ -576,7 +601,7 @@ bool MainWindow::confirmTx(Tx tx) {
// Amount (USD)
auto AmtUSD = new QLabel(confirm.sendToAddrs);
AmtUSD->setObjectName(QString("AmtUSD") % QString::number(i + 1));
AmtUSD->setText(Settings::getUSDFormat(toAddr.amount));
AmtUSD->setText(Settings::getUSDFromZecAmount(toAddr.amount));
AmtUSD->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
confirm.gridLayout->addWidget(AmtUSD, row, 2, 1, 1);
@ -627,7 +652,7 @@ bool MainWindow::confirmTx(Tx tx) {
minerFeeUSD->setObjectName(QStringLiteral("minerFeeUSD"));
minerFeeUSD->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
confirm.gridLayout->addWidget(minerFeeUSD, row, 2, 1, 1);
minerFeeUSD->setText(Settings::getUSDFormat(tx.fee));
minerFeeUSD->setText(Settings::getUSDFromZecAmount(tx.fee));
if (Settings::getInstance()->getAllowCustomFees() && tx.fee != Settings::getMinerFee()) {
confirm.warningLabel->setVisible(true);
@ -637,6 +662,15 @@ bool MainWindow::confirmTx(Tx tx) {
}
}
// Recurring payment info
if (rpi == nullptr) {
confirm.grpRecurring->setVisible(false);
}
else {
confirm.grpRecurring->setVisible(true);
confirm.lblRecurringDesc->setText(rpi->getScheduleDescription());
}
// Syncing warning
confirm.syncingWarning->setVisible(Settings::getInstance()->isSyncing());
@ -652,13 +686,7 @@ bool MainWindow::confirmTx(Tx tx) {
confirm.sendFrom->setToolTip(tooltip);
// Show the dialog and submit it if the user confirms
if (d.exec() == QDialog::Accepted) {
// Then delete the additional fields from the sendTo tab
removeExtraAddresses();
return true;
} else {
return false;
}
return d.exec() == QDialog::Accepted;
}
// Send button clicked
@ -676,17 +704,26 @@ void MainWindow::sendButton() {
// abort the Tx
return;
}
// Show a dialog to confirm the Tx
if (confirmTx(tx)) {
if (confirmTx(tx, sendTxRecurringInfo)) {
// Add it to the list
Recurring::getInstance()->addRecurringInfo(*sendTxRecurringInfo);
// Then delete the additional fields from the sendTo tab
clearSendForm();
// And send the Tx
rpc->executeTransaction(tx,
// Submitted
[=] (QString opid) {
ui->statusBar->showMessage(tr("Computing Tx: ") % opid);
},
[=] (QString, QString txid) {
// Accepted
[=] (QString opid, QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
},
// Errored out
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
@ -720,6 +757,6 @@ QString MainWindow::doSendTxValidations(Tx tx) {
}
void MainWindow::cancelButton() {
removeExtraAddresses();
clearSendForm();
}

16
src/settings.cpp

@ -152,11 +152,13 @@ void Settings::saveRestore(QDialog* d) {
});
}
QString Settings::getUSDFormat(double bal) {
if (!Settings::getInstance()->isTestnet() && Settings::getInstance()->getZECPrice() > 0)
return "$" + QLocale(QLocale::English).toString(bal * Settings::getInstance()->getZECPrice(), 'f', 2);
else
return QString();
QString Settings::getUSDFormat(double usdAmt) {
return "$" + QLocale(QLocale::English).toString(usdAmt, 'f', 2);
}
QString Settings::getUSDFromZecAmount(double bal) {
return getUSDFormat(bal * Settings::getInstance()->getZECPrice());
}
QString Settings::getDecimalString(double amt) {
@ -177,9 +179,9 @@ QString Settings::getZECDisplayFormat(double bal) {
}
QString Settings::getZECUSDDisplayFormat(double bal) {
auto usdFormat = getUSDFormat(bal);
auto usdFormat = getUSDFromZecAmount(bal);
if (!usdFormat.isEmpty())
return getZECDisplayFormat(bal) % " (" % getUSDFormat(bal) % ")";
return getZECDisplayFormat(bal) % " (" % usdFormat % ")";
else
return getZECDisplayFormat(bal);
}

4
src/settings.h

@ -69,7 +69,9 @@ public:
static bool isTAddress(QString addr);
static QString getDecimalString(double amt);
static QString getUSDFormat(double bal);
static QString getUSDFormat(double usdAmt);
static QString getUSDFromZecAmount(double bal);
static QString getZECDisplayFormat(double bal);
static QString getZECUSDDisplayFormat(double bal);

2
src/txtablemodel.cpp

@ -148,7 +148,7 @@ void TxTableModel::updateAllData() {
return addr;
}
case 2: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * (qint64)1000).toLocalTime().toString();
case 3: return Settings::getInstance()->getUSDFormat(modeldata->at(index.row()).amount);
case 3: return Settings::getInstance()->getUSDFromZecAmount(modeldata->at(index.row()).amount);
}
}

Loading…
Cancel
Save