Compare commits

...

40 Commits
master ... chat

Author SHA1 Message Date
Duke Leto aed5e373f6 fix json compile issues 4 years ago
Duke Leto f45d208ea2 Merge branch 'duke' into chat 4 years ago
Duke Leto efc00392f4 Fix wrong type of comments in our project file 4 years ago
Duke Leto ea495c9f69 Add a bunch of debug statements 4 years ago
Duke Leto c54b3114d7 No need to validate our own zaddrs, logging + copyright headers 4 years ago
Duke Leto 009a7b93c2 Merge stuff 4 years ago
Duke Leto efa3a04c88 Merge branch 'duke' into chat 4 years ago
Duke Leto c9d919c62e Merge branch 'duke' into chat 4 years ago
Duke Leto 6c8e262eb4 Bless Satoshi 4 years ago
Duke Leto 5496ae4e41 Create new zaddrs at run-time for new HushContacts 4 years ago
Duke Leto 676f75e2c8 Remove incorrect comment 4 years ago
Duke Leto 9b0510da50 Add some debug 4 years ago
Duke Leto 603e0298d0 Header memos should get their zaddr from the contact object; dynamic zaddr generation not working just yet 4 years ago
Duke Leto cd729c56c8 Find or create our custom HushChat zaddr for each contact when sending a memo 4 years ago
Duke Leto ad78533fc8 Forgive me for writing this code, but it does seem to upgrade v1=>v2 correctly 4 years ago
Duke Leto 8636754703 Large addressbook refactor to use QList, to support contacts having more than 2 data fields 4 years ago
Duke Leto 3960c7e906 copyright 4 years ago
Duke Leto 1b3147118f Use a fixed reply zaddr to enable more testing 4 years ago
Duke Leto 076c2221e4 Correctly set the zaddr for Bob the recipient, we must still set Alice's from zaddr correctly 4 years ago
Duke Leto 9a1ab5babf Convert conversation id to a UUID 4 years ago
Duke Leto 707d858601 Find the current HushContact when sendMemo is clicked 4 years ago
Duke Leto 30dfaf5ce8 Figure out a different way to find out the currently selected HushContact in sendMemo 4 years ago
Duke Leto 9d583e69b7 Prevent editing of contact list and chat list 4 years ago
Duke Leto 6e1fd225f4 Make build fail correctly when there is an error 4 years ago
Duke Leto fec7346a58 Add file upload button 4 years ago
Duke Leto 600462d4a3 Set input text color to red, labels on both columns and stretching options 4 years ago
Duke Leto 51cc069812 Grab the input text for sending a memo 4 years ago
Duke Leto b47180ac0b Try to setup slot+signals but they are not working yet 4 years ago
Duke Leto 50f44ac221 Push checking for updates to be last, give the user data first 4 years ago
Duke Leto 3c42c28db8 Fix a small bug where a rare exception could set default currency to USD (old default) instead of BTC (new default) 4 years ago
Duke Leto 58a8aacd80 copyright 4 years ago
Duke Leto 0466e9ab55 Method to create header memos and updates to sendMemo() 4 years ago
Duke Leto 84cf85bf49 Log the object which gets a mouse event 4 years ago
Duke Leto 130e5aaf66 Detect left vs right button clicks 4 years ago
Duke Leto dd6086496e Add code to detect mouse clicks and fill out sendMemo and HushContact 4 years ago
Duke Leto d76aa8b3dc Fill out HushChat class a bit more 4 years ago
Duke Leto 1c64548bb0 do qr code stuff before slower z operations 4 years ago
Duke Leto 0b22f10b13 Start a c++ class for hush chat objects 4 years ago
Duke Leto 41b17cdd5a Start creating the hushchat memo our new way 4 years ago
Duke Leto 3df6f0d1c2 Hook up the Send button to send an xtn 4 years ago
  1. 1
      build.sh
  2. 4
      silentdragon.pro
  3. 88
      src/addressbook.cpp
  4. 17
      src/addressbook.h
  5. 20
      src/connection.h
  6. 238
      src/mainwindow.cpp
  7. 43
      src/mainwindow.h
  8. 64
      src/mainwindow.ui
  9. 29
      src/rpc.cpp
  10. 2
      src/rpc.h
  11. 3
      src/sendtab.cpp
  12. 4
      src/senttxstore.cpp
  13. 2
      src/txtablemodel.cpp

1
build.sh

@ -3,6 +3,7 @@
# Released under the GPLv3 # Released under the GPLv3
set -e set -e
set -x
UNAME=$(uname) UNAME=$(uname)
if [ "$UNAME" == "Linux" ] ; then if [ "$UNAME" == "Linux" ] ; then

4
silentdragon.pro

@ -1,6 +1,9 @@
# Copyright 2019-2020 The Hush developers
# Released under the GPLv3
#------------------------------------------------- #-------------------------------------------------
# #
# Project created by QtCreator 2018-10-05T09:54:45 # Project created by QtCreator 2018-10-05T09:54:45
# Originally from zecwallet
# #
#------------------------------------------------- #-------------------------------------------------
@ -14,7 +17,6 @@ QT += widgets
QT += websockets QT += websockets
TARGET = silentdragon TARGET = silentdragon
TEMPLATE = app TEMPLATE = app
# The following define makes your compiler emit warnings if you use # The following define makes your compiler emit warnings if you use

88
src/addressbook.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush Developers
// Released under the GPLv3
#include "addressbook.h" #include "addressbook.h"
#include "ui_addressbook.h" #include "ui_addressbook.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
@ -30,9 +32,9 @@ void AddressBookModel::loadData() {
parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray()); parent->horizontalHeader()->restoreState(QSettings().value("addresstablegeometry").toByteArray());
} }
void AddressBookModel::addNewLabel(QString label, QString addr) { void AddressBookModel::addNewLabel(QString label, QString addr, QString myZaddr) {
//labels.push_back(QPair<QString, QString>(label, addr)); //labels.push_back(QPair<QString, QString>(label, addr));
AddressBook::getInstance()->addAddressLabel(label, addr); AddressBook::getInstance()->addAddressLabel(label, addr, myZaddr);
labels.clear(); labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels(); labels = AddressBook::getInstance()->getAllAddressLabels();
@ -45,7 +47,7 @@ void AddressBookModel::removeItemAt(int row) {
if (row >= labels.size()) if (row >= labels.size())
return; return;
AddressBook::getInstance()->removeAddressLabel(labels[row].first, labels[row].second); AddressBook::getInstance()->removeAddressLabel(labels[row][0], labels[row][1]);
labels.clear(); labels.clear();
labels = AddressBook::getInstance()->getAllAddressLabels(); labels = AddressBook::getInstance()->getAllAddressLabels();
@ -54,8 +56,8 @@ void AddressBookModel::removeItemAt(int row) {
layoutChanged(); layoutChanged();
} }
QPair<QString, QString> AddressBookModel::itemAt(int row) { QList<QString> AddressBookModel::itemAt(int row) {
if (row >= labels.size()) return QPair<QString, QString>(); if (row >= labels.size()) return QList<QString>();
return labels.at(row); return labels.at(row);
} }
@ -73,8 +75,8 @@ int AddressBookModel::columnCount(const QModelIndex&) const {
QVariant AddressBookModel::data(const QModelIndex &index, int role) const { QVariant AddressBookModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
switch(index.column()) { switch(index.column()) {
case 0: return labels.at(index.row()).first; case 0: return labels.at(index.row())[0];
case 1: return labels.at(index.row()).second; case 1: return labels.at(index.row())[1];
} }
} }
return QVariant(); return QVariant();
@ -147,7 +149,7 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
return; return;
} }
model.addNewLabel(newLabel, ab.addr->text()); model.addNewLabel(newLabel, ab.addr->text(),"");
}); });
// Import Button // Import Button
@ -176,7 +178,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
continue; continue;
// Add label, address. // Add label, address.
model.addNewLabel(items.at(1), items.at(0)); //TODO: myzaddr
model.addNewLabel(items.at(1), items.at(0), "");
numImported++; numImported++;
} }
@ -196,8 +199,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (index.row() < 0) return; if (index.row() < 0) return;
QString lbl = model.itemAt(index.row()).first; QString lbl = model.itemAt(index.row())[0];
QString addr = model.itemAt(index.row()).second; QString addr = model.itemAt(index.row())[1];
d.accept(); d.accept();
fnSetTargetLabelAddr(target, lbl, addr); fnSetTargetLabelAddr(target, lbl, addr);
}); });
@ -209,8 +212,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
if (index.row() < 0) return; if (index.row() < 0) return;
QString lbl = model.itemAt(index.row()).first; QString lbl = model.itemAt(index.row())[0];
QString addr = model.itemAt(index.row()).second; QString addr = model.itemAt(index.row())[1];
QMenu menu(parent); QMenu menu(parent);
@ -237,7 +240,7 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) {
auto selection = ab.addresses->selectionModel(); auto selection = ab.addresses->selectionModel();
if (selection && selection->hasSelection() && selection->selectedRows().size() > 0) { if (selection && selection->hasSelection() && selection->selectedRows().size() > 0) {
auto item = model.itemAt(selection->selectedRows().at(0).row()); auto item = model.itemAt(selection->selectedRows().at(0).row());
fnSetTargetLabelAddr(target, item.first, item.second); fnSetTargetLabelAddr(target, item[0], item[1]);
} }
}; };
@ -267,26 +270,44 @@ void AddressBook::readFromStorage() {
file.open(QIODevice::ReadOnly); file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file QDataStream in(&file); // read the data serialized from the file
QString version; QString version;
in >> version >> allLabels; in >> version;
if (version == "v1") {
qDebug() << "Detected old addressbook format";
// Convert old addressbook format v1 to v2
QList<QPair<QString,QString>> stuff;
in >> stuff;
qDebug() << "Stuff: " << stuff;
for (int i=0; i < stuff.size(); i++) {
QList<QString> contact = { stuff[i].first, stuff[i].second, "" };
qDebug() << "contact=" << contact;
allLabels.push_back(contact);
}
} else {
in >> allLabels;
}
qDebug() << "Read " << version << " Hush contacts from disk...";
file.close(); file.close();
} else {
qDebug() << "No Hush contacts found on disk!";
} }
// Special. // Special.
// Add the default ZecWallet donation address if it isn't already present // Add the default ZecWallet donation address if it isn't already present
// QList<QString> allAddresses; // QList<QString> allAddresses;
// std::transform(allLabels.begin(), allLabels.end(), // std::transform(allLabels.begin(), allLabels.end(),
// std::back_inserter(allAddresses), [=] (auto i) { return i.second; }); // std::back_inserter(allAddresses), [=] (auto i) { return i[1]; });
// if (!allAddresses.contains(Settings::getDonationAddr())) { // if (!allAddresses.contains(Settings::getDonationAddr())) {
// allLabels.append(QPair<QString, QString>("ZecWallet donation", Settings::getDonationAddr())); // allLabels.append(QPair<QString, QString>("ZecWallet donation", Settings::getDonationAddr()));
// } // }
} }
void AddressBook::writeToStorage() { void AddressBook::writeToStorage() {
//TODO: we probably should do more exception-handling here
QFile file(AddressBook::writeableFile()); QFile file(AddressBook::writeableFile());
file.open(QIODevice::ReadWrite | QIODevice::Truncate); file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file QDataStream out(&file); // we will serialize the data into the file
out << QString("v1") << allLabels; out << QString("v2") << allLabels;
file.close(); file.close();
} }
@ -306,18 +327,25 @@ QString AddressBook::writeableFile() {
// Add a new address/label to the database // Add a new address/label to the database
void AddressBook::addAddressLabel(QString label, QString address) { // TODO: return bool for success/fail
Q_ASSERT(Settings::isValidAddress(address)); void AddressBook::addAddressLabel(QString label, QString address, QString myzaddr) {
qDebug() << "Adding " << label << "=" << address << "," << myzaddr;
if(!Settings::isValidAddress(address)) {
qDebug() << "Invalid zaddr:" << address;
//return;
}
// First, remove any existing label // First, remove any existing label
// Iterate over the list and remove the label/address // Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) { for (int i=0; i < allLabels.size(); i++) {
if (allLabels[i].first == label) { if (allLabels[i][0] == label) {
removeAddressLabel(allLabels[i].first, allLabels[i].second); removeAddressLabel(allLabels[i][0], allLabels[i][1]);
} }
} }
allLabels.push_back(QPair<QString, QString>(label, address)); QList<QString> contact = { label, address, myzaddr };
allLabels.push_back(contact);
writeToStorage(); writeToStorage();
} }
@ -325,7 +353,7 @@ void AddressBook::addAddressLabel(QString label, QString address) {
void AddressBook::removeAddressLabel(QString label, QString address) { void AddressBook::removeAddressLabel(QString label, QString address) {
// Iterate over the list and remove the label/address // Iterate over the list and remove the label/address
for (int i=0; i < allLabels.size(); i++) { for (int i=0; i < allLabels.size(); i++) {
if (allLabels[i].first == label && allLabels[i].second == address) { if (allLabels[i][0] == label && allLabels[i][1] == address) {
allLabels.removeAt(i); allLabels.removeAt(i);
writeToStorage(); writeToStorage();
return; return;
@ -336,8 +364,8 @@ void AddressBook::removeAddressLabel(QString label, QString address) {
void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel) { void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabel) {
// Iterate over the list and update the label/address // Iterate over the list and update the label/address
for (int i = 0; i < allLabels.size(); i++) { for (int i = 0; i < allLabels.size(); i++) {
if (allLabels[i].first == oldlabel && allLabels[i].second == address) { if (allLabels[i][0] == oldlabel && allLabels[i][1] == address) {
allLabels[i].first = newlabel; allLabels[i][0] = newlabel;
writeToStorage(); writeToStorage();
return; return;
} }
@ -345,7 +373,7 @@ void AddressBook::updateLabel(QString oldlabel, QString address, QString newlabe
} }
// Read all addresses // Read all addresses
const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels() { const QList<QList<QString>>& AddressBook::getAllAddressLabels() {
if (allLabels.isEmpty()) { if (allLabels.isEmpty()) {
readFromStorage(); readFromStorage();
} }
@ -355,8 +383,8 @@ const QList<QPair<QString, QString>>& AddressBook::getAllAddressLabels() {
// Get the label for an address // Get the label for an address
QString AddressBook::getLabelForAddress(QString addr) { QString AddressBook::getLabelForAddress(QString addr) {
for (auto i : allLabels) { for (auto i : allLabels) {
if (i.second == addr) if (i[1] == addr)
return i.first; return i[0];
} }
return ""; return "";
@ -365,8 +393,8 @@ QString AddressBook::getLabelForAddress(QString addr) {
// Get the address for a label // Get the address for a label
QString AddressBook::getAddressForLabel(QString label) { QString AddressBook::getAddressForLabel(QString label) {
for (auto i: allLabels) { for (auto i: allLabels) {
if (i.first == label) if (i[0] == label)
return i.second; return i[1];
} }
return ""; return "";

17
src/addressbook.h

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush Developers
// Released under the GPLv3
#ifndef ADDRESSBOOK_H #ifndef ADDRESSBOOK_H
#define ADDRESSBOOK_H #define ADDRESSBOOK_H
@ -11,9 +13,9 @@ public:
AddressBookModel(QTableView* parent); AddressBookModel(QTableView* parent);
~AddressBookModel(); ~AddressBookModel();
void addNewLabel(QString label, QString addr); void addNewLabel(QString label, QString addr, QString myzaddr);
void removeItemAt(int row); void removeItemAt(int row);
QPair<QString, QString> itemAt(int row); QList<QString> itemAt(int row);
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
int columnCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const;
@ -25,7 +27,7 @@ private:
void saveData(); void saveData();
QTableView* parent; QTableView* parent;
QList<QPair<QString, QString>> labels; QList<QList<QString>> labels;
QStringList headers; QStringList headers;
}; };
@ -39,7 +41,7 @@ public:
static QString addressFromAddressLabel(const QString& lblAddr); static QString addressFromAddressLabel(const QString& lblAddr);
// Add a new address/label to the database // Add a new address/label to the database
void addAddressLabel(QString label, QString address); void addAddressLabel(QString label, QString address, QString myZaddr);
// Remove a new address/label from the database // Remove a new address/label from the database
void removeAddressLabel(QString label, QString address); void removeAddressLabel(QString label, QString address);
@ -48,7 +50,7 @@ public:
void updateLabel(QString oldlabel, QString address, QString newlabel); void updateLabel(QString oldlabel, QString address, QString newlabel);
// Read all addresses // Read all addresses
const QList<QPair<QString, QString>>& getAllAddressLabels(); const QList<QList<QString>>& getAllAddressLabels();
// Get an address's first label // Get an address's first label
QString getLabelForAddress(QString address); QString getLabelForAddress(QString address);
@ -61,9 +63,10 @@ private:
void writeToStorage(); void writeToStorage();
QString writeableFile(); QString writeableFile();
QList<QPair<QString, QString>> allLabels; // contact name, contact address, myzaddr (the zaddr we use to receive from this contact)
QList<QList<QString>> allLabels;
static AddressBook* instance; static AddressBook* instance;
}; };
#endif // ADDRESSBOOK_H #endif // ADDRESSBOOK_H

20
src/connection.h

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush developers
// Released under the GPLv3
#ifndef CONNECTION_H #ifndef CONNECTION_H
#define CONNECTION_H #define CONNECTION_H
@ -82,7 +84,7 @@ private:
}; };
/** /**
* Represents a connection to a zcashd. It may even start a new zcashd if needed. * Represents a connection to a hushd. It may even start a new hushd if needed.
* This is also a UI class, so it may show a dialog waiting for the connection. * This is also a UI class, so it may show a dialog waiting for the connection.
*/ */
class Connection { class Connection {
@ -118,8 +120,10 @@ public:
// any overlapping calls // any overlapping calls
static QMap<QString, bool> inProgress; static QMap<QString, bool> inProgress;
//QString method = QString::fromStdString(payloadGenerator(payloads[0])["method"]);
//QString method = QString::fromStdString(payloadGenerator(payloads[0])["method"]);
QString method = payloadGenerator(payloads[0])["method"].toString(); QString method = payloadGenerator(payloads[0])["method"].toString();
qDebug() << __func__ << " with method=" << method << " and totalSize=" << totalSize;
//if (inProgress.value(method, false)) { //if (inProgress.value(method, false)) {
// qDebug() << "In progress batch, skipping"; // qDebug() << "In progress batch, skipping";
// return; // return;
@ -137,11 +141,12 @@ public:
QObject::connect(reply, &QNetworkReply::finished, [=] { QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater(); reply->deleteLater();
if (shutdownInProgress) { if (shutdownInProgress) {
// Ignoring callback because shutdown in progress qDebug() << "Ignoring callback because shutdown in progress";
return; return;
} }
auto all = reply->readAll(); auto all = reply->readAll();
qDebug() << "Parsing JSON...";
auto parsed = QJsonDocument::fromJson(all); auto parsed = QJsonDocument::fromJson(all);
if (reply->error() != QNetworkReply::NoError) { if (reply->error() != QNetworkReply::NoError) {
@ -150,9 +155,12 @@ public:
(*responses)[item] = {}; // Empty object (*responses)[item] = {}; // Empty object
} else { } else {
//if (parsed.is_discarded()) {
// qDebug() << "Discarded response!";
if (parsed.isEmpty()) { if (parsed.isEmpty()) {
(*responses)[item] = {}; // Empty object (*responses)[item] = {}; // Empty object
} else { } else {
qDebug() << "Parsed valid JSON";
(*responses)[item] = parsed["result"]; (*responses)[item] = parsed["result"];
} }
} }
@ -160,8 +168,10 @@ public:
} }
auto waitTimer = new QTimer(main); auto waitTimer = new QTimer(main);
qDebug() << "Created timer...";
QObject::connect(waitTimer, &QTimer::timeout, [=]() { QObject::connect(waitTimer, &QTimer::timeout, [=]() {
if (shutdownInProgress) { if (shutdownInProgress) {
qDebug() << "Shutdown in progress, removing timer";
waitTimer->stop(); waitTimer->stop();
waitTimer->deleteLater(); waitTimer->deleteLater();
return; return;
@ -169,6 +179,7 @@ public:
// If all responses have arrived, return // If all responses have arrived, return
if (responses->size() == totalSize) { if (responses->size() == totalSize) {
qDebug() << "Response arrived, removing timer...";
waitTimer->stop(); waitTimer->stop();
@ -178,6 +189,7 @@ public:
waitTimer->deleteLater(); waitTimer->deleteLater();
} }
}); });
qDebug() << "Starting timer...";
waitTimer->start(100); waitTimer->start(100);
} }

238
src/mainwindow.cpp

@ -23,6 +23,18 @@
#include "websockets.h" #include "websockets.h"
QString MainWindow::getZaddrForContact(QString contact) {
QList<QList<QString>> addressLabels = AddressBook::getInstance()->getAllAddressLabels();
for (int i = 0; i < addressLabels.size(); ++i) {
QList<QString> thisContact = addressLabels.at(i);
if (thisContact[0] == contact) {
qDebug() << "Found contact " << thisContact[0] << " " << thisContact[1];
return thisContact[1];
}
}
return "";
}
MainWindow::MainWindow(QWidget *parent) : MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), QMainWindow(parent),
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
@ -48,23 +60,15 @@ MainWindow::MainWindow(QWidget *parent) :
// Settings editor // Settings editor
setupSettingsModal(); setupSettingsModal();
// Set up exit action // Set up actions
QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close);
// Set up feedback action
QObject::connect(ui->actionDonate, &QAction::triggered, this, &MainWindow::donate); QObject::connect(ui->actionDonate, &QAction::triggered, this, &MainWindow::donate);
QObject::connect(ui->actionDiscord, &QAction::triggered, this, &MainWindow::discord); QObject::connect(ui->actionDiscord, &QAction::triggered, this, &MainWindow::discord);
QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug); QObject::connect(ui->actionReportBug, &QAction::triggered, this, &MainWindow::reportbug);
QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website); QObject::connect(ui->actionWebsite, &QAction::triggered, this, &MainWindow::website);
// Set up check for updates action // Send button
QObject::connect(ui->actionCheck_for_Updates, &QAction::triggered, [=] () { QObject::connect(ui->sendMemo, &QPushButton::clicked, this, &MainWindow::sendMemo);
// Silent is false, so show notification even if no update was found
rpc->checkForUpdate(false);
});
// Request hush // Request hush
QObject::connect(ui->actionRequest_zcash, &QAction::triggered, [=]() { QObject::connect(ui->actionRequest_zcash, &QAction::triggered, [=]() {
@ -118,29 +122,180 @@ MainWindow::MainWindow(QWidget *parent) :
// Initialize to the balances tab // Initialize to the balances tab
ui->tabWidget->setCurrentIndex(0); ui->tabWidget->setCurrentIndex(0);
if (AppDataServer::getInstance()->isAppConnected()) {
auto ads = AppDataServer::getInstance();
QString wormholecode = "";
if (ads->getAllowInternetConnection())
wormholecode = ads->getWormholeCode(ads->getSecretHex());
qDebug() << "MainWindow: createWebsocket with wormholecode=" << wormholecode;
createWebsocket(wormholecode);
}
//TODO: allow user to set this
ui->textEdit->setTextColor( QColor("red") );
QItemSelectionModel* qsm = ui->chatView->selectionModel();
QObject::connect(qsm, SIGNAL(itemSelectionChanged(const QItemSelection&, const QItemSelection&)),this, SLOT(itemSelectionChanged()));
// Contacts and chat views should not be editable
ui->chatView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->contactsView->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->contactsView->setViewMode(QListView::ListMode);
// This works but doesn't take into account dark theme and is unreadable
//ui->contactsView->setAlternatingRowColors(true);
setupSendTab(); setupSendTab();
setupTransactionsTab(); setupTransactionsTab();
setupReceiveTab(); setupReceiveTab();
setupBalancesTab(); setupBalancesTab();
setupMarketTab(); setupMarketTab();
//setupChatTab(); setupChatTab();
setupHushTab(); setupHushTab();
// Set up check for updates action
QObject::connect(ui->actionCheck_for_Updates, &QAction::triggered, [=] () {
// Silent is false, so show notification even if no update was found
rpc->checkForUpdate(false);
});
rpc = new RPC(this); rpc = new RPC(this);
qDebug() << "Created RPC"; qDebug() << "Created RPC";
restoreSavedStates(); restoreSavedStates();
if (AppDataServer::getInstance()->isAppConnected()) { }
auto ads = AppDataServer::getInstance();
QString wormholecode = ""; QString MainWindow::createHeaderMemo(QString cid, QString zaddr, int version=0, int headerNumber=1)
if (ads->getAllowInternetConnection()) {
wormholecode = ads->getWormholeCode(ads->getSecretHex()); QString header="";
QJsonDocument j;
QJsonObject h;
version = -1; // This is unstable v=-1 until we launch with v=0
// We use short keynames to use less space for metadata and so allow
// the user to send more actual data in memos
h["h"] = headerNumber; // header number
h["v"] = version; // HushChat version
h["z"] = zaddr; // zaddr to respond to
h["cid"] = cid; // conversation id
j.setObject(h);
//TODO: how do we remove newlines?
header = j.toJson();
qDebug() << "made header=" << header;
return header;
}
qDebug() << "MainWindow: createWebsocket with wormholecode=" << wormholecode; QString MainWindow::getZaddrForCurrentContact() {
createWebsocket(wormholecode); QString zaddr;
QModelIndex qmi = ui->contactsView->currentIndex();
if (qmi.isValid()) {
qDebug() << "Current (row,col) index: " << qmi.row() << "," << qmi.column();
// we seem to get duplicates due to QT internals shenanigans, just pick the first
QMap <int, QVariant> currentContacts = ui->contactsView->model()->itemData(qmi);
QString contact = currentContacts[0].toString();
qDebug() << "Current HushContact: " << contact;
zaddr = getZaddrForContact(contact);
} else {
qDebug() << "Invalid current index, no contacts selected";
}
return zaddr;
}
QString MainWindow::getNameForCurrentContact() {
QString name;
QModelIndex qmi = ui->contactsView->currentIndex();
if (qmi.isValid()) {
qDebug() << "Current (row,col) index: " << qmi.row() << "," << qmi.column();
// we seem to get duplicates due to QT internals shenanigans, just pick the first
QMap <int, QVariant> currentContacts = ui->contactsView->model()->itemData(qmi);
QString name = currentContacts[0].toString();
} else {
qDebug() << "Invalid current index, no contacts selected";
} }
return name;
}
// Send button clicked
void MainWindow::sendMemo() {
HushChat thisChat = MainWindow::getHushChat();
// Either we made a custom zaddr for this contact in the past, or we make a new one now
if(thisChat.getContact().getMyZaddr().isEmpty()) {
QString newzaddr;
rpc->newZaddr( [=] (QJsonValue reply) {
Tx tx;
tx.fee = Settings::getMinerFee();
//TODO: verify we currently own the private key to this zaddr via z_validateaddress
HushChat chat = MainWindow::getHushChat();
HushContact contact = chat.getContact();
QString myZaddr = reply.toString();
QString addr = getZaddrForCurrentContact();
QString name = getNameForCurrentContact();
qDebug() << "created new myZaddr="<< myZaddr << " for " << name;
contact.setName(name);
contact.setMyZaddr(myZaddr);
contact.setZaddr(addr);
AddressBook::getInstance()->addAddressLabel(contact.getName(), contact.getZaddr(), contact.getMyZaddr());
qDebug() << "Wrote new myZaddr for " << contact.getName() << " to storage";
qDebug() << "Using " << myZaddr << " as from address for " << contact.getName();
double amount = 0;
QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces);
QString hmemo = createHeaderMemo(cid,myZaddr);
QString memo = ui->textEdit->toPlainText();
// we send a header memo plus actual memo
tx.toAddrs.push_back( ToFields{addr, amount, hmemo, hmemo.toUtf8().toHex()} );
tx.toAddrs.push_back( ToFields{addr, amount, memo, memo.toUtf8().toHex()} );
tx.fromAddr = contact.getMyZaddr();
qDebug() << "Sending "<< name << "(" << addr << ") a memo: " << memo;
QString error = doSendTxValidations(tx);
if (!error.isEmpty()) {
// Something went wrong, so show an error and exit
QMessageBox msg(QMessageBox::Critical, tr("Transaction Error"), error,
QMessageBox::Ok, this);
msg.exec();
// abort the Tx
return;
}
// Show a dialog to confirm the Tx
if (confirmTx(tx)) {
// And send the Tx
rpc->executeTransaction(tx,
[=] (QString opid) {
ui->statusBar->showMessage(tr("Computing transaction: ") % opid);
qDebug() << "Computing opid: " << opid;
},
[=] (QString, QString txid) {
ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid);
},
[=] (QString opid, QString errStr) {
ui->statusBar->showMessage(QObject::tr(" Transaction ") % 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);
}
);
}
}); // newZaddr
} else {
// this contact already has a myZaddr
}
} }
void MainWindow::createWebsocket(QString wormholecode) { void MainWindow::createWebsocket(QString wormholecode) {
@ -705,14 +860,27 @@ void MainWindow::balancesReady() {
} }
// Event filter for MacOS specific handling of payment URIs
bool MainWindow::eventFilter(QObject *object, QEvent *event) { bool MainWindow::eventFilter(QObject *object, QEvent *event) {
// Event filter for MacOS specific handling of payment URIs
if (event->type() == QEvent::FileOpen) { if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event); QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
if (!fileEvent->url().isEmpty()) if (!fileEvent->url().isEmpty())
payZcashURI(fileEvent->url().toString()); payZcashURI(fileEvent->url().toString());
return true; return true;
} else if (event->type() == QEvent::MouseButtonPress) {
qDebug() << __func__ <<": "<<" mouse button event on " << object->objectName();
QMouseEvent *ev = static_cast<QMouseEvent *>(event);
if (ev->buttons() & Qt::RightButton)
{
//qDebug()<< "RightButton clicked";
}
if (ev->buttons() & Qt::LeftButton)
{
//qDebug()<< "LeftButton clicked";
//TODO: if this was a HushContact object in chatView, update MainWindow::contact
}
//return false;
} }
return QObject::eventFilter(object, event); return QObject::eventFilter(object, event);
@ -1136,26 +1304,31 @@ void MainWindow::setupBalancesTab() {
void MainWindow::setupHushTab() { void MainWindow::setupHushTab() {
ui->hushlogo->setBasePixmap(QPixmap(":/img/res/zcashdlogo.gif")); ui->hushlogo->setBasePixmap(QPixmap(":/img/res/zcashdlogo.gif"));
} }
/*
void MainWindow::setupChatTab() { void MainWindow::setupChatTab() {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
QList<QPair<QString,QString>> addressLabels = AddressBook::getInstance()->getAllAddressLabels(); QList<QList<QString>> addressLabels = AddressBook::getInstance()->getAllAddressLabels();
QStringListModel *chatModel = new QStringListModel(); QStringListModel *chatModel = new QStringListModel();
QStringList contacts; QStringList contacts;
//contacts << "Alice" << "Bob" << "Charlie" << "Eve"; //contacts << "Alice" << "Bob" << "Charlie" << "Eve";
for (int i = 0; i < addressLabels.size(); ++i) { for (int i = 0; i < addressLabels.size(); ++i) {
QPair<QString,QString> pair = addressLabels.at(i); QList<QString> thisContact = addressLabels.at(i);
qDebug() << "Found contact " << pair.first << " " << pair.second; qDebug() << "Found contact " << thisContact[0] << " " << thisContact[1];
contacts << pair.first; contacts << thisContact[0];
} }
chatModel->setStringList(contacts); chatModel->setStringList(contacts);
QStringListModel *conversationModel = new QStringListModel(); QStringListModel *conversationModel = new QStringListModel();
QStringList conversations; QStringList conversations;
conversations << "Bring home some milk" << "Markets look rough" << "How's the weather?" << "Is this on?"; conversations << "The Bitcoin network might actually reduce spam by diverting zombie farms to generating bitcoins instead.";
conversationModel->setStringList(conversations); conversationModel->setStringList(conversations);
//conversationModel[0].setItemAlignment(Qt::AlignRight);
// iterate on all elements in chat view and set alignment
// ui->chatView->
//Ui_addressBook ab; //Ui_addressBook ab;
//AddressBookModel model(ab.addresses); //AddressBookModel model(ab.addresses);
@ -1166,8 +1339,9 @@ void MainWindow::setupChatTab() {
ui->contactsView->setModel(chatModel); ui->contactsView->setModel(chatModel);
ui->chatView->setModel( conversationModel ); ui->chatView->setModel( conversationModel );
ui->chatGridLayout->setColumnStretch(1,1);
ui->chatGridLayout->setRowStretch(1,2);
} }
*/
void MainWindow::setupMarketTab() { void MainWindow::setupMarketTab() {
qDebug() << "Setting up market tab"; qDebug() << "Setting up market tab";
@ -1486,14 +1660,12 @@ void MainWindow::setupReceiveTab() {
if (!curLabel.isEmpty() && label.isEmpty()) { if (!curLabel.isEmpty() && label.isEmpty()) {
info = "Removed Label '" % curLabel % "'"; info = "Removed Label '" % curLabel % "'";
AddressBook::getInstance()->removeAddressLabel(curLabel, addr); AddressBook::getInstance()->removeAddressLabel(curLabel, addr);
} } else if (!curLabel.isEmpty() && !label.isEmpty()) {
else if (!curLabel.isEmpty() && !label.isEmpty()) {
info = "Updated Label '" % curLabel % "' to '" % label % "'"; info = "Updated Label '" % curLabel % "' to '" % label % "'";
AddressBook::getInstance()->updateLabel(curLabel, addr, label); AddressBook::getInstance()->updateLabel(curLabel, addr, label);
} } else if (curLabel.isEmpty() && !label.isEmpty()) {
else if (curLabel.isEmpty() && !label.isEmpty()) {
info = "Added Label '" % label % "'"; info = "Added Label '" % label % "'";
AddressBook::getInstance()->addAddressLabel(label, addr); AddressBook::getInstance()->addAddressLabel(label, addr,"");
} }
// Update labels everywhere on the UI // Update labels everywhere on the UI
@ -1561,7 +1733,7 @@ void MainWindow::slot_change_currency(const QString& currency_name)
saved_currency_name = Settings::getInstance()->get_currency_name(); saved_currency_name = Settings::getInstance()->get_currency_name();
} catch (const std::exception& e) { } catch (const std::exception& e) {
qDebug() << QString("Ignoring currency change Exception! : "); qDebug() << QString("Ignoring currency change Exception! : ");
saved_currency_name = "USD"; saved_currency_name = "BTC";
} }
} }

43
src/mainwindow.h

@ -29,6 +29,41 @@ namespace Ui {
class MainWindow; class MainWindow;
} }
class HushContact
{
public:
void setName(QString newname) { name = newname; }
QString getName() { return name; }
QString getZaddr() { return zaddr; }
void setZaddr(QString z) { zaddr = z; }
QString getMyZaddr() { return myZaddr; }
void setMyZaddr(QString z) { myZaddr = z; }
private:
QString name;
QString nickname;
QString zaddr;
QString myZaddr;
//int64_t lastSentTime;
//int64_t lastReceivedTime;
};
class HushChat
{
public:
void setContact(HushContact newcontact) { contact = newcontact; }
HushContact getContact() { return contact; }
QString getMyZaddr() { return myZaddr; }
void setMyZaddr(QString z) { myZaddr = z; }
private:
QString myZaddr;
HushContact contact;
};
class MainWindow : public QMainWindow class MainWindow : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -43,6 +78,9 @@ public:
QCompleter* getLabelCompleter() { return labelCompleter; } QCompleter* getLabelCompleter() { return labelCompleter; }
QRegExpValidator* getAmountValidator() { return amtValidator; } QRegExpValidator* getAmountValidator() { return amtValidator; }
QString getZaddrForContact(QString contact);
QString getZaddrForCurrentContact();
QString getNameForCurrentContact();
QString doSendTxValidations(Tx tx); QString doSendTxValidations(Tx tx);
void setDefaultPayFrom(); void setDefaultPayFrom();
@ -70,6 +108,9 @@ public:
Logger* logger; Logger* logger;
void doClose(); void doClose();
HushChat getHushChat() { return hushChat; }
void setHushChat(HushChat chat) { hushChat = chat; }
QString createHeaderMemo(QString cid, QString zaddr, int version, int headerNumnber);
private: private:
void closeEvent(QCloseEvent* event); void closeEvent(QCloseEvent* event);
@ -98,6 +139,7 @@ private:
void cancelButton(); void cancelButton();
void sendButton(); void sendButton();
void sendMemo();
void inputComboTextChanged(int index); void inputComboTextChanged(int index);
void addAddressSection(); void addAddressSection();
void maxAmountChecked(int checked); void maxAmountChecked(int checked);
@ -137,6 +179,7 @@ private:
WSServer* wsserver = nullptr; WSServer* wsserver = nullptr;
WormholeClient* wormhole = nullptr; WormholeClient* wormhole = nullptr;
HushChat hushChat;
RPC* rpc = nullptr; RPC* rpc = nullptr;
QCompleter* labelCompleter = nullptr; QCompleter* labelCompleter = nullptr;

64
src/mainwindow.ui

@ -1019,27 +1019,67 @@
<attribute name="title"> <attribute name="title">
<string>Chat</string> <string>Chat</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_7"> <layout class="QVBoxLayout" name="chatVBoxLayout">
<item> <item>
<layout class="QGridLayout" name="gridLayout_6"> <layout class="QGridLayout" name="chatGridLayout">
<item row="0" column="0"> <item row="1" column="0">
<widget class="QListView" name="contactsView"/> <widget class="QListView" name="contactsView"/>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QTextEdit" name="textEdit"/> <widget class="QListView" name="chatView"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="tmp2">
<property name="text">
<string>Hush Contacts</string>
</property>
</widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QListView" name="chatView"/> <widget class="QLabel" name="tmp3">
<property name="text">
<string>XXX and YYY metadata about this HushChat</string>
</property>
</widget>
</item> </item>
<item row="1" column="2">
<widget class="QPushButton" name="pushButton"> <item row="2" column="1">
<property name="text"> <widget class="QTextEdit" name="textEdit">
<string>Send</string>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="3" column="1">
<widget class="QPushButton" name="pushButton_2">
<layout class="QGridLayout" name="chatButtonLayout">
<item row="0" column="0">
<widget class="QPushButton" name="fileUpload">
<property name="text">
<string>Upload</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="sendMemo">
<property name="sizeHint" stdset="0">
<size>
<width>50</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Send Memo!</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="newHushChat">
<property name="text"> <property name="text">
<string>New HushChat</string> <string>New HushChat</string>
</property> </property>

29
src/rpc.cpp

@ -32,7 +32,7 @@ RPC::RPC(MainWindow* main) {
QObject::connect(priceTimer, &QTimer::timeout, [=]() { QObject::connect(priceTimer, &QTimer::timeout, [=]() {
refreshPrice(); refreshPrice();
}); });
priceTimer->start(Settings::priceRefreshSpeed); // Every hour priceTimer->start(Settings::priceRefreshSpeed);
// Set up a timer to refresh the UI every few seconds // Set up a timer to refresh the UI every few seconds
timer = new QTimer(main); timer = new QTimer(main);
@ -429,6 +429,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// We'll only refresh the received Z txs if settings allows us. // We'll only refresh the received Z txs if settings allows us.
if (!Settings::getInstance()->getSaveZtxs()) { if (!Settings::getInstance()->getSaveZtxs()) {
qDebug() << "Settings have saved zaddr transactions OFF, showing empty list";
QList<TransactionItem> emptylist; QList<TransactionItem> emptylist;
transactionsTableModel->addZRecvData(emptylist); transactionsTableModel->addZRecvData(emptylist);
return; return;
@ -456,6 +457,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
// appears multiple times in a single tx's outputs. // appears multiple times in a single tx's outputs.
QSet<QString> txids; QSet<QString> txids;
QMap<QString, QString> memos; QMap<QString, QString> memos;
qDebug() << "Processing zaddrs...";
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
auto zaddr = it.key(); auto zaddr = it.key();
for (const auto& i : it.value().toArray()) { for (const auto& i : it.value().toArray()) {
@ -468,17 +470,23 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
txids.insert(txid); txids.insert(txid);
// Check for Memos // Check for Memos
QString memoBytes = QString::fromStdString(i["memo"].get<json::string_t>());
//TODO: This should check for valid utf8!
QString memoBytes = i.toObject()["memo"].toString(); QString memoBytes = i.toObject()["memo"].toString();
if (!memoBytes.startsWith("f600")) { if (!memoBytes.startsWith("f600")) {
//QString memo(QByteArray::fromHex(
// QByteArray::fromStdString(i["memo"].get<json::string_t>())));
QString memo(QByteArray::fromHex( QString memo(QByteArray::fromHex(
i.toObject()["memo"].toString().toUtf8())); i.toObject()["memo"].toString().toUtf8()));
if (!memo.trimmed().isEmpty()) if (!memo.trimmed().isEmpty())
qDebug() << "Found a memo for txid=" << txid;
memos[zaddr + txid] = memo; memos[zaddr + txid] = memo;
} }
} }
} }
} }
qDebug() << "Processing all txids...";
// 2. For all txids, go and get the details of that txid. // 2. For all txids, go and get the details of that txid.
conn->doBatchRPC<QString>(txids.toList(), conn->doBatchRPC<QString>(txids.toList(),
[=] (QString txid) { [=] (QString txid) {
@ -536,6 +544,7 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
/// This will refresh all the balance data from hushd /// This will refresh all the balance data from hushd
void RPC::refresh(bool force) { void RPC::refresh(bool force) {
qDebug() << __func__;
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
@ -696,6 +705,8 @@ void RPC::getInfoThenRefresh(bool force) {
price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % ticker % " " % extra; price = QString(", ") % "HUSH" % "=" % QString::number( (double)ticker_price,'f',8) % " " % ticker % " " % extra;
} }
qDebug() << "Updating status bar";
// Update the status bar // Update the status bar
QString statusText = QString() % QString statusText = QString() %
(isSyncing ? QObject::tr("Syncing") : QObject::tr("Connected")) % (isSyncing ? QObject::tr("Syncing") : QObject::tr("Connected")) %
@ -711,8 +722,8 @@ void RPC::getInfoThenRefresh(bool force) {
QString tooltip; QString tooltip;
if (connections > 0) { if (connections > 0) {
tooltip = QObject::tr("Connected to hushd"); tooltip = QObject::tr("Connected to hushd");
} } else {
else { qDeug() << "No connections!";
tooltip = QObject::tr("hushd has no peer connections! Network issues?"); tooltip = QObject::tr("hushd has no peer connections! Network issues?");
} }
tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getZcashdVersion()) % ")"; tooltip = tooltip % "(v" % QString::number(Settings::getInstance()->getZcashdVersion()) % ")";
@ -722,9 +733,11 @@ void RPC::getInfoThenRefresh(bool force) {
} }
main->statusLabel->setToolTip(tooltip); main->statusLabel->setToolTip(tooltip);
main->statusIcon->setToolTip(tooltip); main->statusIcon->setToolTip(tooltip);
qDebug() << "Set tooltip";
}); });
}, [=](QNetworkReply* reply, const QJsonValue&) { }, [=](QNetworkReply* reply, const QJsonValue&) {
qDebug() << "hushd is gone!";
// hushd has probably disappeared. // hushd has probably disappeared.
this->noConnection(); this->noConnection();
@ -742,6 +755,7 @@ void RPC::getInfoThenRefresh(bool force) {
} }
void RPC::refreshAddresses() { void RPC::refreshAddresses() {
qDebug() << __func__;
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
@ -807,6 +821,7 @@ bool RPC::processUnspent(const QJsonValue& reply, QMap<QString, double>* balance
}; };
void RPC::refreshBalances() { void RPC::refreshBalances() {
qDebug() << "Updating balances";
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
@ -836,10 +851,12 @@ void RPC::refreshBalances() {
auto newUtxos = new QList<UnspentOutput>(); auto newUtxos = new QList<UnspentOutput>();
auto newBalances = new QMap<QString, double>(); auto newBalances = new QMap<QString, double>();
qDebug() << "Updating taddr balances";
// Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI // Call the Transparent and Z unspent APIs serially and then, once they're done, update the UI
getTransparentUnspent([=] (QJsonValue reply) { getTransparentUnspent([=] (QJsonValue reply) {
auto anyTUnconfirmed = processUnspent(reply, newBalances, newUtxos); auto anyTUnconfirmed = processUnspent(reply, newBalances, newUtxos);
qDebug() << "Updating zaddr balances";
getZUnspent([=] (QJsonValue reply) { getZUnspent([=] (QJsonValue reply) {
auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos); auto anyZUnconfirmed = processUnspent(reply, newBalances, newUtxos);
@ -893,6 +910,7 @@ void RPC::refreshTransactions() {
// Read sent Z transactions from the file. // Read sent Z transactions from the file.
void RPC::refreshSentZTrans() { void RPC::refreshSentZTrans() {
qDebug() << __func__;
if (conn == nullptr) if (conn == nullptr)
return noConnection(); return noConnection();
@ -946,6 +964,7 @@ void RPC::refreshSentZTrans() {
void RPC::addNewTxToWatch(const QString& newOpid, WatchedTx wtx) { void RPC::addNewTxToWatch(const QString& newOpid, WatchedTx wtx) {
watchingOps.insert(newOpid, wtx); watchingOps.insert(newOpid, wtx);
qDebug() << "Watched new opid " << opid;
watchTxStatus(); watchTxStatus();
} }
@ -1286,8 +1305,8 @@ void RPC::shutdownZcashd() {
*/ */
QString RPC::getDefaultSaplingAddress() { QString RPC::getDefaultSaplingAddress() {
for (QString addr: *zaddresses) { for (QString addr: *zaddresses) {
if (Settings::getInstance()->isSaplingAddress(addr)) //if (Settings::getInstance()->isSaplingAddress(addr))
return addr; return addr;
} }
return QString(); return QString();

2
src/rpc.h

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush Developers
// Released under the GPLv3
#ifndef RPCCLIENT_H #ifndef RPCCLIENT_H
#define RPCCLIENT_H #define RPCCLIENT_H

3
src/sendtab.cpp

@ -1,4 +1,5 @@
// Copyright 2019-2020 Hush developers // Copyright 2019-2020 Hush developers
// Released under the GPLv3
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "addressbook.h" #include "addressbook.h"
@ -123,7 +124,7 @@ void MainWindow::updateLabelsAutoComplete() {
auto labels = AddressBook::getInstance()->getAllAddressLabels(); auto labels = AddressBook::getInstance()->getAllAddressLabels();
std::transform(labels.begin(), labels.end(), std::back_inserter(list), [=] (auto la) -> QString { std::transform(labels.begin(), labels.end(), std::back_inserter(list), [=] (auto la) -> QString {
return la.first % "/" % la.second; return la[0] % "/" % la[1];
}); });
delete labelCompleter; delete labelCompleter;

4
src/senttxstore.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush Developers
// Released under the GPLv3
#include "senttxstore.h" #include "senttxstore.h"
#include "settings.h" #include "settings.h"
@ -103,7 +105,7 @@ void SentTxStore::addToSentTx(Tx tx, QString txid) {
txItem["txid"] = txid; txItem["txid"] = txid;
txItem["amount"] = -totalAmount; txItem["amount"] = -totalAmount;
txItem["fee"] = -tx.fee; txItem["fee"] = -tx.fee;
// TODO: store all outgoing memos // TODO: store all outgoing memos, after encryption
txItem["memo"] = tx.toAddrs[0].txtMemo; txItem["memo"] = tx.toAddrs[0].txtMemo;
list.append(txItem); list.append(txItem);

2
src/txtablemodel.cpp

@ -1,3 +1,5 @@
// Copyright 2019-2020 The Hush Developers
// Released under the GPLv3
#include "txtablemodel.h" #include "txtablemodel.h"
#include "settings.h" #include "settings.h"
#include "rpc.h" #include "rpc.h"

Loading…
Cancel
Save