Merge branch 'master' into turnstile

This commit is contained in:
Aditya Kulkarni
2018-10-28 21:32:46 -07:00
19 changed files with 147 additions and 103 deletions

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@ src/precompiled.h.cpp
.qmake.stash
zec-qt-wallet
zec-qt-wallet.vcxproj*
zec-qt-wallet.sln
zec-qt-wallet.pro.user
Makefile
Makefile.*

View File

@@ -9,8 +9,8 @@ Head over to the releases page and grab the latest binary. https://github.com/ad
### Linux
Extract and run the binary
```
tar -xvf zec-qt-wallet-v0.2.3.tar.gz
./zec-qt-wallet-v0.2.3/zec-qt-wallet
tar -xvf zec-qt-wallet-v0.2.4.tar.gz
./zec-qt-wallet-v0.2.4/zec-qt-wallet
```
### Windows
@@ -89,6 +89,6 @@ The most likely cause for this is that you are trying to spend unconfirmed funds
1-2 blocks for the funds to confirm and retry the transaction.
### Support or other questions
Tweet at [@zcashqtwallet](https://twitter.com/zcashqtwallet) for help.
Tweet at [@zecqtwallet](https://twitter.com/zecqtwallet) for help.
_PS: zec-qt-wallet is NOT an official wallet, and is not affiliated with the Zerocoin Electric Coin Company in any way._

View File

@@ -20,8 +20,8 @@ void BalancesTableModel::setNewData(const QMap<QString, double>* balances,
// Process the address balances into a list
delete modeldata;
modeldata = new QList<std::tuple<QString, QString>>();
std::for_each(balances->constKeyValueBegin(), balances->constKeyValueEnd(), [=] (auto it) {
modeldata->push_back(std::make_tuple(it.first, QString::number(it.second, 'g', 8)));
std::for_each(balances->keyBegin(), balances->keyEnd(), [=] (auto keyIt) {
modeldata->push_back(std::make_tuple(keyIt, QString::number(balances->value(keyIt), 'g', 8)));
});
// And then update the data

View File

@@ -132,6 +132,9 @@
<property name="text">
<string>TextLabel</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">

View File

@@ -64,7 +64,7 @@ MainWindow::MainWindow(QWidget *parent) :
rpc = new RPC(new QNetworkAccessManager(this), this);
rpc->refreshZECPrice();
rpc->refresh();
rpc->refresh(true); // Force refresh first time
}
void MainWindow::turnstileProgress() {
@@ -249,7 +249,7 @@ void MainWindow::setupStatusBar() {
}
menu.addAction("Refresh", [=]() {
rpc->refresh();
rpc->refresh(true);
});
QPoint gpos(mapToGlobal(pos).x(), mapToGlobal(pos).y() + this->height() - ui->statusBar->height());
menu.exec(gpos);
@@ -262,8 +262,7 @@ void MainWindow::setupStatusBar() {
ui->statusBar->addPermanentWidget(statusIcon);
}
void MainWindow::setupSettingsModal() {
void MainWindow::setupSettingsModal() {
// Set up File -> Settings action
QObject::connect(ui->actionSettings, &QAction::triggered, [=]() {
QDialog settingsDialog(this);
@@ -282,7 +281,7 @@ void MainWindow::setupSettingsModal() {
QMessageBox::Yes, QMessageBox::Cancel)) {
SentTxStore::deleteHistory();
// Reload after the clear button so existing txs disappear
rpc->refresh();
rpc->refresh(true);
}
});
@@ -332,7 +331,7 @@ void MainWindow::setupSettingsModal() {
}
// Then refresh everything.
this->rpc->refresh();
this->rpc->refresh(true);
};
});
@@ -340,7 +339,8 @@ void MainWindow::setupSettingsModal() {
void MainWindow::donate() {
// Set up a donation to me :)
ui->Address1->setText(Utils::getDonationAddr());
ui->Address1->setText(Utils::getDonationAddr(
Settings::getInstance()->isSaplingAddress(ui->inputsCombo->currentText())));
ui->Address1->setCursorPosition(0);
ui->Amount1->setText("0.01");
@@ -392,6 +392,19 @@ void MainWindow::setupBalancesTab() {
ui->statusBar->showMessage("Copied to clipboard", 3 * 1000);
});
menu.addAction("Send from " % addr.left(40) % (addr.size() > 40 ? "..." : ""), [=]() {
// Find the inputs combo
for (int i = 0; i < ui->inputsCombo->count(); i++) {
if (ui->inputsCombo->itemText(i).startsWith(addr)) {
ui->inputsCombo->setCurrentIndex(i);
break;
}
}
// And switch to the send tab.
ui->tabWidget->setCurrentIndex(1);
});
if (addr.startsWith("t")) {
menu.addAction("View on block explorer", [=] () {
QString url;

View File

@@ -422,6 +422,9 @@
<property name="text">
<string/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>

View File

@@ -6,17 +6,14 @@
<rect>
<x>0</x>
<y>0</y>
<width>618</width>
<height>115</height>
<width>520</width>
<height>168</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="memoTxt"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
@@ -27,14 +24,14 @@
<item row="0" column="1">
<widget class="QLabel" name="memoSize">
<property name="text">
<string>6 / 512</string>
<string>0 / 512</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -44,18 +41,8 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<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 row="1" column="0" colspan="2">
<widget class="QPlainTextEdit" name="memoTxt"/>
</item>
</layout>
</widget>

View File

@@ -349,6 +349,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
QSet<QString> txids;
QMap<QString, QString> memos;
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
auto zaddr = it.key();
for (auto& i : it.value().get<json::array_t>()) {
// Filter out change txs
if (! i["change"].get<json::boolean_t>()) {
@@ -361,7 +362,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
QString memo(QByteArray::fromHex(
QByteArray::fromStdString(i["memo"].get<json::string_t>())));
if (!memo.trimmed().isEmpty())
memos[txid] = memo;
memos[zaddr + txid] = memo;
}
}
}
@@ -406,7 +407,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
auto confirmations = txidInfo["confirmations"].get<json::number_unsigned_t>();
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
confirmations, "", memos.value(txid, "") };
confirmations, "", memos.value(zaddr + txid, "") };
txdata.push_front(tx);
}
}
@@ -424,13 +425,12 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
/// This will refresh all the balance data from zcashd
void RPC::refresh() {
// First, test the connection to see if we can actually get info.
getInfoThenRefresh();
void RPC::refresh(bool force) {
getInfoThenRefresh(force);
}
void RPC::getInfoThenRefresh() {
void RPC::getInfoThenRefresh(bool force) {
json payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
@@ -447,10 +447,17 @@ void RPC::getInfoThenRefresh() {
QIcon i(":/icons/res/connected.png");
main->statusIcon->setPixmap(i.pixmap(16, 16));
// Refresh everything.
refreshBalances();
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
static int lastBlock = 0;
int curBlock = reply["blocks"].get<json::number_integer_t>();
if ( force || (curBlock != lastBlock) ) {
// Something changed, so refresh everything.
lastBlock = curBlock;
refreshBalances();
refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans()
refreshTransactions();
}
// Call to see if the blockchain is syncing.
json payload = {
@@ -679,7 +686,7 @@ void RPC::watchTxStatus() {
watchingOps.remove(id);
// Refresh balances to show unconfirmed balances
refresh();
refresh(true);
} else if (status == "failed") {
// If it failed, then we'll actually show a warning.
auto errorMsg = QString::fromStdString(it["error"]["message"]);

View File

@@ -30,8 +30,9 @@ public:
RPC(QNetworkAccessManager* restclient, MainWindow* main);
~RPC();
void refresh(); // Refresh all transactions
void refreshAddresses(); // Refresh wallet Z-addrs
void refresh(bool force = false);
void refreshAddresses();
void refreshZECPrice();
void fillTxJsonParams(json& params, Tx tx);
@@ -113,7 +114,7 @@ private:
bool processUnspent (const json& reply);
void updateUI (bool anyUnconfirmed);
void getInfoThenRefresh();
void getInfoThenRefresh(bool force);
void getBalance(const std::function<void(json)>& cb);

View File

@@ -3,6 +3,14 @@ if (-not (Test-Path env:APP_VERSION)) { echo "APP_VERSION is not set. Please set
$target="zec-qt-wallet-v$Env:APP_VERSION"
echo "Git Status"
$branch= &git branch | select -first 1
if ($branch -ne "* master") {
echo "Not on master branch!"
exit;
}
git pull
echo "Cleaning"
nmake clean *>$null
Remove-Item -Path debug -Recurse | Out-Null
@@ -27,12 +35,12 @@ Copy-Item README.md release/$target | Out-Null
echo "Zipping"
Compress-Archive -LiteralPath release/$target -DestinationPath "release/Windows-$target.zip"
echo "Package Contents"
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
foreach($sourceFile in (Get-ChildItem "release/Windows-$target.zip"))
{
[IO.Compression.ZipFile]::OpenRead($sourceFile.FullName).Entries.FullName |
%{ "$sourcefile`:$_" }
}
#echo "Package Contents"
#[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem')
#foreach($sourceFile in (Get-ChildItem "release/Windows-$target.zip"))
#{
# [IO.Compression.ZipFile]::OpenRead($sourceFile.FullName).Entries.FullName |
# %{ "$sourcefile`:$_" }
#}
echo "Done"

View File

@@ -36,18 +36,18 @@ void MainWindow::setupSendTab() {
// The first Memo button
QObject::connect(ui->MemoBtn1, &QPushButton::clicked, [=] () {
memoButtonClicked(1);
this->memoButtonClicked(1);
});
setMemoEnabled(1, false);
// The first Address button
QObject::connect(ui->Address1, &QLineEdit::textChanged, [=] (auto text) {
addressChanged(1, text);
this->addressChanged(1, text);
});
// The first Amount button
QObject::connect(ui->Amount1, &QLineEdit::textChanged, [=] (auto text) {
amountChanged(1, text);
this->amountChanged(1, text);
});
// Font for the first Memo label
@@ -139,7 +139,7 @@ void MainWindow::addAddressSection() {
Address1->setObjectName(QString("Address") % QString::number(itemNumber));
Address1->setPlaceholderText("Address");
QObject::connect(Address1, &QLineEdit::textChanged, [=] (auto text) {
addressChanged(itemNumber, text);
this->addressChanged(itemNumber, text);
});
horizontalLayout_12->addWidget(Address1);
@@ -160,7 +160,7 @@ void MainWindow::addAddressSection() {
auto amtValidator = new QDoubleValidator(0, 21000000, 8, Amount1);
Amount1->setValidator(amtValidator);
QObject::connect(Amount1, &QLineEdit::textChanged, [=] (auto text) {
amountChanged(itemNumber, text);
this->amountChanged(itemNumber, text);
});
horizontalLayout_13->addWidget(Amount1);
@@ -177,7 +177,7 @@ void MainWindow::addAddressSection() {
MemoBtn1->setText("Memo");
// Connect Memo Clicked button
QObject::connect(MemoBtn1, &QPushButton::clicked, [=] () {
memoButtonClicked(itemNumber);
this->memoButtonClicked(itemNumber);
});
horizontalLayout_13->addWidget(MemoBtn1);
setMemoEnabled(itemNumber, false);
@@ -189,6 +189,7 @@ void MainWindow::addAddressSection() {
QFont font1 = Address1->font();
font1.setPointSize(font1.pointSize()-1);
MemoTxt1->setFont(font1);
MemoTxt1->setWordWrap(true);
sendAddressLayout->addWidget(MemoTxt1);
ui->sendToLayout->insertWidget(itemNumber-1, verticalGroupBox);
@@ -232,33 +233,26 @@ void MainWindow::memoButtonClicked(int number) {
return;
}
auto memoTxt = ui->sendToWidgets->findChild<QLabel *>(QString("MemoTxt") + QString::number(number));
// Get the current memo if it exists
auto memoTxt = ui->sendToWidgets->findChild<QLabel *>(QString("MemoTxt") + QString::number(number));
QString currentMemo = memoTxt->text();
// Ref to see if the button was clicked
// bool ok;
// QString newMemo = QInputDialog::getText(this, "Memo",
// "Please type a memo to include with the amount. The memo will be visible to the recepient",
// QLineEdit::Normal, currentMemo, &ok);
Ui_MemoDialog memoDialog;
QDialog dialog(this);
memoDialog.setupUi(&dialog);
QObject::connect(memoDialog.memoTxt, &QLineEdit::textChanged, [=] (QString txt) {
QObject::connect(memoDialog.memoTxt, &QPlainTextEdit::textChanged, [=] () {
QString txt = memoDialog.memoTxt->toPlainText();
memoDialog.memoSize->setText(QString::number(txt.toUtf8().size()) + "/512");
memoDialog.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(txt.toUtf8().size() <= 512);
if (txt.toUtf8().size() > 512) {
memoDialog.memoSize->setStyleSheet("color: red;");
} else {
memoDialog.memoSize->setStyleSheet("");
}
});
memoDialog.memoTxt->setText(currentMemo);
memoDialog.memoTxt->setPlainText(currentMemo);
memoDialog.memoTxt->setFocus();
if (dialog.exec() == QDialog::Accepted) {
memoTxt->setText(memoDialog.memoTxt->text());
memoTxt->setText(memoDialog.memoTxt->toPlainText());
}
}
@@ -412,6 +406,7 @@ bool MainWindow::confirmTx(Tx tx, ToFields devFee) {
QFont font1 = Addr->font();
font1.setPointSize(font1.pointSize() - 1);
Memo->setFont(font1);
Memo->setWordWrap(true);
confirm.gridLayout->addWidget(Memo, (i*2)+1, 0, 1, 3);
}

View File

@@ -87,7 +87,7 @@ void SentTxStore::addToSentTx(Tx tx, QString txid) {
QJsonObject txItem;
txItem["type"] = "sent";
txItem["from"] = tx.fromAddr;
txItem["datetime"] = QDateTime().currentSecsSinceEpoch();
txItem["datetime"] = QDateTime().currentMSecsSinceEpoch() / 1000;
txItem["address"] = QString(); // The sent address is blank, to be consistent with t-Addr sent behaviour
txItem["txid"] = txid;
txItem["amount"] = -totalAmount;

View File

@@ -5,7 +5,7 @@
TxTableModel::TxTableModel(QObject *parent)
: QAbstractTableModel(parent) {
headers << "Category" << "Address" << "Date/Time" << "Amount";
headers << "Type" << "Address" << "Date/Time" << "Amount";
}
TxTableModel::~TxTableModel() {
@@ -86,10 +86,11 @@ void TxTableModel::updateAllData() {
b.setColor(Qt::black);
return b;
}
if (role == Qt::DisplayRole || role == Qt::ToolTipRole) {
auto dat = modeldata->at(index.row());
if (role == Qt::DisplayRole) {
switch (index.column()) {
case 0: return modeldata->at(index.row()).type;
case 0: return dat.type;
case 1: {
auto addr = modeldata->at(index.row()).address;
if (addr.trimmed().isEmpty())
@@ -97,14 +98,37 @@ void TxTableModel::updateAllData() {
else
return addr;
}
case 2: return QDateTime::fromSecsSinceEpoch(modeldata->at(index.row()).datetime).toLocalTime().toString();
case 3: {
if (role == Qt::DisplayRole)
return Settings::getInstance()->getZECDisplayFormat(modeldata->at(index.row()).amount);
else {
return Settings::getInstance()->getUSDFormat(modeldata->at(index.row()).amount);
case 2: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * 1000).toLocalTime().toString();
case 3: return Settings::getInstance()->getZECDisplayFormat(modeldata->at(index.row()).amount);
}
}
if (role == Qt::ToolTipRole) {
switch (index.column()) {
case 0: return modeldata->at(index.row()).type +
(dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\"");
case 1: {
auto addr = modeldata->at(index.row()).address;
if (addr.trimmed().isEmpty())
return "(Shielded)";
else
return addr;
}
}
case 2: return QDateTime::fromMSecsSinceEpoch(modeldata->at(index.row()).datetime * 1000).toLocalTime().toString();
case 3: return Settings::getInstance()->getUSDFormat(modeldata->at(index.row()).amount);
}
}
if (role == Qt::DecorationRole && index.column() == 0) {
if (!dat.memo.isEmpty()) {
// Return the info pixmap to indicate memo
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
return QVariant(icon.pixmap(16, 16));
} else {
// Empty pixmap to make it align
QPixmap p(16, 16);
p.fill(Qt::white);
return QVariant(p);
}
}

View File

@@ -125,6 +125,7 @@ public:
Memo1 = new QLabel(sendToAddrs);
Memo1->setObjectName(QStringLiteral("Memo1"));
Memo1->setWordWrap(true);
gridLayout->addWidget(Memo1, 1, 0, 1, 3);

View File

@@ -438,6 +438,7 @@ public:
QFont font1;
font1.setPointSize(10);
MemoTxt1->setFont(font1);
MemoTxt1->setWordWrap(true);
sendAddressLayout->addWidget(MemoTxt1);

View File

@@ -15,8 +15,7 @@
#include <QtWidgets/QDialogButtonBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QSpacerItem>
#include <QtWidgets/QPlainTextEdit>
QT_BEGIN_NAMESPACE
@@ -24,24 +23,18 @@ class Ui_MemoDialog
{
public:
QGridLayout *gridLayout;
QLineEdit *memoTxt;
QLabel *label;
QLabel *memoSize;
QDialogButtonBox *buttonBox;
QSpacerItem *verticalSpacer;
QPlainTextEdit *memoTxt;
void setupUi(QDialog *MemoDialog)
{
if (MemoDialog->objectName().isEmpty())
MemoDialog->setObjectName(QStringLiteral("MemoDialog"));
MemoDialog->resize(618, 115);
MemoDialog->resize(520, 168);
gridLayout = new QGridLayout(MemoDialog);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
memoTxt = new QLineEdit(MemoDialog);
memoTxt->setObjectName(QStringLiteral("memoTxt"));
gridLayout->addWidget(memoTxt, 1, 0, 1, 2);
label = new QLabel(MemoDialog);
label->setObjectName(QStringLiteral("label"));
@@ -58,11 +51,12 @@ public:
buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
gridLayout->addWidget(buttonBox, 3, 0, 1, 2);
gridLayout->addWidget(buttonBox, 2, 0, 1, 2);
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
memoTxt = new QPlainTextEdit(MemoDialog);
memoTxt->setObjectName(QStringLiteral("memoTxt"));
gridLayout->addItem(verticalSpacer, 2, 0, 1, 2);
gridLayout->addWidget(memoTxt, 1, 0, 1, 2);
retranslateUi(MemoDialog);
@@ -76,7 +70,7 @@ public:
{
MemoDialog->setWindowTitle(QApplication::translate("MemoDialog", "Dialog", nullptr));
label->setText(QApplication::translate("MemoDialog", "Memo", nullptr));
memoSize->setText(QApplication::translate("MemoDialog", "6 / 512", nullptr));
memoSize->setText(QApplication::translate("MemoDialog", "0 / 512", nullptr));
} // retranslateUi
};

View File

@@ -12,11 +12,17 @@ const QString Utils::getTokenName() {
}
}
const QString Utils::getDonationAddr() {
const QString Utils::getDonationAddr(bool sapling) {
if (Settings::getInstance()->isTestnet())
return "tmP1JL19JyJh3jPMUbfovk4W67jB7VJWybu";
if (sapling)
return "ztestsapling1kdp74adyfsmm9838jaupgfyx3npgw8ut63stjjx757pc248cuc0ymzphqeux60c64qe5qt68ygh";
else
return "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D";
else
return "t1KfJJrSuVYmnNLrw7EZHRv1kZY3zdGGLyb";
if (sapling)
return "zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u";
else
return "zcEgrceTwvoiFdEvPWcsJHAMrpLsprMF6aRJiQa3fan5ZphyXLPuHghnEPrEPRoEVzUy65GnMVyCTRdkT6BYBepnXh6NBYs";
}
const QString Utils::getDevSproutAddr() {

View File

@@ -14,7 +14,7 @@ public:
static const QString getTokenName();
static const QString getDevSproutAddr();
static const QString getDevAddr(Tx tx);
static const QString getDonationAddr();
static const QString getDonationAddr(bool sapling);
static double getMinerFee();
static double getDevFee();

View File

@@ -13,7 +13,7 @@ PRECOMPILED_HEADER = src/precompiled.h
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = zec-qt-wallet
APP_VERSION=\\\"0.2.3\\\"
APP_VERSION=\\\"0.2.4\\\"
TEMPLATE = app