diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 68a95b7..a5ff83d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -60,7 +60,7 @@ MainWindow::MainWindow(QWidget *parent) : rpc = new RPC(new QNetworkAccessManager(this), this); rpc->refreshZECPrice(); - rpc->refresh(); + rpc->refresh(true); // Force refresh first time } void MainWindow::setupStatusBar() { @@ -99,7 +99,7 @@ void MainWindow::setupStatusBar() { } menu.addAction("Refresh", [=]() { - rpc->refresh(); + rpc->refresh(true); }); QPoint gpos(mapToGlobal(pos).x(), mapToGlobal(pos).y() + this->height() - ui->statusBar->height()); menu.exec(gpos); @@ -112,8 +112,7 @@ void MainWindow::setupStatusBar() { ui->statusBar->addPermanentWidget(statusIcon); } -void MainWindow::setupSettingsModal() { - +void MainWindow::setupSettingsModal() { // Set up File -> Settings action QObject::connect(ui->actionSettings, &QAction::triggered, [=]() { QDialog settingsDialog(this); @@ -132,7 +131,7 @@ void MainWindow::setupSettingsModal() { QMessageBox::Yes, QMessageBox::Cancel)) { SentTxStore::deleteHistory(); // Reload after the clear button so existing txs disappear - rpc->refresh(); + rpc->refresh(true); } }); @@ -182,7 +181,7 @@ void MainWindow::setupSettingsModal() { } // Then refresh everything. - this->rpc->refresh(); + this->rpc->refresh(true); }; }); diff --git a/src/rpc.cpp b/src/rpc.cpp index 5837697..fb190eb 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -366,6 +366,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { QSet txids; QMap memos; for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { + auto zaddr = it.key(); for (auto& i : it.value().get()) { // Filter out change txs if (! i["change"].get()) { @@ -378,7 +379,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { QString memo(QByteArray::fromHex( QByteArray::fromStdString(i["memo"].get()))); if (!memo.trimmed().isEmpty()) - memos[txid] = memo; + memos[zaddr + txid] = memo; } } } @@ -423,7 +424,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { auto confirmations = txidInfo["confirmations"].get(); TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount, - confirmations, "", memos.value(txid, "") }; + confirmations, "", memos.value(zaddr + txid, "") }; txdata.push_front(tx); } } @@ -441,13 +442,12 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { /// This will refresh all the balance data from zcashd -void RPC::refresh() { - // First, test the connection to see if we can actually get info. - getInfoThenRefresh(); +void RPC::refresh(bool force) { + getInfoThenRefresh(force); } -void RPC::getInfoThenRefresh() { +void RPC::getInfoThenRefresh(bool force) { json payload = { {"jsonrpc", "1.0"}, {"id", "someid"}, @@ -464,10 +464,17 @@ void RPC::getInfoThenRefresh() { QIcon i(":/icons/res/connected.png"); main->statusIcon->setPixmap(i.pixmap(16, 16)); - // Refresh everything. - refreshBalances(); - refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans() - refreshTransactions(); + static int lastBlock = 0; + int curBlock = reply["blocks"].get(); + + if ( force || (curBlock != lastBlock) ) { + // Something changed, so refresh everything. + lastBlock = curBlock; + + refreshBalances(); + refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans() + refreshTransactions(); + } // Call to see if the blockchain is syncing. json payload = { @@ -697,7 +704,7 @@ void RPC::watchTxStatus() { watchingOps.remove(id); // Refresh balances to show unconfirmed balances - refresh(); + refresh(true); } else if (status == "failed") { // If it failed, then we'll actually show a warning. auto errorMsg = QString::fromStdString(it["error"]["message"]); diff --git a/src/rpc.h b/src/rpc.h index a174ca3..b0e89ef 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -29,8 +29,9 @@ public: RPC(QNetworkAccessManager* restclient, MainWindow* main); ~RPC(); - void refresh(); // Refresh all transactions - void refreshAddresses(); // Refresh wallet Z-addrs + void refresh(bool force = false); + + void refreshAddresses(); void refreshZECPrice(); void sendZTransaction (json params, const std::function& cb); @@ -60,7 +61,7 @@ private: bool processUnspent (const json& reply); void updateUI (bool anyUnconfirmed); - void getInfoThenRefresh(); + void getInfoThenRefresh(bool force); void getBalance(const std::function& cb); diff --git a/src/txtablemodel.cpp b/src/txtablemodel.cpp index f86c860..b335d9f 100644 --- a/src/txtablemodel.cpp +++ b/src/txtablemodel.cpp @@ -5,7 +5,7 @@ TxTableModel::TxTableModel(QObject *parent) : QAbstractTableModel(parent) { - headers << "Category" << "Address" << "Date/Time" << "Amount"; + headers << "Type" << "Address" << "Date/Time" << "Amount"; } TxTableModel::~TxTableModel() { @@ -86,10 +86,16 @@ void TxTableModel::updateAllData() { b.setColor(Qt::black); return b; } - - if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { + + auto dat = modeldata->at(index.row()); + if (role == Qt::DisplayRole) { switch (index.column()) { - case 0: return modeldata->at(index.row()).type; + case 0: { + QString labels = (dat.type == "send" ? "S" : "R"); + if (!dat.memo.isEmpty()) + labels = labels + " M"; + return labels; + } case 1: { auto addr = modeldata->at(index.row()).address; if (addr.trimmed().isEmpty()) @@ -98,14 +104,24 @@ void TxTableModel::updateAllData() { return addr; } case 2: return QDateTime::fromSecsSinceEpoch(modeldata->at(index.row()).datetime).toLocalTime().toString(); - case 3: { - if (role == Qt::DisplayRole) - return Settings::getInstance()->getZECDisplayFormat(modeldata->at(index.row()).amount); - else { - return Settings::getInstance()->getUSDFormat(modeldata->at(index.row()).amount); - } - } + case 3: return Settings::getInstance()->getZECDisplayFormat(modeldata->at(index.row()).amount); } + } + + if (role == Qt::ToolTipRole) { + switch (index.column()) { + case 0: return modeldata->at(index.row()).type + + (dat.memo.isEmpty() ? "" : " tx memo: \"" + dat.memo + "\""); + case 1: { + auto addr = modeldata->at(index.row()).address; + if (addr.trimmed().isEmpty()) + return "(Shielded)"; + else + return addr; + } + case 2: return QDateTime::fromSecsSinceEpoch(modeldata->at(index.row()).datetime).toLocalTime().toString(); + case 3: return Settings::getInstance()->getUSDFormat(modeldata->at(index.row()).amount); + } } return QVariant();