Browse Source

merge

import_zecw
Aditya Kulkarni 6 years ago
parent
commit
e7bf6b1677
  1. 12
      README.md
  2. 2
      application.qrc
  3. BIN
      docs/screenshot-main.png
  4. BIN
      res/connected.gif
  5. BIN
      res/connected.png
  6. 125
      src/addressbook.cpp
  7. 13
      src/addressbook.h
  8. 2
      src/main.cpp
  9. 79
      src/mainwindow.cpp
  10. 7
      src/mainwindow.h
  11. 1
      src/precompiled.h
  12. 57
      src/rpc.cpp
  13. 2
      src/rpc.h
  14. 2
      src/scripts/mkrelease.sh
  15. 28
      src/sendtab.cpp
  16. 8
      src/settings.cpp
  17. 5
      src/settings.h
  18. 71
      src/txid.ui
  19. 35
      src/utils.cpp
  20. 12
      src/zboard.ui
  21. 2
      zec-qt-wallet.pro

12
README.md

@ -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.8.tar.gz
./zec-qt-wallet-v0.2.8/zec-qt-wallet
tar -xvf zec-qt-wallet-v0.2.9.tar.gz
./zec-qt-wallet-v0.2.9/zec-qt-wallet
```
### Windows
@ -24,7 +24,7 @@ There is currently no official zcashd build for Windows so Windows users may eit
Alternatively run zcashd inside [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
For all installations zcashd needs to run with RPC enabled (`server=1`, which is the default) and with a RPC username/password set. Add the following entries into `~/.zcash/zcash.conf` for Linux or` C:\Users\your-username\AppData\Roaming\Zcash\zcash.conf` on Windows replacing the default values with a strong password. zec-qt-wallet should detect these settings but if that fails you may edit the connection settings manually via the `File->Settings` menu.
For all installations zcashd needs to run with RPC enabled (`server=1`, which is the default) and with a RPC username/password set. Add the following entries into `~/.zcash/zcash.conf` for Linux or` C:\Users\your-username\AppData\Roaming\Zcash\zcash.conf` on Windows replacing the default values with a strong password. zec-qt-wallet should detect these settings but if that fails you may edit the connection settings manually via the `Edit->Settings` menu.
```
rpcuser=username
@ -41,7 +41,7 @@ https://z.cash/downloads/sprout-proving.key
https://z.cash/downloads/sprout-verifying.key
```
If you are running zcashd on WSL, then please set the connection parameters in the `File->Settings` menu.
If you are running zcashd on WSL, then please set the connection parameters in the `Edit->Settings` menu.
## Compiling from source
zec-qt-wallet is written in C++ 14, and can be compiled with g++/clang++/visual c++. It also depends on Qt5, which you can get from here: https://www.qt.io/download
@ -49,6 +49,8 @@ zec-qt-wallet is written in C++ 14, and can be compiled with g++/clang++/visual
### Compiling on Linux
```
sudo apt install libgl1-mesa-dev
git clone https://github.com/adityapk00/zec-qt-wallet.git
cd zec-qt-wallet
/path/to/qt5/bin/qmake zec-qt-wallet.pro CONFIG+=debug
@ -64,7 +66,7 @@ From the VS Tools command prompt
```
git clone https://github.com/adityapk00/zec-qt-wallet.git
cd zec-qt-wallet
c:\Qt5\bin\qmake.exe zec-qt-wallet.pro CONFIG+=debug
c:\Qt5\bin\qmake.exe zec-qt-wallet.pro -spec win32-msvc CONFIG+=debug
nmake
debug\zec-qt-wallet.exe

2
application.qrc

@ -3,7 +3,7 @@
<file>res/Ubuntu-R.ttf</file>
</qresource>
<qresource prefix="/icons">
<file>res/connected.png</file>
<file>res/connected.gif</file>
<file>res/loading.gif</file>
<file>res/icon.ico</file>
</qresource>

BIN
docs/screenshot-main.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 72 KiB

BIN
res/connected.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
res/connected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

125
src/addressbook.cpp

@ -10,83 +10,56 @@ AddressBookModel::AddressBookModel(QTableView *parent)
headers << "Label" << "Address";
this->parent = parent;
loadDataFromStorage();
loadData();
}
AddressBookModel::~AddressBookModel() {
if (labels != nullptr)
saveDataToStorage();
delete labels;
saveData();
}
void AddressBookModel::saveDataToStorage() {
QFile file(writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file
out << QString("v1") << *labels;
file.close();
void AddressBookModel::saveData() {
AddressBook::writeToStorage(labels);
// Save column positions
QSettings().setValue("addresstablegeometry", parent->horizontalHeader()->saveState());
}
void AddressBookModel::loadDataFromStorage() {
QFile file(writeableFile());
delete labels;
labels = new QList<QPair<QString, QString>>();
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file
QString version;
in >> version >> *labels;
file.close();
void AddressBookModel::loadData() {
labels = AddressBook::readFromStorage();
parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray());
}
void AddressBookModel::addNewLabel(QString label, QString addr) {
labels->push_back(QPair<QString, QString>(label, addr));
labels.push_back(QPair<QString, QString>(label, addr));
AddressBook::writeToStorage(labels);
dataChanged(index(0, 0), index(labels->size()-1, columnCount(index(0,0))-1));
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
void AddressBookModel::removeItemAt(int row) {
if (row >= labels->size())
if (row >= labels.size())
return;
labels->removeAt(row);
dataChanged(index(0, 0), index(labels->size()-1, columnCount(index(0,0))-1));
labels.removeAt(row);
AddressBook::writeToStorage(labels);
dataChanged(index(0, 0), index(labels.size()-1, columnCount(index(0,0))-1));
layoutChanged();
}
QPair<QString, QString> AddressBookModel::itemAt(int row) {
if (row >= labels->size()) return QPair<QString, QString>();
if (row >= labels.size()) return QPair<QString, QString>();
return labels->at(row);
return labels.at(row);
}
QString AddressBookModel::writeableFile() {
auto filename = QStringLiteral("addresslabels.dat");
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);
}
}
int AddressBookModel::rowCount(const QModelIndex&) const {
if (labels == nullptr) return 0;
return labels->size();
return labels.size();
}
int AddressBookModel::columnCount(const QModelIndex&) const {
@ -97,12 +70,12 @@ int AddressBookModel::columnCount(const QModelIndex&) const {
QVariant AddressBookModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) {
switch(index.column()) {
case 0: return labels->at(index.row()).first;
case 1: return labels->at(index.row()).second;
case 0: return labels.at(index.row()).first;
case 1: return labels.at(index.row()).second;
}
}
return QVariant();
}
}
QVariant AddressBookModel::headerData(int section, Qt::Orientation orientation, int role) const {
@ -117,6 +90,7 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
QDialog d(parent);
Ui_addressBook ab;
ab.setupUi(&d);
Settings::saveRestore(&d);
AddressBookModel model(ab.addresses);
ab.addresses->setModel(&model);
@ -126,6 +100,9 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
ab.buttonBox->button(QDialogButtonBox::Ok)->setText("Pick");
}
// Connect the dialog's closing to updating the label address completor
QObject::connect(&d, &QDialog::finished, [=] (auto) { parent->updateLabelsAutoComplete(); });
// If there is a target then make it the addr for the "Add to" button
if (target != nullptr && Utils::isValidAddress(target->text())) {
ab.addr->setText(target->text());
@ -145,13 +122,18 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
}
});
auto fnSetTargetLabelAddr = [=] (QLineEdit* target, QString label, QString addr) {
target->setText(label % "/" % addr);
};
// Double-Click picks the item
QObject::connect(ab.addresses, &QTableView::doubleClicked, [&] (auto index) {
if (index.row() < 0) return;
QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second;
d.accept();
target->setText(addr);
fnSetTargetLabelAddr(target, lbl, addr);
});
// Right-Click
@ -161,13 +143,15 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (index.row() < 0) return;
QString lbl = model.itemAt(index.row()).first;
QString addr = model.itemAt(index.row()).second;
QMenu menu(parent);
if (target != nullptr) {
menu.addAction("Pick", [&] () {
target->setText(addr);
d.accept();
fnSetTargetLabelAddr(target, lbl, addr);
});
}
@ -186,7 +170,46 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (d.exec() == QDialog::Accepted && target != nullptr) {
auto selection = ab.addresses->selectionModel();
if (selection->hasSelection()) {
target->setText(model.itemAt(selection->selectedRows().at(0).row()).second);
auto item = model.itemAt(selection->selectedRows().at(0).row());
fnSetTargetLabelAddr(target, item.first, item.second);
}
};
}
QList<QPair<QString, QString>> AddressBook::readFromStorage() {
QFile file(AddressBook::writeableFile());
QList<QPair<QString, QString>> labels;
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file
QString version;
in >> version >> labels;
file.close();
return labels;
}
void AddressBook::writeToStorage(QList<QPair<QString, QString>> labels) {
QFile file(AddressBook::writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file
out << QString("v1") << labels;
file.close();
}
QString AddressBook::writeableFile() {
auto filename = QStringLiteral("addresslabels.dat");
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);
}
}

13
src/addressbook.h

@ -21,19 +21,22 @@ public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
private:
void loadDataFromStorage();
void saveDataToStorage();
QString writeableFile();
void loadData();
void saveData();
QTableView* parent;
QList<QPair<QString, QString>>* labels = nullptr;
QList<QPair<QString, QString>> labels;
QStringList headers;
};
class AddressBook {
public:
static void open(MainWindow* parent, QLineEdit* target = nullptr);
static QList<QPair<QString, QString>> readFromStorage();
static void writeToStorage(QList<QPair<QString, QString>> labels);
static QString writeableFile();
};
#endif // ADDRESSBOOK_H

2
src/main.cpp

@ -18,7 +18,7 @@ int main(int argc, char *argv[])
qApp->setFont(QFont("Ubuntu", 11, QFont::Normal, false));
#endif
std::srand(std::time(nullptr));
std::srand(static_cast<unsigned int>(std::time(nullptr)));
Settings::init();
Settings::getInstance()->setExecName(argv[0]);

79
src/mainwindow.cpp

@ -109,6 +109,7 @@ void MainWindow::turnstileProgress() {
Ui_TurnstileProgress progress;
QDialog d(this);
progress.setupUi(&d);
Settings::saveRestore(&d);
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
progress.msgIcon->setPixmap(icon.pixmap(64, 64));
@ -189,6 +190,7 @@ void MainWindow::turnstileDoMigration(QString fromAddr) {
Ui_Turnstile turnstile;
QDialog d(this);
turnstile.setupUi(&d);
Settings::saveRestore(&d);
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation);
turnstile.msgIcon->setPixmap(icon.pixmap(64, 64));
@ -240,8 +242,7 @@ void MainWindow::turnstileDoMigration(QString fromAddr) {
if (!fromAddr.isEmpty())
turnstile.migrateZaddList->setCurrentText(fromAddr);
fnUpdateSproutBalance(turnstile.migrateZaddList->currentText());
fnUpdateSproutBalance(turnstile.migrateZaddList->currentText());
// Combo box selection event
QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, fnUpdateSproutBalance);
@ -349,6 +350,7 @@ void MainWindow::setupSettingsModal() {
QDialog settingsDialog(this);
Ui_Settings settings;
settings.setupUi(&settingsDialog);
Settings::saveRestore(&settingsDialog);
// Setup save sent check box
QObject::connect(settings.chkSaveTxs, &QCheckBox::stateChanged, [=](auto checked) {
@ -412,7 +414,7 @@ void MainWindow::setupSettingsModal() {
auto cl = new ConnectionLoader(this, rpc);
cl->loadConnection();
}
};
}
});
}
@ -449,6 +451,10 @@ void MainWindow::postToZBoard() {
QDialog d(this);
Ui_zboard zb;
zb.setupUi(&d);
Settings::saveRestore(&d);
if (rpc->getConnection() == nullptr)
return;
// Fill the from field with sapling addresses.
for (auto i = rpc->getAllBalances()->keyBegin(); i != rpc->getAllBalances()->keyEnd(); i++) {
@ -457,6 +463,18 @@ void MainWindow::postToZBoard() {
}
}
QMap<QString, QString> topics;
// Insert the main topic automatically
topics.insert("#Main_Area", Utils::getZboardAddr());
zb.topicsList->addItem(topics.firstKey());
// 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) {
for (auto t : topicsMap.keys()) {
topics.insert(t, topicsMap[t]);
zb.topicsList->addItem(t);
}
});
// Testnet warning
if (Settings::getInstance()->isTestnet()) {
zb.testnetWarning->setText("You are on testnet, your post won't actually appear on z-board.net");
@ -465,10 +483,20 @@ void MainWindow::postToZBoard() {
zb.testnetWarning->setText("");
}
QRegExpValidator v(QRegExp("^[a-zA-Z0-9_]{3,20}$"), zb.postAs);
zb.postAs->setValidator(&v);
zb.feeAmount->setText(Settings::getInstance()->getZECUSDDisplayFormat(Utils::getZboardAmount() + Utils::getMinerFee()));
QObject::connect(zb.memoTxt, &QPlainTextEdit::textChanged, [=] () {
QString txt = zb.memoTxt->toPlainText();
auto fnBuildNameMemo = [=]() -> QString {
auto memo = zb.memoTxt->toPlainText().trimmed();
if (!zb.postAs->text().trimmed().isEmpty())
memo = zb.postAs->text().trimmed() + ":: " + memo;
return memo;
};
auto fnUpdateMemoSize = [=]() {
QString txt = fnBuildNameMemo();
zb.memoSize->setText(QString::number(txt.toUtf8().size()) + "/512");
if (txt.toUtf8().size() <= 512) {
@ -477,14 +505,26 @@ void MainWindow::postToZBoard() {
zb.memoSize->setStyleSheet("");
}
else {
// Overweight
// Overweight
zb.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
zb.memoSize->setStyleSheet("color: red;");
}
});
// Disallow blank memos
if (zb.memoTxt->toPlainText().trimmed().isEmpty()) {
zb.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
}
else {
zb.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
};
// Memo text changed
QObject::connect(zb.memoTxt, &QPlainTextEdit::textChanged, fnUpdateMemoSize);
QObject::connect(zb.postAs, &QLineEdit::textChanged, fnUpdateMemoSize);
zb.memoTxt->setFocus();
fnUpdateMemoSize();
if (d.exec() == QDialog::Accepted) {
// Create a transaction.
@ -501,7 +541,8 @@ void MainWindow::postToZBoard() {
if (!zb.postAs->text().trimmed().isEmpty())
memo = zb.postAs->text().trimmed() + ":: " + memo;
tx.toAddrs.push_back(ToFields{ Utils::getZboardAddr(), Utils::getZboardAmount(), memo, memo.toUtf8().toHex() });
auto toAddr = topics[zb.topicsList->currentText()];
tx.toAddrs.push_back(ToFields{ toAddr, Utils::getZboardAmount(), memo, memo.toUtf8().toHex() });
tx.fee = Utils::getMinerFee();
json params = json::array();
@ -520,7 +561,6 @@ void MainWindow::postToZBoard() {
}
void MainWindow::doImport(QList<QString>* keys) {
qDebug() << keys->size();
if (keys->isEmpty()) {
delete keys;
ui->statusBar->showMessage("Private key import rescan finished");
@ -545,6 +585,7 @@ void MainWindow::importPrivKey() {
QDialog d(this);
Ui_PrivKey pui;
pui.setupUi(&d);
Settings::saveRestore(&d);
pui.buttonBox->button(QDialogButtonBox::Save)->setVisible(false);
pui.helpLbl->setText(QString() %
@ -577,11 +618,14 @@ void MainWindow::exportAllKeys() {
QDialog d(this);
Ui_PrivKey pui;
pui.setupUi(&d);
// Make the window big by default
auto ps = this->geometry();
QMargins margin = QMargins() + 50;
d.setGeometry(ps.marginsRemoved(margin));
Settings::saveRestore(&d);
pui.privKeyTxt->setPlainText("Loading...");
pui.privKeyTxt->setReadOnly(true);
pui.privKeyTxt->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
@ -706,9 +750,19 @@ void MainWindow::setupZcashdTab() {
}
void MainWindow::setupTransactionsTab() {
// Double click opens up memo if one exists
QObject::connect(ui->transactionsTable, &QTableView::doubleClicked, [=] (auto index) {
auto txModel = dynamic_cast<TxTableModel *>(ui->transactionsTable->model());
QString memo = txModel->getMemo(index.row());
if (!memo.isEmpty()) {
QMessageBox::information(this, "Memo", memo, QMessageBox::Ok);
}
});
// Set up context menu on transactions tab
ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu);
// Table right click
QObject::connect(ui->transactionsTable, &QTableView::customContextMenuRequested, [=] (QPoint pos) {
QModelIndex index = ui->transactionsTable->indexAt(pos);
if (index.row() < 0) return;
@ -877,6 +931,7 @@ MainWindow::~MainWindow()
{
delete ui;
delete rpc;
delete labelCompleter;
delete loadingMovie;
}

7
src/mainwindow.h

@ -36,6 +36,8 @@ public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void updateLabelsAutoComplete();
Ui::MainWindow* ui;
QLabel* statusLabel;
@ -90,9 +92,10 @@ private:
void restoreSavedStates();
RPC* rpc = nullptr;
RPC* rpc = nullptr;
QCompleter* labelCompleter = nullptr;
QMovie* loadingMovie;
QMovie* loadingMovie;
};
#endif // MAINWINDOW_H

1
src/precompiled.h

@ -22,6 +22,7 @@
#include <QPair>
#include <QDir>
#include <QMenu>
#include <QCompleter>
#include <QDateTime>
#include <QTimer>
#include <QSettings>

57
src/rpc.cpp

@ -470,7 +470,7 @@ void RPC::getInfoThenRefresh(bool force) {
};
// Connected, so display checkmark.
QIcon i(":/icons/res/connected.png");
QIcon i(":/icons/res/connected.gif");
main->statusIcon->setPixmap(i.pixmap(16, 16));
static int lastBlock = 0;
@ -899,3 +899,58 @@ void RPC::shutdownZcashd() {
// Wait for the zcash process to exit.
d.exec();
}
// Fetch the Z-board topics list
void RPC::getZboardTopics(std::function<void(QMap<QString, QString>)> cb) {
if (conn == nullptr)
return noConnection();
QUrl cmcURL("http://z-board.net/listTopics");
QNetworkRequest req;
req.setUrl(cmcURL);
QNetworkReply *reply = conn->restclient->get(req);
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
try {
if (reply->error() != QNetworkReply::NoError) {
auto parsed = json::parse(reply->readAll(), nullptr, false);
if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) {
qDebug() << QString::fromStdString(parsed["error"]["message"]);
}
else {
qDebug() << reply->errorString();
}
return;
}
auto all = reply->readAll();
auto parsed = json::parse(all, nullptr, false);
if (parsed.is_discarded()) {
return;
}
QMap<QString, QString> topics;
for (const json& item : parsed["topics"].get<json::array_t>()) {
if (item.find("addr") == item.end() || item.find("topicName") == item.end())
return;
QString addr = QString::fromStdString(item["addr"].get<json::string_t>());
QString topic = QString::fromStdString(item["topicName"].get<json::string_t>());
topics.insert(topic, addr);
}
cb(topics);
}
catch (...) {
// If anything at all goes wrong, just set the price to 0 and move on.
qDebug() << QString("Caught something nasty");
}
});
}

2
src/rpc.h

@ -38,7 +38,9 @@ public:
void refresh(bool force = false);
void refreshAddresses();
void refreshZECPrice();
void getZboardTopics(std::function<void(QMap<QString, QString>)> cb);
void fillTxJsonParams(json& params, Tx tx);
void sendZTransaction (json params, const std::function<void(json)>& cb);

2
src/scripts/mkrelease.sh

@ -29,6 +29,7 @@ echo "[OK]"
echo -n "Cleaning.........."
rm -rf bin/*
rm -rf artifacts/*
make distclean > /dev/null
echo "[OK]"
@ -58,6 +59,7 @@ echo "[OK]"
echo -n "Packaging........."
mkdir bin/zec-qt-wallet-v$APP_VERSION > /dev/null
strip zec-qt-wallet
cp zec-qt-wallet bin/zec-qt-wallet-v$APP_VERSION > /dev/null
cp ../zcash/artifacts/zcashd bin/zec-qt-wallet-v$APP_VERSION > /dev/null
cp README.md bin/zec-qt-wallet-v$APP_VERSION > /dev/null

28
src/sendtab.cpp

@ -45,6 +45,11 @@ void MainWindow::setupSendTab() {
QObject::connect(ui->Address1, &QLineEdit::textChanged, [=] (auto text) {
this->addressChanged(1, text);
});
// This is the damnest thing ever. If we do AddressBook::readFromStorage() directly, the whole file
// doesn't get read. It needs to run in a timer after everything has finished to be able to read
// the file properly.
QTimer::singleShot(100, [=]() { updateLabelsAutoComplete(); });
// The first address book button
QObject::connect(ui->AddressBook1, &QPushButton::clicked, [=] () {
@ -87,6 +92,25 @@ void MainWindow::setupSendTab() {
});
}
void MainWindow::updateLabelsAutoComplete() {
QList<QString> list;
auto labels = AddressBook::readFromStorage();
std::transform(labels.begin(), labels.end(), std::back_inserter(list), [=] (auto la) -> QString {
return la.first % "/" % la.second;
});
delete labelCompleter;
labelCompleter = new QCompleter(list, this);
labelCompleter->setCaseSensitivity(Qt::CaseInsensitive);
// Then, find all the address fields and update the completer.
QRegExp re("Address[0-9]+", Qt::CaseInsensitive);
for (auto target: ui->sendToWidgets->findChildren<QLineEdit *>(re)) {
target->setCompleter(labelCompleter);
}
}
void MainWindow::setDefaultPayFrom() {
auto findMax = [=] (QString startsWith) {
double max_amt = 0;
@ -148,6 +172,7 @@ void MainWindow::addAddressSection() {
QObject::connect(Address1, &QLineEdit::textChanged, [=] (auto text) {
this->addressChanged(itemNumber, text);
});
Address1->setCompleter(labelCompleter);
horizontalLayout_12->addWidget(Address1);
@ -350,6 +375,9 @@ Tx MainWindow::createTxFromSendPage() {
int totalItems = ui->sendToWidgets->children().size() - 2; // The last one is a spacer, so ignore that
for (int i=0; i < totalItems; i++) {
QString addr = ui->sendToWidgets->findChild<QLineEdit*>(QString("Address") % QString::number(i+1))->text().trimmed();
// Remove label if it exists
addr = addr.split("/").last();
double amt = ui->sendToWidgets->findChild<QLineEdit*>(QString("Amount") % QString::number(i+1))->text().trimmed().toDouble();
QString memo = ui->sendToWidgets->findChild<QLabel*>(QString("MemoTxt") % QString::number(i+1))->text().trimmed();

8
src/settings.cpp

@ -120,3 +120,11 @@ QString Settings::getZECUSDDisplayFormat(double bal) {
else
return getZECDisplayFormat(bal);
}
void Settings::saveRestore(QDialog* d) {
d->restoreGeometry(QSettings().value(d->objectName() % "geometry").toByteArray());
QObject::connect(d, &QDialog::finished, [=](auto) {
QSettings().setValue(d->objectName() % "geometry", d->saveGeometry());
});
}

5
src/settings.h

@ -16,6 +16,8 @@ public:
static Settings* init();
static Settings* getInstance();
static void saveRestore(QDialog* d);
Config getSettings();
void saveSettings(const QString& host, const QString& port, const QString& username, const QString& password);
@ -48,8 +50,7 @@ public:
void setZECPrice(double p) { zecPrice = p; }
double getZECPrice();
QString getUSDFormat (double bal);
QString getZECDisplayFormat (double bal);
QString getZECUSDDisplayFormat(double bal);

71
src/txid.ui

@ -1,71 +0,0 @@
<ui version="4.0" >
<author></author>
<comment></comment>
<exportmacro></exportmacro>
<class>Dialog</class>
<widget class="QDialog" name="Dialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="geometry" >
<rect>
<x>30</x>
<y>240</y>
<width>341</width>
<height>32</height>
</rect>
</property>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<pixmapfunction></pixmapfunction>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</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>Dialog</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>

35
src/utils.cpp

@ -30,37 +30,8 @@ const QString Utils::getDevSproutAddr() {
}
// Get the dev fee address based on the transaction
const QString Utils::getDevAddr(Tx tx) {
auto testnetAddrLookup = [=] (const QString& addr) -> QString {
if (addr.startsWith("ztestsapling")) {
return "ztestsapling1kdp74adyfsmm9838jaupgfyx3npgw8ut63stjjx757pc248cuc0ymzphqeux60c64qe5qt68ygh";
} else if (addr.startsWith("zt")) {
return getDevSproutAddr();
} else {
return QString();
}
};
if (Settings::getInstance()->isTestnet()) {
auto devAddr = testnetAddrLookup(tx.fromAddr);
if (!devAddr.isEmpty()) {
return devAddr;
}
// t-Addr, find if it is going to a Sprout or Sapling address
for (const ToFields& to : tx.toAddrs) {
devAddr = testnetAddrLookup(to.addr);
if (!devAddr.isEmpty()) {
return devAddr;
}
}
// If this is a t-Addr -> t-Addr transaction, use the Sapling address by default
return testnetAddrLookup("ztestsapling");
} else {
// Mainnet doesn't have a fee yet!
return QString();
}
const QString Utils::getDevAddr(Tx) {
return QString();
}
@ -82,7 +53,7 @@ QString Utils::getZboardAddr() {
}
double Utils::getDevFee() {
if (Settings::getInstance()->isTestnet()) {
return 0.0001;
return 0;
} else {
return 0;
}

12
src/zboard.ui

@ -82,7 +82,7 @@
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ZBoard: Fully anonymous and untraceable chat messages based on the ZCash blockchain. &lt;a href=&quot;http://www.z-board.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.z-board.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Posting to ZBoard: #Main_Area&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ZBoard: Fully anonymous and untraceable chat messages based on the ZCash blockchain. &lt;a href=&quot;http://www.z-board.net/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://www.z-board.net/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -115,6 +115,16 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="topicsList"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Posting to Board</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>

2
zec-qt-wallet.pro

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

Loading…
Cancel
Save