Merge branch 'master' into websockets
This commit is contained in:
commit
7c71457cc1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -254,9 +254,6 @@ void AddressBook::readFromStorage() {
|
|||
}
|
||||
|
||||
void AddressBook::writeToStorage() {
|
||||
if (allLabels.isEmpty())
|
||||
return;
|
||||
|
||||
QFile file(AddressBook::writeableFile());
|
||||
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
|
||||
QDataStream out(&file); // we will serialize the data into the file
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "mainwindow.h"
|
||||
#include "settings.h"
|
||||
#include "ui_connection.h"
|
||||
#include "ui_createzcashconfdialog.h"
|
||||
#include "rpc.h"
|
||||
|
||||
#include "precompiled.h"
|
||||
|
@ -128,9 +129,47 @@ void ConnectionLoader::createZcashConf() {
|
|||
main->logger->write("createZcashConf");
|
||||
|
||||
auto confLocation = zcashConfWritableLocation();
|
||||
main->logger->write("Creating file " + confLocation);
|
||||
|
||||
QFileInfo fi(confLocation);
|
||||
|
||||
QDialog d(main);
|
||||
Ui_createZcashConf ui;
|
||||
ui.setupUi(&d);
|
||||
|
||||
QPixmap logo(":/img/res/zcashdlogo.gif");
|
||||
ui.lblTopIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
ui.btnPickDir->setEnabled(false);
|
||||
|
||||
ui.grpAdvanced->setVisible(false);
|
||||
QObject::connect(ui.btnAdvancedConfig, &QPushButton::toggled, [=](bool isVisible) {
|
||||
ui.grpAdvanced->setVisible(isVisible);
|
||||
ui.btnAdvancedConfig->setText(isVisible ? QObject::tr("Hide Advanced Config") : QObject::tr("Show Advanced Config"));
|
||||
});
|
||||
|
||||
QObject::connect(ui.chkCustomDatadir, &QCheckBox::stateChanged, [=](int chked) {
|
||||
if (chked == Qt::Checked) {
|
||||
ui.btnPickDir->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui.btnPickDir->setEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(ui.btnPickDir, &QPushButton::clicked, [=]() {
|
||||
auto datadir = QFileDialog::getExistingDirectory(main, QObject::tr("Choose data directory"), ui.lblDirName->text(), QFileDialog::ShowDirsOnly);
|
||||
if (!datadir.isEmpty()) {
|
||||
ui.lblDirName->setText(QDir::toNativeSeparators(datadir));
|
||||
}
|
||||
});
|
||||
|
||||
// Show the dialog
|
||||
QString datadir = "";
|
||||
bool useTor = false;
|
||||
if (d.exec() == QDialog::Accepted) {
|
||||
datadir = ui.lblDirName->text();
|
||||
useTor = ui.chkUseTor->isChecked();
|
||||
}
|
||||
|
||||
main->logger->write("Creating file " + confLocation);
|
||||
QDir().mkdir(fi.dir().absolutePath());
|
||||
|
||||
QFile file(confLocation);
|
||||
|
@ -145,6 +184,13 @@ void ConnectionLoader::createZcashConf() {
|
|||
out << "addnode=mainnet.z.cash\n";
|
||||
out << "rpcuser=zec-qt-wallet\n";
|
||||
out << "rpcpassword=" % randomPassword() << "\n";
|
||||
if (!datadir.isEmpty()) {
|
||||
out << "datadir=" % datadir % "\n";
|
||||
}
|
||||
if (useTor) {
|
||||
out << "proxy=127.0.0.1:9050\n";
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
// Now that zcash.conf exists, try to autoconnect again
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>createZcashConf</class>
|
||||
<widget class="QDialog" name="createZcashConf">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>508</width>
|
||||
<height>352</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Configure zcash.conf</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="FilledIconLabel" name="lblTopIcon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: #fff;</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAdvancedConfig">
|
||||
<property name="text">
|
||||
<string>Show Advanced Configuration</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Your zcash node will be configured for you automatically</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QGroupBox" name="grpAdvanced">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="chkCustomDatadir">
|
||||
<property name="text">
|
||||
<string>Use custom datadir</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Please chose a directory to store your wallet.dat and blockchain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPickDir">
|
||||
<property name="text">
|
||||
<string>Choose directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDirName">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="chkUseTor">
|
||||
<property name="text">
|
||||
<string>Connect over Tor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Please note that you'll need to already have a Tor service configured on port 9050</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FilledIconLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>fillediconlabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>createZcashConf</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>createZcashConf</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -256,12 +256,18 @@ void MainWindow::turnstileDoMigration(QString fromAddr) {
|
|||
|
||||
auto fnUpdateSproutBalance = [=] (QString addr) {
|
||||
double bal = 0;
|
||||
|
||||
// The currentText contains the balance as well, so strip that.
|
||||
if (addr.contains("(")) {
|
||||
addr = addr.left(addr.indexOf("("));
|
||||
}
|
||||
|
||||
if (addr.startsWith("All")) {
|
||||
bal = fnGetAllSproutBalance();
|
||||
} else {
|
||||
bal = rpc->getAllBalances()->value(addr);
|
||||
}
|
||||
|
||||
|
||||
auto balTxt = Settings::getZECUSDDisplayFormat(bal);
|
||||
|
||||
if (bal < Turnstile::minMigrationAmount) {
|
||||
|
@ -634,17 +640,20 @@ void MainWindow::postToZBoard() {
|
|||
tx.toAddrs.push_back(ToFields{ toAddr, Settings::getZboardAmount(), memo, memo.toUtf8().toHex() });
|
||||
tx.fee = Settings::getMinerFee();
|
||||
|
||||
json params = json::array();
|
||||
rpc->fillTxJsonParams(params, tx);
|
||||
std::cout << std::setw(2) << params << std::endl;
|
||||
|
||||
// And send the Tx
|
||||
rpc->sendZTransaction(params, [=](const json& reply) {
|
||||
QString opid = QString::fromStdString(reply.get<json::string_t>());
|
||||
rpc->executeTransaction(tx, [=] (QString opid) {
|
||||
ui->statusBar->showMessage(tr("Computing Tx: ") % opid);
|
||||
},
|
||||
[=] (QString /*opid*/, QString txid) {
|
||||
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
|
||||
},
|
||||
[=] (QString opid, QString errStr) {
|
||||
ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
|
||||
|
||||
// And then start monitoring the transaction
|
||||
rpc->addNewTxToWatch(tx, opid);
|
||||
if (!opid.isEmpty())
|
||||
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
|
||||
|
||||
QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -731,7 +740,7 @@ void MainWindow::payZcashURI() {
|
|||
|
||||
if (kv[0].toLower() == "amt" || kv[0].toLower() == "amount") {
|
||||
amount = kv[1].toDouble();
|
||||
} else if (kv[0].toLower() == "memo") {
|
||||
} else if (kv[0].toLower() == "memo" || kv[0].toLower() == "message" || kv[0].toLower() == "msg") {
|
||||
memo = kv[1];
|
||||
// Test if this is hex
|
||||
|
||||
|
@ -1200,7 +1209,16 @@ void MainWindow::setupRecieveTab() {
|
|||
});
|
||||
|
||||
// zAddr toggle button, one for sprout and one for sapling
|
||||
QObject::connect(ui->rdioZAddr, &QRadioButton::toggled, addZAddrsToComboList(false));
|
||||
QObject::connect(ui->rdioZAddr, &QRadioButton::toggled, [=](bool checked) {
|
||||
ui->btnRecieveNewAddr->setEnabled(!checked);
|
||||
if (checked) {
|
||||
ui->btnRecieveNewAddr->setToolTip(tr("Creation of new Sprout addresses is deprecated"));
|
||||
}
|
||||
else {
|
||||
ui->btnRecieveNewAddr->setToolTip("");
|
||||
}
|
||||
addZAddrsToComboList(false)(checked);
|
||||
});
|
||||
QObject::connect(ui->rdioZSAddr, &QRadioButton::toggled, addZAddrsToComboList(true));
|
||||
|
||||
// Explicitly get new address button.
|
||||
|
@ -1233,7 +1251,7 @@ void MainWindow::setupRecieveTab() {
|
|||
if (Settings::getInstance()->isSaplingActive()) {
|
||||
ui->rdioZSAddr->setVisible(true);
|
||||
ui->rdioZSAddr->setChecked(true);
|
||||
ui->rdioZAddr->setText("z-Addr(Sprout)");
|
||||
ui->rdioZAddr->setText("z-Addr(Legacy Sprout)");
|
||||
} else {
|
||||
ui->rdioZSAddr->setVisible(false);
|
||||
ui->rdioZAddr->setChecked(true);
|
||||
|
@ -1260,7 +1278,6 @@ void MainWindow::setupRecieveTab() {
|
|||
ui->rcvBal->clear();
|
||||
ui->txtRecieve->clear();
|
||||
ui->qrcodeDisplay->clear();
|
||||
ui->lblUsed->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1277,9 +1294,9 @@ void MainWindow::setupRecieveTab() {
|
|||
ui->txtRecieve->setPlainText(addr);
|
||||
ui->qrcodeDisplay->setQrcodeString(addr);
|
||||
if (rpc->getUsedAddresses()->value(addr, false)) {
|
||||
ui->lblUsed->setText(tr("Address has been previously used"));
|
||||
ui->rcvBal->setToolTip(tr("Address has been previously used"));
|
||||
} else {
|
||||
ui->lblUsed->setText(tr("Address is unused"));
|
||||
ui->rcvBal->setToolTip(tr("Address is unused"));
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
void updateLabelsAutoComplete();
|
||||
RPC* getRPC() { return rpc; }
|
||||
|
||||
QString doSendTxValidations(Tx tx);
|
||||
void setDefaultPayFrom();
|
||||
|
@ -78,6 +79,8 @@ private:
|
|||
void addAddressSection();
|
||||
void maxAmountChecked(int checked);
|
||||
|
||||
void editSchedule();
|
||||
|
||||
void addressChanged(int number, const QString& text);
|
||||
void amountChanged (int number, const QString& text);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
|
@ -346,8 +346,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>928</width>
|
||||
<height>380</height>
|
||||
<width>920</width>
|
||||
<height>301</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="sendToLayout">
|
||||
|
@ -530,6 +530,50 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layoutSendRecurring">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chkRecurring">
|
||||
<property name="text">
|
||||
<string>Recurring payment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblRecurDesc">
|
||||
<property name="text">
|
||||
<string>Every month, starting 12-May-2012, for 6 payments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnRecurSchedule">
|
||||
<property name="text">
|
||||
<string>Edit Schedule</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
|
@ -559,6 +603,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
@ -629,7 +680,7 @@
|
|||
<item>
|
||||
<widget class="QRadioButton" name="rdioZSAddr">
|
||||
<property name="text">
|
||||
<string>z-Addr(Sapling)</string>
|
||||
<string>z-Addr</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -649,7 +700,7 @@
|
|||
<item>
|
||||
<widget class="QRadioButton" name="rdioZAddr">
|
||||
<property name="text">
|
||||
<string>z-Addr(Sprout)</string>
|
||||
<string>z-Addr(Legacy Sprout)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -739,17 +790,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Address</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<item row="3" column="1" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_16">
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportKey">
|
||||
|
@ -773,17 +814,13 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Address used</string>
|
||||
<string>Address</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QLabel" name="lblUsed">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>newRecurringDialog</class>
|
||||
<widget class="QDialog" name="newRecurringDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>740</width>
|
||||
<height>403</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit Schedule</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="5" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbSchedule"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="10" column="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Schedule</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Payment Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="lblNextPayment">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtAmt">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cmbCurrency"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="txtDesc"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>From</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Number of payments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Amount</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="AddressCombo" name="cmbFromAddress"/>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtNumPayments"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Next Payment</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLineEdit" name="txtToAddr"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>To</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPlainTextEdit" name="txtMemo"/>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Memo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>AddressCombo</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>addresscombo.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>txtDesc</tabstop>
|
||||
<tabstop>cmbFromAddress</tabstop>
|
||||
<tabstop>txtToAddr</tabstop>
|
||||
<tabstop>txtAmt</tabstop>
|
||||
<tabstop>cmbCurrency</tabstop>
|
||||
<tabstop>cmbSchedule</tabstop>
|
||||
<tabstop>txtNumPayments</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>newRecurringDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>newRecurringDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -0,0 +1,48 @@
|
|||
#include "recurring.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "rpc.h"
|
||||
#include "settings.h"
|
||||
#include "ui_newrecurring.h"
|
||||
|
||||
void Recurring::showEditDialog(QWidget* parent, MainWindow* main, Tx tx) {
|
||||
Ui_newRecurringDialog ui;
|
||||
QDialog d(parent);
|
||||
ui.setupUi(&d);
|
||||
Settings::saveRestore(&d);
|
||||
|
||||
// Add all the from addresses
|
||||
auto allBalances = main->getRPC()->getAllBalances();
|
||||
for (QString addr : allBalances->keys()) {
|
||||
ui.cmbFromAddress->addItem(addr, allBalances->value(addr));
|
||||
}
|
||||
|
||||
if (!tx.fromAddr.isEmpty()) {
|
||||
ui.cmbFromAddress->setCurrentText(tx.fromAddr);
|
||||
ui.cmbFromAddress->setEnabled(false);
|
||||
}
|
||||
|
||||
ui.cmbCurrency->addItem(Settings::getTokenName());
|
||||
ui.cmbCurrency->addItem("USD");
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
ui.txtNumPayments->setText("10");
|
||||
|
||||
ui.txtDesc->setFocus();
|
||||
d.exec();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef RECURRING_H
|
||||
#define RECURRING_H
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
enum Schedule {
|
||||
DAY = 1,
|
||||
WEEK,
|
||||
MONTH,
|
||||
YEAR
|
||||
};
|
||||
|
||||
struct RecurringPaymentInfo {
|
||||
QString desc;
|
||||
QString fromAddr;
|
||||
QString toAddr;
|
||||
double amt;
|
||||
QString currency;
|
||||
Schedule schedule;
|
||||
int numPayments;
|
||||
|
||||
long startBlock;
|
||||
int completedPayments;
|
||||
};
|
||||
|
||||
class Recurring
|
||||
{
|
||||
public:
|
||||
Recurring();
|
||||
|
||||
static void showEditDialog(QWidget* parent, MainWindow* main, Tx tx);
|
||||
};
|
||||
|
||||
#endif // RECURRING_H
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>RecurringDialog</class>
|
||||
<widget class="QDialog" name="RecurringDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>601</width>
|
||||
<height>438</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTableView" name="tableView"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_3">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>RecurringDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>RecurringDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
97
src/rpc.cpp
97
src/rpc.cpp
|
@ -227,7 +227,8 @@ void RPC::getTransactions(const std::function<void(json)>& cb) {
|
|||
conn->doRPCWithDefaultErrorHandling(payload, cb);
|
||||
}
|
||||
|
||||
void RPC::sendZTransaction(json params, const std::function<void(json)>& cb) {
|
||||
void RPC::sendZTransaction(json params, const std::function<void(json)>& cb,
|
||||
const std::function<void(QString)>& err) {
|
||||
json payload = {
|
||||
{"jsonrpc", "1.0"},
|
||||
{"id", "someid"},
|
||||
|
@ -235,7 +236,13 @@ void RPC::sendZTransaction(json params, const std::function<void(json)>& cb) {
|
|||
{"params", params}
|
||||
};
|
||||
|
||||
conn->doRPCWithDefaultErrorHandling(payload, cb);
|
||||
conn->doRPC(payload, cb, [=] (auto reply, auto parsed) {
|
||||
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
|
||||
err(QString::fromStdString(parsed["error"]["message"]));
|
||||
} else {
|
||||
err(reply->errorString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -537,11 +544,15 @@ void RPC::getInfoThenRefresh(bool force) {
|
|||
|
||||
static int lastBlock = 0;
|
||||
int curBlock = reply["blocks"].get<json::number_integer_t>();
|
||||
int version = reply["version"].get<json::number_integer_t>();
|
||||
|
||||
if ( force || (curBlock != lastBlock) ) {
|
||||
// Something changed, so refresh everything.
|
||||
lastBlock = curBlock;
|
||||
|
||||
// See if the turnstile migration has any steps that need to be done.
|
||||
turnstile->executeMigrationStep();
|
||||
|
||||
refreshBalances();
|
||||
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
|
||||
refreshTransactions();
|
||||
|
@ -602,7 +613,7 @@ void RPC::getInfoThenRefresh(bool force) {
|
|||
// as the progress instead of verification progress.
|
||||
progress = (double)blockNumber / (double)estimatedheight;
|
||||
}
|
||||
txt = txt % " ( " % QString::number(progress * 100, 'f', 0) % "% )";
|
||||
txt = txt % " ( " % QString::number(progress * 100, 'f', 2) % "% )";
|
||||
ui->blockheight->setText(txt);
|
||||
ui->heightLabel->setText(QObject::tr("Downloading blocks"));
|
||||
} else {
|
||||
|
@ -617,7 +628,7 @@ void RPC::getInfoThenRefresh(bool force) {
|
|||
" (" %
|
||||
(Settings::getInstance()->isTestnet() ? QObject::tr("testnet:") : "") %
|
||||
QString::number(blockNumber) %
|
||||
(isSyncing ? ("/" % QString::number(progress*100, 'f', 0) % "%") : QString()) %
|
||||
(isSyncing ? ("/" % QString::number(progress*100, 'f', 2) % "%") : QString()) %
|
||||
")";
|
||||
main->statusLabel->setText(statusText);
|
||||
|
||||
|
@ -629,6 +640,7 @@ void RPC::getInfoThenRefresh(bool force) {
|
|||
else {
|
||||
tooltip = QObject::tr("zcashd has no peer connections");
|
||||
}
|
||||
tooltip = tooltip % "(v " % QString::number(version) % ")";
|
||||
|
||||
if (!zecPrice.isEmpty()) {
|
||||
tooltip = "1 ZEC = " % zecPrice % "\n" % tooltip;
|
||||
|
@ -690,10 +702,7 @@ void RPC::refreshAddresses() {
|
|||
}
|
||||
|
||||
// Function to create the data model and update the views, used below.
|
||||
void RPC::updateUI(bool anyUnconfirmed) {
|
||||
// See if the turnstile migration has any steps that need to be done.
|
||||
turnstile->executeMigrationStep();
|
||||
|
||||
void RPC::updateUI(bool anyUnconfirmed) {
|
||||
ui->unconfirmedWarning->setVisible(anyUnconfirmed);
|
||||
|
||||
// Update balances model data, which will update the table too
|
||||
|
@ -863,12 +872,36 @@ void RPC::refreshSentZTrans() {
|
|||
);
|
||||
}
|
||||
|
||||
void RPC::addNewTxToWatch(Tx tx, const QString& newOpid) {
|
||||
watchingOps.insert(newOpid, tx);
|
||||
void RPC::addNewTxToWatch(const QString& newOpid, WatchedTx wtx) {
|
||||
watchingOps.insert(newOpid, wtx);
|
||||
|
||||
watchTxStatus();
|
||||
}
|
||||
|
||||
|
||||
// Execute a transaction!
|
||||
void RPC::executeTransaction(Tx tx,
|
||||
const std::function<void(QString opid)> submitted,
|
||||
const std::function<void(QString opid, QString txid)> computed,
|
||||
const std::function<void(QString opid, QString errStr)> error) {
|
||||
// First, create the json params
|
||||
json params = json::array();
|
||||
fillTxJsonParams(params, tx);
|
||||
std::cout << std::setw(2) << params << std::endl;
|
||||
|
||||
sendZTransaction(params, [=](const json& reply) {
|
||||
QString opid = QString::fromStdString(reply.get<json::string_t>());
|
||||
|
||||
// And then start monitoring the transaction
|
||||
addNewTxToWatch( opid, WatchedTx { opid, tx, computed, error} );
|
||||
submitted(opid);
|
||||
},
|
||||
[=](QString errStr) {
|
||||
error("", errStr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void RPC::watchTxStatus() {
|
||||
if (conn == nullptr)
|
||||
return noConnection();
|
||||
|
@ -888,35 +921,26 @@ void RPC::watchTxStatus() {
|
|||
if (watchingOps.contains(id)) {
|
||||
// And if it ended up successful
|
||||
QString status = QString::fromStdString(it["status"]);
|
||||
main->loadingLabel->setVisible(false);
|
||||
|
||||
if (status == "success") {
|
||||
auto txid = QString::fromStdString(it["result"]["txid"]);
|
||||
|
||||
SentTxStore::addToSentTx(watchingOps.value(id), txid);
|
||||
|
||||
main->ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
|
||||
main->loadingLabel->setVisible(false);
|
||||
SentTxStore::addToSentTx(watchingOps[id].tx, txid);
|
||||
|
||||
auto wtx = watchingOps[id];
|
||||
watchingOps.remove(id);
|
||||
wtx.completed(id, txid);
|
||||
|
||||
// Refresh balances to show unconfirmed balances
|
||||
refresh(true);
|
||||
refresh(true);
|
||||
} else if (status == "failed") {
|
||||
// If it failed, then we'll actually show a warning.
|
||||
auto errorMsg = QString::fromStdString(it["error"]["message"]);
|
||||
QMessageBox msg(
|
||||
QMessageBox::Critical,
|
||||
QObject::tr("Transaction Error"),
|
||||
QObject::tr("The transaction with id ") % id % QObject::tr(" failed. The error was") + ":\n\n" + errorMsg,
|
||||
QMessageBox::Ok,
|
||||
main
|
||||
);
|
||||
|
||||
watchingOps.remove(id);
|
||||
|
||||
main->ui->statusBar->showMessage(QObject::tr(" Tx ") % id % QObject::tr(" failed"), 15 * 1000);
|
||||
main->loadingLabel->setVisible(false);
|
||||
|
||||
msg.exec();
|
||||
auto wtx = watchingOps[id];
|
||||
watchingOps.remove(id);
|
||||
wtx.error(id, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,8 +997,14 @@ void RPC::checkForUpdate(bool silent) {
|
|||
}
|
||||
|
||||
auto currentVersion = QVersionNumber::fromString(APP_VERSION);
|
||||
|
||||
// Get the max version that the user has hidden updates for
|
||||
QSettings s;
|
||||
auto maxHiddenVersion = QVersionNumber::fromString(s.value("update/lastversion", "0.0.0").toString());
|
||||
|
||||
qDebug() << "Version check: Current " << currentVersion << ", Available " << maxVersion;
|
||||
if (maxVersion > currentVersion) {
|
||||
|
||||
if (maxVersion > currentVersion && maxVersion > maxHiddenVersion) {
|
||||
auto ans = QMessageBox::information(main, QObject::tr("Update Available"),
|
||||
QObject::tr("A new release v%1 is available! You have v%2.\n\nWould you like to visit the releases page?")
|
||||
.arg(maxVersion.toString())
|
||||
|
@ -982,6 +1012,15 @@ void RPC::checkForUpdate(bool silent) {
|
|||
QMessageBox::Yes, QMessageBox::Cancel);
|
||||
if (ans == QMessageBox::Yes) {
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/ZcashFoundation/zec-qt-wallet/releases"));
|
||||
} else {
|
||||
// If the user selects cancel, don't bother them again for this version
|
||||
s.setValue("update/lastversion", maxVersion.toString());
|
||||
}
|
||||
} else {
|
||||
if (!silent) {
|
||||
QMessageBox::information(main, QObject::tr("No updates available"),
|
||||
QObject::tr("You already have the latest release v%1")
|
||||
.arg(currentVersion.toString()));
|
||||
}
|
||||
} else {
|
||||
if (!silent) {
|
||||
|
|
19
src/rpc.h
19
src/rpc.h
|
@ -24,6 +24,13 @@ struct TransactionItem {
|
|||
QString memo;
|
||||
};
|
||||
|
||||
struct WatchedTx {
|
||||
QString opid;
|
||||
Tx tx;
|
||||
std::function<void(QString, QString)> completed;
|
||||
std::function<void(QString, QString)> error;
|
||||
};
|
||||
|
||||
class RPC
|
||||
{
|
||||
public:
|
||||
|
@ -42,11 +49,17 @@ public:
|
|||
void refreshZECPrice();
|
||||
void getZboardTopics(std::function<void(QMap<QString, QString>)> cb);
|
||||
|
||||
void executeTransaction(Tx tx,
|
||||
const std::function<void(QString opid)> submitted,
|
||||
const std::function<void(QString opid, QString txid)> computed,
|
||||
const std::function<void(QString opid, QString errStr)> error);
|
||||
|
||||
void fillTxJsonParams(json& params, Tx tx);
|
||||
void sendZTransaction (json params, const std::function<void(json)>& cb);
|
||||
void sendZTransaction(json params, const std::function<void(json)>& cb, const std::function<void(QString)>& err);
|
||||
void watchTxStatus();
|
||||
void addNewTxToWatch(Tx tx, const QString& newOpid);
|
||||
|
||||
const QMap<QString, Tx> getWatchingTxns() { return watchingOps; }
|
||||
void addNewTxToWatch(const QString& newOpid, WatchedTx wtx);
|
||||
|
||||
const TxTableModel* getTransactionsModel() { return transactionsTableModel; }
|
||||
const QList<QString>* getAllZAddresses() { return zaddresses; }
|
||||
|
@ -103,7 +116,7 @@ private:
|
|||
QList<QString>* zaddresses = nullptr;
|
||||
QList<QString>* taddresses = nullptr;
|
||||
|
||||
QMap<QString, Tx> watchingOps;
|
||||
QMap<QString, WatchedTx> watchingOps;
|
||||
|
||||
TxTableModel* transactionsTableModel = nullptr;
|
||||
BalancesTableModel* balancesTableModel = nullptr;
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include "addressbook.h"
|
||||
#include "ui_confirm.h"
|
||||
#include "ui_memodialog.h"
|
||||
#include "ui_newrecurring.h"
|
||||
#include "settings.h"
|
||||
#include "rpc.h"
|
||||
#include "recurring.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
|
@ -80,6 +82,34 @@ void MainWindow::setupSendTab() {
|
|||
QFont f = ui->Address1->font();
|
||||
f.setPointSize(f.pointSize() - 1);
|
||||
ui->MemoTxt1->setFont(f);
|
||||
|
||||
// Recurring button
|
||||
QObject::connect(ui->chkRecurring, &QCheckBox::stateChanged, [=] (int checked) {
|
||||
if (checked) {
|
||||
ui->btnRecurSchedule->setEnabled(true);
|
||||
} 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();
|
||||
}
|
||||
|
||||
void MainWindow::editSchedule() {
|
||||
// Open the edit schedule dialog
|
||||
Recurring::showEditDialog(this, this, createTxFromSendPage());
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateLabelsAutoComplete() {
|
||||
|
@ -354,6 +384,11 @@ void MainWindow::removeExtraAddresses() {
|
|||
|
||||
delete addressGroupBox;
|
||||
}
|
||||
|
||||
// Reset the recurring button
|
||||
ui->chkRecurring->setCheckState(Qt::Unchecked);
|
||||
ui->btnRecurSchedule->setEnabled(false);
|
||||
ui->lblRecurDesc->setText("");
|
||||
}
|
||||
|
||||
void MainWindow::maxAmountChecked(int checked) {
|
||||
|
@ -620,18 +655,23 @@ void MainWindow::sendButton() {
|
|||
|
||||
// Show a dialog to confirm the Tx
|
||||
if (confirmTx(tx)) {
|
||||
json params = json::array();
|
||||
rpc->fillTxJsonParams(params, tx);
|
||||
std::cout << std::setw(2) << params << std::endl;
|
||||
|
||||
// And send the Tx
|
||||
rpc->sendZTransaction(params, [=](const json& reply) {
|
||||
QString opid = QString::fromStdString(reply.get<json::string_t>());
|
||||
ui->statusBar->showMessage(tr("Computing Tx: ") % opid);
|
||||
rpc->executeTransaction(tx,
|
||||
[=] (QString opid) {
|
||||
ui->statusBar->showMessage(tr("Computing Tx: ") % opid);
|
||||
},
|
||||
[=] (QString, QString txid) {
|
||||
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
|
||||
},
|
||||
[=] (QString opid, QString errStr) {
|
||||
ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
|
||||
|
||||
// And then start monitoring the transaction
|
||||
rpc->addNewTxToWatch(tx, opid);
|
||||
});
|
||||
if (!opid.isEmpty())
|
||||
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
|
||||
|
||||
QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -84,12 +84,22 @@ void SentTxStore::addToSentTx(Tx tx, QString txid) {
|
|||
totalAmount += i.amount;
|
||||
}
|
||||
|
||||
QString toAddresses;
|
||||
if (tx.toAddrs.length() == 1) {
|
||||
toAddresses = tx.toAddrs[0].addr;
|
||||
} else {
|
||||
// Concatenate all the toAddresses
|
||||
for (auto a : tx.toAddrs) {
|
||||
toAddresses += a.addr % "(" % Settings::getZECDisplayFormat(a.amount) % ") ";
|
||||
}
|
||||
}
|
||||
|
||||
auto list = jsonDoc.array();
|
||||
QJsonObject txItem;
|
||||
txItem["type"] = "sent";
|
||||
txItem["from"] = tx.fromAddr;
|
||||
txItem["datetime"] = QDateTime::currentMSecsSinceEpoch() / (qint64)1000;
|
||||
txItem["address"] = QString(); // The sent address is blank, to be consistent with t-Addr sent behaviour
|
||||
txItem["address"] = toAddresses;
|
||||
txItem["txid"] = txid;
|
||||
txItem["amount"] = -totalAmount;
|
||||
txItem["fee"] = -tx.fee;
|
||||
|
|
|
@ -320,8 +320,10 @@ void Turnstile::executeMigrationStep() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Sometimes, we check too quickly, and the unspent UTXO is not updated yet, so we'll
|
||||
// double check to see if there is enough balance.
|
||||
if (!rpc->getAllBalances()->keys().contains(nextStep->intTAddr)) {
|
||||
qDebug() << QString("The intermediate t-address doesn't have balance, even though it is confirmed");
|
||||
//qDebug() << QString("The intermediate t-address doesn't have balance, even though it seems to be confirmed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -351,17 +353,20 @@ void Turnstile::executeMigrationStep() {
|
|||
}
|
||||
|
||||
void Turnstile::doSendTx(Tx tx, std::function<void(void)> cb) {
|
||||
json params = json::array();
|
||||
rpc->fillTxJsonParams(params, tx);
|
||||
std::cout << std::setw(2) << params << std::endl;
|
||||
rpc->sendZTransaction(params, [=] (const json& reply) {
|
||||
QString opid = QString::fromStdString(reply.get<json::string_t>());
|
||||
//qDebug() << opid;
|
||||
mainwindow->ui->statusBar->showMessage(QObject::tr("Computing Tx: ") % opid);
|
||||
rpc->executeTransaction(tx, [=] (QString opid) {
|
||||
mainwindow->ui->statusBar->showMessage(QObject::tr("Computing Tx: ") % opid);
|
||||
},
|
||||
[=] (QString /*opid*/, QString txid) {
|
||||
mainwindow->ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
|
||||
cb();
|
||||
},
|
||||
[=] (QString opid, QString errStr) {
|
||||
mainwindow->ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000);
|
||||
|
||||
// And then start monitoring the transaction
|
||||
rpc->addNewTxToWatch(tx, opid);
|
||||
if (!opid.isEmpty())
|
||||
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
|
||||
|
||||
cb();
|
||||
});
|
||||
QMessageBox::critical(mainwindow, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ SOURCES += \
|
|||
src/logger.cpp \
|
||||
src/addresscombo.cpp \
|
||||
src/websockets.cpp \
|
||||
src/mobileappconnector.cpp
|
||||
src/mobileappconnector.cpp \
|
||||
src/recurring.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/mainwindow.h \
|
||||
|
@ -76,7 +77,8 @@ HEADERS += \
|
|||
src/logger.h \
|
||||
src/addresscombo.h \
|
||||
src/websockets.h \
|
||||
src/mobileappconnector.h
|
||||
src/mobileappconnector.h \
|
||||
src/recurring.h
|
||||
|
||||
FORMS += \
|
||||
src/mainwindow.ui \
|
||||
|
@ -90,7 +92,10 @@ FORMS += \
|
|||
src/connection.ui \
|
||||
src/zboard.ui \
|
||||
src/addressbook.ui \
|
||||
src/mobileappconnector.ui
|
||||
src/mobileappconnector.ui \
|
||||
src/createzcashconfdialog.ui \
|
||||
src/recurringdialog.ui \
|
||||
src/newrecurring.ui
|
||||
|
||||
|
||||
TRANSLATIONS = res/zec_qt_wallet_es.ts \
|
||||
|
|
Loading…
Reference in New Issue