Merge branch 'master' of github.com:zcashfoundation/zecwallet
This commit is contained in:
@@ -82,8 +82,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
// Export transactions
|
// Export transactions
|
||||||
QObject::connect(ui->actionExport_transactions, &QAction::triggered, this, &MainWindow::exportTransactions);
|
QObject::connect(ui->actionExport_transactions, &QAction::triggered, this, &MainWindow::exportTransactions);
|
||||||
|
|
||||||
|
// Z-board seems to have been abandoned
|
||||||
// z-Board.net
|
// z-Board.net
|
||||||
QObject::connect(ui->actionz_board_net, &QAction::triggered, this, &MainWindow::postToZBoard);
|
// QObject::connect(ui->actionz_board_net, &QAction::triggered, this, &MainWindow::postToZBoard);
|
||||||
|
|
||||||
// Validate Address
|
// Validate Address
|
||||||
QObject::connect(ui->actionValidate_Address, &QAction::triggered, this, &MainWindow::validateAddress);
|
QObject::connect(ui->actionValidate_Address, &QAction::triggered, this, &MainWindow::validateAddress);
|
||||||
@@ -177,6 +178,11 @@ void MainWindow::restoreSavedStates() {
|
|||||||
|
|
||||||
ui->balancesTable->horizontalHeader()->restoreState(s.value("baltablegeometry").toByteArray());
|
ui->balancesTable->horizontalHeader()->restoreState(s.value("baltablegeometry").toByteArray());
|
||||||
ui->transactionsTable->horizontalHeader()->restoreState(s.value("tratablegeometry").toByteArray());
|
ui->transactionsTable->horizontalHeader()->restoreState(s.value("tratablegeometry").toByteArray());
|
||||||
|
|
||||||
|
// Explicitly set the tx table resize headers, since some previous values may have made them
|
||||||
|
// non-expandable.
|
||||||
|
ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Interactive);
|
||||||
|
ui->transactionsTable->horizontalHeader()->setSectionResizeMode(4, QHeaderView::Interactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::doClose() {
|
void MainWindow::doClose() {
|
||||||
@@ -637,8 +643,7 @@ void MainWindow::donate() {
|
|||||||
// Set up a donation to me :)
|
// Set up a donation to me :)
|
||||||
clearSendForm();
|
clearSendForm();
|
||||||
|
|
||||||
ui->Address1->setText(Settings::getDonationAddr(
|
ui->Address1->setText(Settings::getDonationAddr());
|
||||||
Settings::getInstance()->isSaplingAddress(ui->inputsCombo->currentText())));
|
|
||||||
ui->Address1->setCursorPosition(0);
|
ui->Address1->setCursorPosition(0);
|
||||||
ui->Amount1->setText("0.01");
|
ui->Amount1->setText("0.01");
|
||||||
ui->MemoTxt1->setText(tr("Thanks for supporting ZecWallet!"));
|
ui->MemoTxt1->setText(tr("Thanks for supporting ZecWallet!"));
|
||||||
@@ -710,12 +715,12 @@ void MainWindow::postToZBoard() {
|
|||||||
|
|
||||||
QMap<QString, QString> topics;
|
QMap<QString, QString> topics;
|
||||||
// Insert the main topic automatically
|
// Insert the main topic automatically
|
||||||
topics.insert("#Main_Area", Settings::getInstance()->isTestnet() ? Settings::getDonationAddr(true) : Settings::getZboardAddr());
|
topics.insert("#Main_Area", Settings::getInstance()->isTestnet() ? Settings::getDonationAddr() : Settings::getZboardAddr());
|
||||||
zb.topicsList->addItem(topics.firstKey());
|
zb.topicsList->addItem(topics.firstKey());
|
||||||
// Then call the API to get topics, and if it returns successfully, then add the rest of the topics
|
// Then call the API to get topics, and if it returns successfully, then add the rest of the topics
|
||||||
rpc->getZboardTopics([&](QMap<QString, QString> topicsMap) {
|
rpc->getZboardTopics([&](QMap<QString, QString> topicsMap) {
|
||||||
for (auto t : topicsMap.keys()) {
|
for (auto t : topicsMap.keys()) {
|
||||||
topics.insert(t, Settings::getInstance()->isTestnet() ? Settings::getDonationAddr(true) : topicsMap[t]);
|
topics.insert(t, Settings::getInstance()->isTestnet() ? Settings::getDonationAddr() : topicsMap[t]);
|
||||||
zb.topicsList->addItem(t);
|
zb.topicsList->addItem(t);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -791,20 +796,7 @@ void MainWindow::postToZBoard() {
|
|||||||
tx.fee = Settings::getMinerFee();
|
tx.fee = Settings::getMinerFee();
|
||||||
|
|
||||||
// And send the Tx
|
// And send the Tx
|
||||||
rpc->executeTransaction(tx, [=] (QString opid) {
|
rpc->executeStandardUITransaction(tx);
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,7 +817,7 @@ void MainWindow::doImport(QList<QString>* keys) {
|
|||||||
keys->pop_front();
|
keys->pop_front();
|
||||||
bool rescan = keys->isEmpty();
|
bool rescan = keys->isEmpty();
|
||||||
|
|
||||||
if (key.startsWith("S") ||
|
if (key.startsWith("SK") ||
|
||||||
key.startsWith("secret")) { // Z key
|
key.startsWith("secret")) { // Z key
|
||||||
rpc->importZPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
|
rpc->importZPrivKey(key, rescan, [=] (auto) { this->doImport(keys); });
|
||||||
} else {
|
} else {
|
||||||
@@ -949,6 +941,16 @@ void MainWindow::importPrivKey() {
|
|||||||
return key.trimmed().split(" ")[0];
|
return key.trimmed().split(" ")[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Special case.
|
||||||
|
// Sometimes, when importing from a paperwallet or such, the key is split by newlines, and might have
|
||||||
|
// been pasted like that. So check to see if the whole thing is one big private key
|
||||||
|
if (Settings::getInstance()->isValidSaplingPrivateKey(keys->join(""))) {
|
||||||
|
auto multiline = keys;
|
||||||
|
keys = new QList<QString>();
|
||||||
|
keys->append(multiline->join(""));
|
||||||
|
delete multiline;
|
||||||
|
}
|
||||||
|
|
||||||
// Start the import. The function takes ownership of keys
|
// Start the import. The function takes ownership of keys
|
||||||
QTimer::singleShot(1, [=]() {doImport(keys);});
|
QTimer::singleShot(1, [=]() {doImport(keys);});
|
||||||
|
|
||||||
@@ -1304,6 +1306,9 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
|
|||||||
return [=] (bool checked) {
|
return [=] (bool checked) {
|
||||||
if (checked && this->rpc->getAllZAddresses() != nullptr) {
|
if (checked && this->rpc->getAllZAddresses() != nullptr) {
|
||||||
auto addrs = this->rpc->getAllZAddresses();
|
auto addrs = this->rpc->getAllZAddresses();
|
||||||
|
|
||||||
|
// Save the current address, so we can update it later
|
||||||
|
auto zaddr = ui->listReceiveAddresses->currentText();
|
||||||
ui->listReceiveAddresses->clear();
|
ui->listReceiveAddresses->clear();
|
||||||
|
|
||||||
std::for_each(addrs->begin(), addrs->end(), [=] (auto addr) {
|
std::for_each(addrs->begin(), addrs->end(), [=] (auto addr) {
|
||||||
@@ -1315,6 +1320,10 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!zaddr.isEmpty() && Settings::isZAddress(zaddr)) {
|
||||||
|
ui->listReceiveAddresses->setCurrentText(zaddr);
|
||||||
|
}
|
||||||
|
|
||||||
// If z-addrs are empty, then create a new one.
|
// If z-addrs are empty, then create a new one.
|
||||||
if (addrs->isEmpty()) {
|
if (addrs->isEmpty()) {
|
||||||
@@ -1508,6 +1517,10 @@ void MainWindow::setupReceiveTab() {
|
|||||||
void MainWindow::updateTAddrCombo(bool checked) {
|
void MainWindow::updateTAddrCombo(bool checked) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
auto utxos = this->rpc->getUTXOs();
|
auto utxos = this->rpc->getUTXOs();
|
||||||
|
|
||||||
|
// Save the current address so we can restore it later
|
||||||
|
auto currentTaddr = ui->listReceiveAddresses->currentText();
|
||||||
|
|
||||||
ui->listReceiveAddresses->clear();
|
ui->listReceiveAddresses->clear();
|
||||||
|
|
||||||
// Maintain a set of addresses so we don't duplicate any, because we'll be adding
|
// Maintain a set of addresses so we don't duplicate any, because we'll be adding
|
||||||
@@ -1550,7 +1563,17 @@ void MainWindow::updateTAddrCombo(bool checked) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Add a last, disabled item if there are remaining items
|
// 4. Add the previously selected t-address
|
||||||
|
if (!currentTaddr.isEmpty() && Settings::isTAddress(currentTaddr)) {
|
||||||
|
// Make sure the current taddr is in the list
|
||||||
|
if (!addrs.contains(currentTaddr)) {
|
||||||
|
auto bal = rpc->getAllBalances()->value(currentTaddr);
|
||||||
|
ui->listReceiveAddresses->addItem(currentTaddr, bal);
|
||||||
|
}
|
||||||
|
ui->listReceiveAddresses->setCurrentText(currentTaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Add a last, disabled item if there are remaining items
|
||||||
if (allTaddrs->size() > addrs.size()) {
|
if (allTaddrs->size() > addrs.size()) {
|
||||||
auto num = QString::number(allTaddrs->size() - addrs.size());
|
auto num = QString::number(allTaddrs->size() - addrs.size());
|
||||||
ui->listReceiveAddresses->addItem("-- " + num + " more --", 0);
|
ui->listReceiveAddresses->addItem("-- " + num + " more --", 0);
|
||||||
|
|||||||
@@ -1149,14 +1149,6 @@
|
|||||||
<string>&Export all private keys</string>
|
<string>&Export all private keys</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionz_board_net">
|
|
||||||
<property name="text">
|
|
||||||
<string>&z-board.net</string>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut">
|
|
||||||
<string>Ctrl+A, Ctrl+Z</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_Address_Book">
|
<action name="action_Address_Book">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Address &book</string>
|
<string>Address &book</string>
|
||||||
|
|||||||
28
src/rpc.cpp
28
src/rpc.cpp
@@ -27,8 +27,7 @@ RPC::RPC(MainWindow* main) {
|
|||||||
// Setup transactions table model
|
// Setup transactions table model
|
||||||
transactionsTableModel = new TxTableModel(ui->transactionsTable);
|
transactionsTableModel = new TxTableModel(ui->transactionsTable);
|
||||||
main->ui->transactionsTable->setModel(transactionsTableModel);
|
main->ui->transactionsTable->setModel(transactionsTableModel);
|
||||||
main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
|
|
||||||
|
|
||||||
// Set up timer to refresh Price
|
// Set up timer to refresh Price
|
||||||
priceTimer = new QTimer(main);
|
priceTimer = new QTimer(main);
|
||||||
QObject::connect(priceTimer, &QTimer::timeout, [=]() {
|
QObject::connect(priceTimer, &QTimer::timeout, [=]() {
|
||||||
@@ -220,7 +219,7 @@ void RPC::importTPrivKey(QString addr, bool rescan, const std::function<void(jso
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RPC::validateAddress(QString address, const std::function<void(json)>& cb) {
|
void RPC::validateAddress(QString address, const std::function<void(json)>& cb) {
|
||||||
QString method = address.startsWith("z") ? "z_validateaddress" : "validateaddress";
|
QString method = Settings::isZAddress(address) ? "z_validateaddress" : "validateaddress";
|
||||||
|
|
||||||
json payload = {
|
json payload = {
|
||||||
{"jsonrpc", "1.0"},
|
{"jsonrpc", "1.0"},
|
||||||
@@ -963,6 +962,29 @@ void RPC::addNewTxToWatch(const QString& newOpid, WatchedTx wtx) {
|
|||||||
watchTxStatus();
|
watchTxStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a transaction with the standard UI. i.e., standard status bar message and standard error
|
||||||
|
* handling
|
||||||
|
*/
|
||||||
|
void RPC::executeStandardUITransaction(Tx tx) {
|
||||||
|
executeTransaction(tx,
|
||||||
|
[=] (QString opid) {
|
||||||
|
ui->statusBar->showMessage(QObject::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);
|
||||||
|
|
||||||
|
if (!opid.isEmpty())
|
||||||
|
errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr;
|
||||||
|
|
||||||
|
QMessageBox::critical(main, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Execute a transaction!
|
// Execute a transaction!
|
||||||
void RPC::executeTransaction(Tx tx,
|
void RPC::executeTransaction(Tx tx,
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ public:
|
|||||||
void refreshZECPrice();
|
void refreshZECPrice();
|
||||||
void getZboardTopics(std::function<void(QMap<QString, QString>)> cb);
|
void getZboardTopics(std::function<void(QMap<QString, QString>)> cb);
|
||||||
|
|
||||||
|
void executeStandardUITransaction(Tx tx);
|
||||||
|
|
||||||
void executeTransaction(Tx tx,
|
void executeTransaction(Tx tx,
|
||||||
const std::function<void(QString opid)> submitted,
|
const std::function<void(QString opid)> submitted,
|
||||||
const std::function<void(QString opid, QString txid)> computed,
|
const std::function<void(QString opid, QString txid)> computed,
|
||||||
|
|||||||
@@ -512,7 +512,12 @@ Tx MainWindow::createTxFromSendPage() {
|
|||||||
// If address is sprout, then we can't send change to sapling, because of turnstile.
|
// If address is sprout, then we can't send change to sapling, because of turnstile.
|
||||||
sendChangeToSapling = sendChangeToSapling && !Settings::getInstance()->isSproutAddress(addr);
|
sendChangeToSapling = sendChangeToSapling && !Settings::getInstance()->isSproutAddress(addr);
|
||||||
|
|
||||||
double amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount") % QString::number(i+1))->text().trimmed().toDouble();
|
QString amtStr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount") % QString::number(i+1))->text().trimmed();
|
||||||
|
if (amtStr.isEmpty()) {
|
||||||
|
amtStr = "-1";; // The user didn't specify an amount
|
||||||
|
}
|
||||||
|
|
||||||
|
double amt = amtStr.toDouble();
|
||||||
totalAmt += amt;
|
totalAmt += amt;
|
||||||
QString memo = ui->sendToWidgets->findChild<QLabel*>(QString("MemoTxt") % QString::number(i+1))->text().trimmed();
|
QString memo = ui->sendToWidgets->findChild<QLabel*>(QString("MemoTxt") % QString::number(i+1))->text().trimmed();
|
||||||
|
|
||||||
@@ -521,8 +526,7 @@ Tx MainWindow::createTxFromSendPage() {
|
|||||||
|
|
||||||
if (Settings::getInstance()->getAllowCustomFees()) {
|
if (Settings::getInstance()->getAllowCustomFees()) {
|
||||||
tx.fee = ui->minerFeeAmt->text().toDouble();
|
tx.fee = ui->minerFeeAmt->text().toDouble();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
tx.fee = Settings::getMinerFee();
|
tx.fee = Settings::getMinerFee();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,6 +735,8 @@ bool MainWindow::confirmTx(Tx tx, RecurringPaymentInfo* rpi) {
|
|||||||
|
|
||||||
// Send button clicked
|
// Send button clicked
|
||||||
void MainWindow::sendButton() {
|
void MainWindow::sendButton() {
|
||||||
|
// Create a Tx from the values on the send tab. Note that this Tx object
|
||||||
|
// might not be valid yet.
|
||||||
Tx tx = createTxFromSendPage();
|
Tx tx = createTxFromSendPage();
|
||||||
|
|
||||||
QString error = doSendTxValidations(tx);
|
QString error = doSendTxValidations(tx);
|
||||||
@@ -810,7 +816,7 @@ QString MainWindow::doSendTxValidations(Tx tx) {
|
|||||||
// This technically shouldn't be possible, but issue #62 seems to have discovered a bug
|
// This technically shouldn't be possible, but issue #62 seems to have discovered a bug
|
||||||
// somewhere, so just add a check to make sure.
|
// somewhere, so just add a check to make sure.
|
||||||
if (toAddr.amount < 0) {
|
if (toAddr.amount < 0) {
|
||||||
return QString(tr("Amount '%1' is invalid!").arg(toAddr.amount));
|
return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ void Settings::saveRestore(QDialog* d) {
|
|||||||
|
|
||||||
void Settings::saveRestoreTableHeader(QTableView* table, QDialog* d, QString tablename) {
|
void Settings::saveRestoreTableHeader(QTableView* table, QDialog* d, QString tablename) {
|
||||||
table->horizontalHeader()->restoreState(QSettings().value(tablename).toByteArray());
|
table->horizontalHeader()->restoreState(QSettings().value(tablename).toByteArray());
|
||||||
|
table->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
|
||||||
QObject::connect(d, &QDialog::finished, [=](auto) {
|
QObject::connect(d, &QDialog::finished, [=](auto) {
|
||||||
QSettings().setValue(tablename, table->horizontalHeader()->saveState());
|
QSettings().setValue(tablename, table->horizontalHeader()->saveState());
|
||||||
@@ -250,17 +251,12 @@ QString Settings::getTokenName() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Settings::getDonationAddr(bool sapling) {
|
QString Settings::getDonationAddr() {
|
||||||
if (Settings::getInstance()->isTestnet())
|
if (Settings::getInstance()->isTestnet())
|
||||||
if (sapling)
|
|
||||||
return "ztestsapling1wn6889vznyu42wzmkakl2effhllhpe4azhu696edg2x6me4kfsnmqwpglaxzs7tmqsq7kudemp5";
|
return "ztestsapling1wn6889vznyu42wzmkakl2effhllhpe4azhu696edg2x6me4kfsnmqwpglaxzs7tmqsq7kudemp5";
|
||||||
else
|
|
||||||
return "ztn6fYKBii4Fp4vbGhkPgrtLU4XjXp4ZBMZgShtopmDGbn1L2JLTYbBp2b7SSkNr9F3rQeNZ9idmoR7s4JCVUZ7iiM5byhF";
|
|
||||||
else
|
else
|
||||||
if (sapling)
|
|
||||||
return "zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u";
|
return "zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u";
|
||||||
else
|
|
||||||
return "zcEgrceTwvoiFdEvPWcsJHAMrpLsprMF6aRJiQa3fan5ZphyXLPuHghnEPrEPRoEVzUy65GnMVyCTRdkT6BYBepnXh6NBYs";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::addToZcashConf(QString confLocation, QString line) {
|
bool Settings::addToZcashConf(QString confLocation, QString line) {
|
||||||
@@ -320,13 +316,23 @@ double Settings::getZboardAmount() {
|
|||||||
|
|
||||||
QString Settings::getZboardAddr() {
|
QString Settings::getZboardAddr() {
|
||||||
if (Settings::getInstance()->isTestnet()) {
|
if (Settings::getInstance()->isTestnet()) {
|
||||||
return getDonationAddr(true);
|
return getDonationAddr();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return "zs10m00rvkhfm4f7n23e4sxsx275r7ptnggx39ygl0vy46j9mdll5c97gl6dxgpk0njuptg2mn9w5s";
|
return "zs10m00rvkhfm4f7n23e4sxsx275r7ptnggx39ygl0vy46j9mdll5c97gl6dxgpk0njuptg2mn9w5s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::isValidSaplingPrivateKey(QString pk) {
|
||||||
|
if (isTestnet()) {
|
||||||
|
QRegExp zspkey("^secret-extended-key-test[0-9a-z]{278}$", Qt::CaseInsensitive);
|
||||||
|
return zspkey.exactMatch(pk);
|
||||||
|
} else {
|
||||||
|
QRegExp zspkey("^secret-extended-key-main[0-9a-z]{278}$", Qt::CaseInsensitive);
|
||||||
|
return zspkey.exactMatch(pk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Settings::isValidAddress(QString addr) {
|
bool Settings::isValidAddress(QString addr) {
|
||||||
QRegExp zcexp("^z[a-z0-9]{94}$", Qt::CaseInsensitive);
|
QRegExp zcexp("^z[a-z0-9]{94}$", Qt::CaseInsensitive);
|
||||||
QRegExp zsexp("^z[a-z0-9]{77}$", Qt::CaseInsensitive);
|
QRegExp zsexp("^z[a-z0-9]{77}$", Qt::CaseInsensitive);
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ public:
|
|||||||
bool isSaplingAddress(QString addr);
|
bool isSaplingAddress(QString addr);
|
||||||
bool isSproutAddress(QString addr);
|
bool isSproutAddress(QString addr);
|
||||||
|
|
||||||
|
bool isValidSaplingPrivateKey(QString pk);
|
||||||
|
|
||||||
bool isSyncing();
|
bool isSyncing();
|
||||||
void setSyncing(bool syncing);
|
void setSyncing(bool syncing);
|
||||||
|
|
||||||
@@ -101,7 +103,7 @@ public:
|
|||||||
static QString getZECUSDDisplayFormat(double bal);
|
static QString getZECUSDDisplayFormat(double bal);
|
||||||
|
|
||||||
static QString getTokenName();
|
static QString getTokenName();
|
||||||
static QString getDonationAddr(bool sapling);
|
static QString getDonationAddr();
|
||||||
|
|
||||||
static double getMinerFee();
|
static double getMinerFee();
|
||||||
static double getZboardAmount();
|
static double getZboardAmount();
|
||||||
|
|||||||
@@ -104,9 +104,9 @@ void TxTableModel::updateAllData() {
|
|||||||
|
|
||||||
QVariant TxTableModel::data(const QModelIndex &index, int role) const
|
QVariant TxTableModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
// Align column 4,5 (confirmations, amount) right
|
// Align numeric columns (confirmations, amount) right
|
||||||
if (role == Qt::TextAlignmentRole &&
|
if (role == Qt::TextAlignmentRole &&
|
||||||
(index.column() == 3 || index.column() == 4))
|
(index.column() == Column::Confirmations || index.column() == Column::Amount))
|
||||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
|
||||||
auto dat = modeldata->at(index.row());
|
auto dat = modeldata->at(index.row());
|
||||||
@@ -125,23 +125,23 @@ void TxTableModel::updateAllData() {
|
|||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case 0: return dat.type;
|
case Column::Type: return dat.type;
|
||||||
case 1: {
|
case Column::Address: {
|
||||||
auto addr = dat.address;
|
auto addr = dat.address;
|
||||||
if (addr.trimmed().isEmpty())
|
if (addr.trimmed().isEmpty())
|
||||||
return "(Shielded)";
|
return "(Shielded)";
|
||||||
else
|
else
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
case 2: return QDateTime::fromMSecsSinceEpoch(dat.datetime * (qint64)1000).toLocalTime().toString();
|
case Column::Time: return QDateTime::fromMSecsSinceEpoch(dat.datetime * (qint64)1000).toLocalTime().toString();
|
||||||
case 3: return QString::number(dat.confirmations);
|
case Column::Confirmations: return QString::number(dat.confirmations);
|
||||||
case 4: return Settings::getZECDisplayFormat(dat.amount);
|
case Column::Amount: return Settings::getZECDisplayFormat(dat.amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role == Qt::ToolTipRole) {
|
if (role == Qt::ToolTipRole) {
|
||||||
switch (index.column()) {
|
switch (index.column()) {
|
||||||
case 0: {
|
case Column::Type: {
|
||||||
if (dat.memo.startsWith("zcash:")) {
|
if (dat.memo.startsWith("zcash:")) {
|
||||||
return Settings::paymentURIPretty(Settings::parseURI(dat.memo));
|
return Settings::paymentURIPretty(Settings::parseURI(dat.memo));
|
||||||
} else {
|
} else {
|
||||||
@@ -149,16 +149,16 @@ void TxTableModel::updateAllData() {
|
|||||||
(dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\"");
|
(dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 1: {
|
case Column::Address: {
|
||||||
auto addr = modeldata->at(index.row()).address;
|
auto addr = modeldata->at(index.row()).address;
|
||||||
if (addr.trimmed().isEmpty())
|
if (addr.trimmed().isEmpty())
|
||||||
return "(Shielded)";
|
return "(Shielded)";
|
||||||
else
|
else
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
case 2: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * (qint64)1000).toLocalTime().toString();
|
case Column::Time: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * (qint64)1000).toLocalTime().toString();
|
||||||
case 3: return QString("%1 Network Confirmations").arg(QString::number(dat.confirmations));
|
case Column::Confirmations: return QString("%1 Network Confirmations").arg(QString::number(dat.confirmations));
|
||||||
case 4: return Settings::getInstance()->getUSDFromZecAmount(modeldata->at(index.row()).amount);
|
case Column::Amount: return Settings::getInstance()->getUSDFromZecAmount(modeldata->at(index.row()).amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ void TxTableModel::updateAllData() {
|
|||||||
|
|
||||||
QVariant TxTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant TxTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
if (role == Qt::TextAlignmentRole && (section == 3 || section == 4))
|
if (role == Qt::TextAlignmentRole && (section == Column::Confirmations || section == Column::Amount))
|
||||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
|
|
||||||
if (role == Qt::FontRole) {
|
if (role == Qt::FontRole) {
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ public:
|
|||||||
TxTableModel(QObject* parent);
|
TxTableModel(QObject* parent);
|
||||||
~TxTableModel();
|
~TxTableModel();
|
||||||
|
|
||||||
|
enum Column
|
||||||
|
{
|
||||||
|
Type = 0,
|
||||||
|
Address = 1,
|
||||||
|
Time = 2,
|
||||||
|
Confirmations = 3,
|
||||||
|
Amount = 4
|
||||||
|
};
|
||||||
|
|
||||||
void addTData (const QList<TransactionItem>& data);
|
void addTData (const QList<TransactionItem>& data);
|
||||||
void addZSentData(const QList<TransactionItem>& data);
|
void addZSentData(const QList<TransactionItem>& data);
|
||||||
void addZRecvData(const QList<TransactionItem>& data);
|
void addZRecvData(const QList<TransactionItem>& data);
|
||||||
|
|||||||
Reference in New Issue
Block a user