diff --git a/application.qrc b/application.qrc index c7201af..52afaf1 100644 --- a/application.qrc +++ b/application.qrc @@ -17,5 +17,6 @@ res/zec_qt_wallet_fr.qm res/zec_qt_wallet_pt.qm res/zec_qt_wallet_it.qm + res/zec_qt_wallet_zh.qm diff --git a/res/zec_qt_wallet_zh.qm b/res/zec_qt_wallet_zh.qm new file mode 100644 index 0000000..de6ed57 Binary files /dev/null and b/res/zec_qt_wallet_zh.qm differ diff --git a/silentdragon.pro b/silentdragon.pro index 025ba3a..090294d 100644 --- a/silentdragon.pro +++ b/silentdragon.pro @@ -53,11 +53,13 @@ SOURCES += \ src/addressbook.cpp \ src/logger.cpp \ src/addresscombo.cpp \ + src/validateaddress.cpp \ src/websockets.cpp \ src/mobileappconnector.cpp \ src/recurring.cpp \ src/requestdialog.cpp \ - src/memoedit.cpp + src/memoedit.cpp \ + src/viewalladdresses.cpp HEADERS += \ src/mainwindow.h \ @@ -77,12 +79,14 @@ HEADERS += \ src/fillediconlabel.h \ src/addressbook.h \ src/logger.h \ - src/addresscombo.h \ + src/addresscombo.h \ + src/validateaddress.h \ src/websockets.h \ src/mobileappconnector.h \ src/recurring.h \ src/requestdialog.h \ - src/memoedit.h + src/memoedit.h \ + src/viewalladdresses.h FORMS += \ src/mainwindow.ui \ @@ -92,10 +96,14 @@ FORMS += \ src/turnstile.ui \ src/turnstileprogress.ui \ src/privkey.ui \ - src/memodialog.ui \ + src/memodialog.ui \ + src/viewalladdresses.ui \ + src/validateaddress.ui \ + src/viewalladdresses.ui \ src/connection.ui \ src/zboard.ui \ src/addressbook.ui \ + src/viewalladdresses.ui \ src/mobileappconnector.ui \ src/createzcashconfdialog.ui \ src/recurringdialog.ui \ @@ -107,7 +115,8 @@ TRANSLATIONS = res/zec_qt_wallet_es.ts \ res/zec_qt_wallet_fr.ts \ res/zec_qt_wallet_de.ts \ res/zec_qt_wallet_pt.ts \ - res/zec_qt_wallet_it.ts + res/zec_qt_wallet_it.ts \ + res/zec_qt_wallet_zh.ts include(singleapplication/singleapplication.pri) DEFINES += QAPPLICATION_CLASS=QApplication diff --git a/src/addressbook.cpp b/src/addressbook.cpp index 6cf0489..4ef2d2b 100644 --- a/src/addressbook.cpp +++ b/src/addressbook.cpp @@ -122,14 +122,32 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) { // Add new address button QObject::connect(ab.addNew, &QPushButton::clicked, [&] () { auto addr = ab.addr->text().trimmed(); - if (!addr.isEmpty() && !ab.label->text().isEmpty()) { - // Test if address is valid. - if (!Settings::isValidAddress(addr)) { - QMessageBox::critical(parent, QObject::tr("Address Format Error"), addr + QObject::tr(" doesn't seem to be a valid Hush address."), QMessageBox::Ok); - } else { - model.addNewLabel(ab.label->text(), ab.addr->text()); - } + QString newLabel = ab.label->text(); + + if (addr.isEmpty() || newLabel.isEmpty()) { + QMessageBox::critical(parent, QObject::tr("Address or Label Error"), + QObject::tr("Address or Label cannot be empty"), QMessageBox::Ok); + return; } + // Test if address is valid. + if (!Settings::isValidAddress(addr)) { + QMessageBox::critical(parent, QObject::tr("Address Format Error"), + QObject::tr("%1 doesn't seem to be a valid Zcash address.") + .arg(addr), + QMessageBox::Ok); + return; + } + + // Don't allow duplicate address labels. + if (!getInstance()->getAddressForLabel(newLabel).isEmpty()) { + QMessageBox::critical(parent, QObject::tr("Label Error"), + QObject::tr("The label '%1' already exists. Please remove the existing label.") + .arg(newLabel), + QMessageBox::Ok); + return; + } + + model.addNewLabel(newLabel, ab.addr->text()); }); // Import Button @@ -217,7 +235,7 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) { if (d.exec() == QDialog::Accepted && target != nullptr) { auto selection = ab.addresses->selectionModel(); - if (selection->hasSelection()) { + if (selection && selection->hasSelection() && selection->selectedRows().size() > 0) { auto item = model.itemAt(selection->selectedRows().at(0).row()); fnSetTargetLabelAddr(target, item.first, item.second); } @@ -244,17 +262,24 @@ AddressBook::AddressBook() { void AddressBook::readFromStorage() { QFile file(AddressBook::writeableFile()); - if (!file.exists()) { - return; - } + if (file.exists()) { + allLabels.clear(); + file.open(QIODevice::ReadOnly); + QDataStream in(&file); // read the data serialized from the file + QString version; + in >> version >> allLabels; - allLabels.clear(); - file.open(QIODevice::ReadOnly); - QDataStream in(&file); // read the data serialized from the file - QString version; - in >> version >> allLabels; + file.close(); + } - file.close(); + // Special. + // Add the default ZecWallet donation address if it isn't already present + // QList allAddresses; + // std::transform(allLabels.begin(), allLabels.end(), + // std::back_inserter(allAddresses), [=] (auto i) { return i.second; }); + // if (!allAddresses.contains(Settings::getDonationAddr(true))) { + // allLabels.append(QPair("ZecWallet donation", Settings::getDonationAddr(true))); + // } } void AddressBook::writeToStorage() { @@ -337,6 +362,16 @@ QString AddressBook::getLabelForAddress(QString addr) { return ""; } +// Get the address for a label +QString AddressBook::getAddressForLabel(QString label) { + for (auto i: allLabels) { + if (i.first == label) + return i.second; + } + + return ""; +} + QString AddressBook::addLabelToAddress(QString addr) { QString label = AddressBook::getInstance()->getLabelForAddress(addr); if (!label.isEmpty()) diff --git a/src/addressbook.h b/src/addressbook.h index 41f9ff9..af64c07 100644 --- a/src/addressbook.h +++ b/src/addressbook.h @@ -10,9 +10,9 @@ class AddressBookModel : public QAbstractTableModel { public: AddressBookModel(QTableView* parent); ~AddressBookModel(); - - void addNewLabel(QString label, QString addr); - void removeItemAt(int row); + + void addNewLabel(QString label, QString addr); + void removeItemAt(int row); QPair itemAt(int row); int rowCount(const QModelIndex &parent) const; @@ -52,6 +52,8 @@ public: // Get an address's first label QString getLabelForAddress(QString address); + // Get a Label's address + QString getAddressForLabel(QString label); private: AddressBook(); diff --git a/src/addressbook.ui b/src/addressbook.ui index 946fb13..a20ee8f 100644 --- a/src/addressbook.ui +++ b/src/addressbook.ui @@ -23,7 +23,7 @@ - Address + Address (z-Addr or t-Addr) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c285882..279068b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,5 +1,7 @@ #include "mainwindow.h" #include "addressbook.h" +#include "viewalladdresses.h" +#include "validateaddress.h" #include "ui_mainwindow.h" #include "ui_mobileappconnector.h" #include "ui_addressbook.h" @@ -9,6 +11,8 @@ #include "ui_settings.h" #include "ui_turnstile.h" #include "ui_turnstileprogress.h" +#include "ui_viewalladdresses.h" +#include "ui_validateaddress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" @@ -75,6 +79,9 @@ MainWindow::MainWindow(QWidget *parent) : // z-Board.net QObject::connect(ui->actionz_board_net, &QAction::triggered, this, &MainWindow::postToZBoard); + // Validate Address + QObject::connect(ui->actionValidate_Address, &QAction::triggered, this, &MainWindow::validateAddress); + // Connect mobile app QObject::connect(ui->actionConnect_Mobile_App, &QAction::triggered, this, [=] () { if (rpc->getConnection() == nullptr) @@ -109,7 +116,7 @@ MainWindow::MainWindow(QWidget *parent) : setupSendTab(); setupTransactionsTab(); - setupRecieveTab(); + setupReceiveTab(); setupBalancesTab(); setupTurnstileDialog(); setupZcashdTab(); @@ -628,6 +635,48 @@ void MainWindow::donate() { ui->tabWidget->setCurrentIndex(1); } +/** + * Validate an address + */ +void MainWindow::validateAddress() { + // Make sure everything is up and running + if (!getRPC() || !getRPC()->getConnection()) + return; + + // First thing is ask the user for an address + bool ok; + auto address = QInputDialog::getText(this, tr("Enter Address to validate"), + tr("Transparent or Shielded Address:") + QString(" ").repeated(140), // Pad the label so the dialog box is wide enough + QLineEdit::Normal, "", &ok); + if (!ok) + return; + + getRPC()->validateAddress(address, [=] (json props) { + QDialog d(this); + Ui_ValidateAddress va; + va.setupUi(&d); + Settings::saveRestore(&d); + Settings::saveRestoreTableHeader(va.tblProps, &d, "validateaddressprops"); + va.tblProps->horizontalHeader()->setStretchLastSection(true); + + va.lblAddress->setText(address); + + QList> propsList; + for (auto it = props.begin(); it != props.end(); it++) { + + propsList.append( + QPair( + QString::fromStdString(it.key()), QString::fromStdString(it.value().dump())) + ); + } + + ValidateAddressesModel model(va.tblProps, propsList); + va.tblProps->setModel(&model); + + d.exec(); + }); + +} void MainWindow::postToZBoard() { QDialog d(this); @@ -827,7 +876,7 @@ void MainWindow::payZcashURI(QString uri, QString myAddr) { return; // Extract the address - qDebug() << "Recieved URI " << uri; + qDebug() << "Received URI " << uri; PaymentURI paymentInfo = Settings::parseURI(uri); if (!paymentInfo.error.isEmpty()) { QMessageBox::critical(this, tr("Error paying pirate URI"), @@ -1238,7 +1287,6 @@ void MainWindow::setupTransactionsTab() { } void MainWindow::addNewZaddr(bool sapling) { - rpc->newZaddr(sapling, [=] (json reply) { QString addr = QString::fromStdString(reply.get()); // Make sure the RPC class reloads the z-addrs for future use @@ -1246,8 +1294,8 @@ void MainWindow::addNewZaddr(bool sapling) { // Just double make sure the z-address is still checked if ( sapling && ui->rdioZSAddr->isChecked() ) { - ui->listRecieveAddresses->insertItem(0, addr); - ui->listRecieveAddresses->setCurrentIndex(0); + ui->listReceiveAddresses->insertItem(0, addr); + ui->listReceiveAddresses->setCurrentIndex(0); ui->statusBar->showMessage(QString::fromStdString("Created new zAddr") % (sapling ? "(Sapling)" : "(Sprout)"), @@ -1263,14 +1311,14 @@ std::function MainWindow::addZAddrsToComboList(bool sapling) { return [=] (bool checked) { if (checked && this->rpc->getAllZAddresses() != nullptr) { auto addrs = this->rpc->getAllZAddresses(); - ui->listRecieveAddresses->clear(); + ui->listReceiveAddresses->clear(); std::for_each(addrs->begin(), addrs->end(), [=] (auto addr) { if ( (sapling && Settings::getInstance()->isSaplingAddress(addr)) || (!sapling && !Settings::getInstance()->isSaplingAddress(addr))) { if (rpc->getAllBalances()) { auto bal = rpc->getAllBalances()->value(addr); - ui->listRecieveAddresses->addItem(addr, bal); + ui->listReceiveAddresses->addItem(addr, bal); } } }); @@ -1283,15 +1331,17 @@ std::function MainWindow::addZAddrsToComboList(bool sapling) { }; } -void MainWindow::setupRecieveTab() { +void MainWindow::setupReceiveTab() { auto addNewTAddr = [=] () { rpc->newTaddr([=] (json reply) { QString addr = QString::fromStdString(reply.get()); + // Make sure the RPC class reloads the t-addrs for future use + rpc->refreshAddresses(); // Just double make sure the t-address is still checked if (ui->rdioTAddr->isChecked()) { - ui->listRecieveAddresses->insertItem(0, addr); - ui->listRecieveAddresses->setCurrentIndex(0); + ui->listReceiveAddresses->insertItem(0, addr); + ui->listReceiveAddresses->setCurrentIndex(0); ui->statusBar->showMessage(tr("Created new t-Addr"), 10 * 1000); } @@ -1304,14 +1354,58 @@ void MainWindow::setupRecieveTab() { // want to reuse t-addrs if (checked && this->rpc->getUTXOs() != nullptr) { updateTAddrCombo(checked); - addNewTAddr(); } + + // Toggle the "View all addresses" button as well + ui->btnViewAllAddresses->setVisible(checked); + }); + + // View all addresses goes to "View all private keys" + QObject::connect(ui->btnViewAllAddresses, &QPushButton::clicked, [=] () { + // If there's no RPC, return + if (!getRPC()) + return; + + QDialog d(this); + Ui_ViewAddressesDialog viewaddrs; + viewaddrs.setupUi(&d); + Settings::saveRestore(&d); + Settings::saveRestoreTableHeader(viewaddrs.tblAddresses, &d, "viewalladdressestable"); + viewaddrs.tblAddresses->horizontalHeader()->setStretchLastSection(true); + + ViewAllAddressesModel model(viewaddrs.tblAddresses, *getRPC()->getAllTAddresses(), getRPC()); + viewaddrs.tblAddresses->setModel(&model); + + QObject::connect(viewaddrs.btnExportAll, &QPushButton::clicked, this, &MainWindow::exportAllKeys); + + viewaddrs.tblAddresses->setContextMenuPolicy(Qt::CustomContextMenu); + QObject::connect(viewaddrs.tblAddresses, &QTableView::customContextMenuRequested, [=] (QPoint pos) { + QModelIndex index = viewaddrs.tblAddresses->indexAt(pos); + if (index.row() < 0) return; + + index = index.sibling(index.row(), 0); + QString addr = viewaddrs.tblAddresses->model()->data(index).toString(); + + QMenu menu(this); + menu.addAction(tr("Export Private Key"), [=] () { + if (addr.isEmpty()) + return; + + this->exportKeys(addr); + }); + menu.addAction(tr("Copy Address"), [=]() { + QGuiApplication::clipboard()->setText(addr); + }); + menu.exec(viewaddrs.tblAddresses->viewport()->mapToGlobal(pos)); + }); + + d.exec(); }); QObject::connect(ui->rdioZSAddr, &QRadioButton::toggled, addZAddrsToComboList(true)); // Explicitly get new address button. - QObject::connect(ui->btnRecieveNewAddr, &QPushButton::clicked, [=] () { + QObject::connect(ui->btnReceiveNewAddr, &QPushButton::clicked, [=] () { if (!rpc->getConnection()) return; @@ -1327,9 +1421,10 @@ void MainWindow::setupRecieveTab() { if (tab == 2) { // Switched to receive tab, select the z-addr radio button ui->rdioZSAddr->setChecked(true); + ui->btnViewAllAddresses->setVisible(false); // And then select the first one - ui->listRecieveAddresses->setCurrentIndex(0); + ui->listReceiveAddresses->setCurrentIndex(0); } }); @@ -1338,15 +1433,15 @@ void MainWindow::setupRecieveTab() { ui->rcvLabel->setValidator(v); // Select item in address list - QObject::connect(ui->listRecieveAddresses, + QObject::connect(ui->listReceiveAddresses, QOverload::of(&QComboBox::currentIndexChanged), [=] (int index) { - QString addr = ui->listRecieveAddresses->itemText(index); + QString addr = ui->listReceiveAddresses->itemText(index); if (addr.isEmpty()) { // Draw empty stuff ui->rcvLabel->clear(); ui->rcvBal->clear(); - ui->txtRecieve->clear(); + ui->txtReceive->clear(); ui->qrcodeDisplay->clear(); return; } @@ -1361,7 +1456,7 @@ void MainWindow::setupRecieveTab() { ui->rcvLabel->setText(label); ui->rcvBal->setText(Settings::getZECUSDDisplayFormat(rpc->getAllBalances()->value(addr))); - ui->txtRecieve->setPlainText(addr); + ui->txtReceive->setPlainText(addr); ui->qrcodeDisplay->setQrcodeString(addr); if (rpc->getUsedAddresses()->value(addr, false)) { ui->rcvBal->setToolTip(tr("Address has been previously used")); @@ -1373,7 +1468,7 @@ void MainWindow::setupRecieveTab() { // Receive tab add/update label QObject::connect(ui->rcvUpdateLabel, &QPushButton::clicked, [=]() { - QString addr = ui->listRecieveAddresses->currentText(); + QString addr = ui->listReceiveAddresses->currentText(); if (addr.isEmpty()) return; @@ -1407,9 +1502,9 @@ void MainWindow::setupRecieveTab() { } }); - // Recieve Export Key + // Receive Export Key QObject::connect(ui->exportKey, &QPushButton::clicked, [=]() { - QString addr = ui->listRecieveAddresses->currentText(); + QString addr = ui->listReceiveAddresses->currentText(); if (addr.isEmpty()) return; @@ -1417,16 +1512,17 @@ void MainWindow::setupRecieveTab() { }); } + void MainWindow::updateTAddrCombo(bool checked) { if (checked) { auto utxos = this->rpc->getUTXOs(); - ui->listRecieveAddresses->clear(); + ui->listReceiveAddresses->clear(); std::for_each(utxos->begin(), utxos->end(), [=](auto& utxo) { auto addr = utxo.address; - if (addr.startsWith("R") && ui->listRecieveAddresses->findText(addr) < 0) { + if (addr.startsWith("R") && ui->listReceiveAddresses->findText(addr) < 0) { auto bal = rpc->getAllBalances()->value(addr); - ui->listRecieveAddresses->addItem(addr, bal); + ui->listReceiveAddresses->addItem(addr, bal); } }); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 9a1971d..7a14fa3 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -56,6 +56,8 @@ public: void balancesReady(); void payZcashURI(QString uri = "", QString myAddr = ""); + void validateAddress(); + void updateLabels(); void updateTAddrCombo(bool checked); void updateFromCombo(); @@ -76,7 +78,7 @@ private: void setupSendTab(); void setupTransactionsTab(); - void setupRecieveTab(); + void setupReceiveTab(); void setupBalancesTab(); void setupZcashdTab(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index b11eb6d..34eb4db 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -756,7 +756,7 @@ - + 0 @@ -769,12 +769,19 @@ - + New Address + + + + View All Addresses + + + @@ -825,7 +832,7 @@ - + 0 @@ -1335,6 +1342,7 @@ &Apps + @@ -1451,6 +1459,11 @@ Request HUSH... + + + Validate Address + + @@ -1483,9 +1496,9 @@ cancelSendButton rdioZSAddr rdioTAddr - listRecieveAddresses - btnRecieveNewAddr - txtRecieve + listReceiveAddresses + btnReceiveNewAddr + txtReceive rcvLabel rcvUpdateLabel transactionsTable diff --git a/src/precompiled.h b/src/precompiled.h index 5745182..79c4c8b 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/privkey.ui b/src/privkey.ui index 9fe3760..57bdb16 100644 --- a/src/privkey.ui +++ b/src/privkey.ui @@ -11,7 +11,7 @@ - Private Key + Private Keys diff --git a/src/rpc.cpp b/src/rpc.cpp index cdd727d..64e09e8 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -230,6 +230,18 @@ void RPC::importTPrivKey(QString privkey, bool rescan, const std::functiondoRPCWithDefaultErrorHandling(payload, cb); } +void RPC::validateAddress(QString address, const std::function& cb) { + QString method = address.startsWith("z") ? "z_validateaddress" : "validateaddress"; + + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", method.toStdString() }, + {"params", { address.toStdString() } }, + }; + + conn->doRPCWithDefaultErrorHandling(payload, cb); +} void RPC::getBalance(const std::function& cb) { json payload = { diff --git a/src/rpc.h b/src/rpc.h index 3b95a71..48193ee 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -75,6 +75,7 @@ public: void getTPrivKey(QString addr, const std::function& cb); void importZPrivKey(QString addr, bool rescan, const std::function& cb); void importTPrivKey(QString addr, bool rescan, const std::function& cb); + void validateAddress(QString address, const std::function& cb); void shutdownZcashd(); void noConnection(); diff --git a/src/settings.cpp b/src/settings.cpp index 27499a7..b8e4891 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -40,6 +40,15 @@ void Settings::saveSettings(const QString& host, const QString& port, const QStr init(); } +void Settings::saveRestoreTableHeader(QTableView* table, QDialog* d, QString tablename) { + table->horizontalHeader()->restoreState(QSettings().value(tablename).toByteArray()); + table->horizontalHeader()->setStretchLastSection(true); + + QObject::connect(d, &QDialog::finished, [=](auto) { + QSettings().setValue(tablename, table->horizontalHeader()->saveState()); + }); +} + void Settings::setUsingZcashConf(QString confLocation) { if (!confLocation.isEmpty()) _confLocation = confLocation; diff --git a/src/settings.h b/src/settings.h index e72434e..fb289cc 100644 --- a/src/settings.h +++ b/src/settings.h @@ -76,6 +76,7 @@ public: static const QString txidStatusMessage; static void saveRestore(QDialog* d); + static void saveRestoreTableHeader(QTableView* table, QDialog* d, QString tablename) ; static PaymentURI parseURI(QString paymentURI); static QString paymentURIPretty(PaymentURI); diff --git a/src/validateaddress.cpp b/src/validateaddress.cpp new file mode 100644 index 0000000..d82e82e --- /dev/null +++ b/src/validateaddress.cpp @@ -0,0 +1,37 @@ +#include "validateaddress.h" + + +ValidateAddressesModel::ValidateAddressesModel(QTableView *parent, QList> props) + : QAbstractTableModel(parent) { + headers << tr("Property") << tr("Value"); + this->props = props; +} + + +int ValidateAddressesModel::rowCount(const QModelIndex&) const { + return props.size(); +} + +int ValidateAddressesModel::columnCount(const QModelIndex&) const { + return headers.size(); +} + +QVariant ValidateAddressesModel::data(const QModelIndex &index, int role) const { + QPair p = props.at(index.row()); + if (role == Qt::DisplayRole) { + switch(index.column()) { + case 0: return p.first; + case 1: return p.second; + } + } + return QVariant(); +} + + +QVariant ValidateAddressesModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + return headers.at(section); + } + + return QVariant(); +} diff --git a/src/validateaddress.h b/src/validateaddress.h new file mode 100644 index 0000000..19db4cb --- /dev/null +++ b/src/validateaddress.h @@ -0,0 +1,23 @@ +#ifndef VALIDATEADDRESS_H +#define VALIDATEADDRESS_H + +#include "precompiled.h" + +class ValidateAddressesModel : public QAbstractTableModel { + +public: + ValidateAddressesModel(QTableView* parent, QList> props); + ~ValidateAddressesModel() = default; + + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +private: + QList> props; + QStringList headers; +}; + + +#endif // VALIDATEADDRESS_H diff --git a/src/validateaddress.ui b/src/validateaddress.ui new file mode 100644 index 0000000..20caebb --- /dev/null +++ b/src/validateaddress.ui @@ -0,0 +1,85 @@ + + + ValidateAddress + + + + 0 + 0 + 400 + 300 + + + + Validate Address + + + + + + TextLabel + + + + + + + Address: + + + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + ValidateAddress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ValidateAddress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/viewalladdresses.cpp b/src/viewalladdresses.cpp new file mode 100644 index 0000000..7b7af7d --- /dev/null +++ b/src/viewalladdresses.cpp @@ -0,0 +1,38 @@ +#include "viewalladdresses.h" +#include "settings.h" + +ViewAllAddressesModel::ViewAllAddressesModel(QTableView *parent, QList taddrs, RPC* rpc) + : QAbstractTableModel(parent) { + headers << tr("Address") << tr("Balance (%1)").arg(Settings::getTokenName()); + addresses = taddrs; + this->rpc = rpc; +} + + +int ViewAllAddressesModel::rowCount(const QModelIndex&) const { + return addresses.size(); +} + +int ViewAllAddressesModel::columnCount(const QModelIndex&) const { + return headers.size(); +} + +QVariant ViewAllAddressesModel::data(const QModelIndex &index, int role) const { + QString address = addresses.at(index.row()); + if (role == Qt::DisplayRole) { + switch(index.column()) { + case 0: return address; + case 1: return rpc->getAllBalances()->value(address, 0.0); + } + } + return QVariant(); +} + + +QVariant ViewAllAddressesModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { + return headers.at(section); + } + + return QVariant(); +} diff --git a/src/viewalladdresses.h b/src/viewalladdresses.h new file mode 100644 index 0000000..4e9e3d4 --- /dev/null +++ b/src/viewalladdresses.h @@ -0,0 +1,24 @@ +#ifndef VIEWALLADDRESSES_H +#define VIEWALLADDRESSES_H + +#include "precompiled.h" +#include "rpc.h" + +class ViewAllAddressesModel : public QAbstractTableModel { + +public: + ViewAllAddressesModel(QTableView* parent, QList taddrs, RPC* rpc); + ~ViewAllAddressesModel() = default; + + int rowCount(const QModelIndex &parent) const; + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +private: + QList addresses; + QStringList headers; + RPC* rpc; +}; + +#endif \ No newline at end of file diff --git a/src/viewalladdresses.ui b/src/viewalladdresses.ui new file mode 100644 index 0000000..fae5ecf --- /dev/null +++ b/src/viewalladdresses.ui @@ -0,0 +1,81 @@ + + + ViewAddressesDialog + + + + 0 + 0 + 400 + 300 + + + + All Addresses + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + Export All Keys + + + + + + + QAbstractItemView::SingleSelection + + + true + + + + + + + + + buttonBox + accepted() + ViewAddressesDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ViewAddressesDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +