diff --git a/src/appcontext.cpp b/src/appcontext.cpp index 3deae3a..c496ae2 100644 --- a/src/appcontext.cpp +++ b/src/appcontext.cpp @@ -37,6 +37,7 @@ WalletKeysFilesModel *AppContext::wallets = nullptr; TxFiatHistory *AppContext::txFiatHistory = nullptr; double AppContext::balance = 0; QMap AppContext::txDescriptionCache; +QMap AppContext::txCache; AppContext::AppContext(QCommandLineParser *cmdargs) { this->network = new QNetworkAccessManager(); diff --git a/src/appcontext.h b/src/appcontext.h index a4002c6..79e2942 100644 --- a/src/appcontext.h +++ b/src/appcontext.h @@ -86,6 +86,7 @@ public: static WalletKeysFilesModel *wallets; static double balance; static QMap txDescriptionCache; + static QMap txCache; static TxFiatHistory *txFiatHistory; // libwalletqt @@ -172,7 +173,6 @@ signals: void setTitle(const QString &title); // set window title private: - void sorry(); const unsigned int m_donationBoundary = 15; UtilsNetworking *m_utilsNetworkingNodes; QTimer *m_storeTimer = new QTimer(this); diff --git a/src/dialog/broadcasttxdialog.cpp b/src/dialog/broadcasttxdialog.cpp index f6c5959..71f0f6a 100644 --- a/src/dialog/broadcasttxdialog.cpp +++ b/src/dialog/broadcasttxdialog.cpp @@ -3,10 +3,11 @@ #include "broadcasttxdialog.h" #include "ui_broadcasttxdialog.h" +#include "utils/nodes.h" #include -BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx) +BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex) : QDialog(parent) , m_ctx(ctx) , ui(new Ui::BroadcastTxDialog) @@ -23,6 +24,10 @@ BroadcastTxDialog::BroadcastTxDialog(QWidget *parent, AppContext *ctx) connect(m_rpc, &DaemonRpc::ApiResponse, this, &BroadcastTxDialog::onApiResponse); + if (!transactionHex.isEmpty()) { + ui->transaction->setPlainText(transactionHex); + } + this->adjustSize(); } @@ -33,7 +38,7 @@ void BroadcastTxDialog::broadcastTx() { QString node; if (ui->radio_useCustom->isChecked()) node = ui->customNode->text(); - else + else if (ui->radio_useDefault->isChecked()) node = m_ctx->nodes->connection().full; if (!node.startsWith("http://")) diff --git a/src/dialog/broadcasttxdialog.h b/src/dialog/broadcasttxdialog.h index 3c158cc..9917ed2 100644 --- a/src/dialog/broadcasttxdialog.h +++ b/src/dialog/broadcasttxdialog.h @@ -17,7 +17,7 @@ class BroadcastTxDialog : public QDialog Q_OBJECT public: - explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx); + explicit BroadcastTxDialog(QWidget *parent, AppContext *ctx, const QString &transactionHex = ""); ~BroadcastTxDialog() override; private slots: diff --git a/src/dialog/broadcasttxdialog.ui b/src/dialog/broadcasttxdialog.ui index af12c00..0be33f2 100644 --- a/src/dialog/broadcasttxdialog.ui +++ b/src/dialog/broadcasttxdialog.ui @@ -63,16 +63,6 @@ - - - - false - - - All transactions are broadcast over Tor - - - diff --git a/src/dialog/txconfdialog.cpp b/src/dialog/txconfdialog.cpp index 7bb9a11..a57e6b7 100644 --- a/src/dialog/txconfdialog.cpp +++ b/src/dialog/txconfdialog.cpp @@ -51,6 +51,7 @@ TxConfDialog::TxConfDialog(AppContext *ctx, PendingTransaction *tx, const QStrin connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::setShowAdvanced); + AppContext::txCache[tx->txid()[0]] = tx->signedTxToHex(0); this->adjustSize(); } diff --git a/src/historywidget.cpp b/src/historywidget.cpp index 489d759..db56de5 100644 --- a/src/historywidget.cpp +++ b/src/historywidget.cpp @@ -25,20 +25,9 @@ HistoryWidget::HistoryWidget(QWidget *parent) m_copyMenu->addAction("Transaction ID", this, [this]{copy(copyField::TxID);}); m_copyMenu->addAction("Date", this, [this]{copy(copyField::Date);}); m_copyMenu->addAction("Amount", this, [this]{copy(copyField::Amount);}); - auto spendProof = m_copyMenu->addAction("Spend proof", this, &HistoryWidget::getSpendProof); ui->history->setContextMenuPolicy(Qt::CustomContextMenu); - connect(ui->history, &QTreeView::customContextMenuRequested, [=](const QPoint & point){ - QModelIndex index = ui->history->indexAt(point); - if (index.isValid()) { - TransactionInfo::Direction direction; - m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction](TransactionInfo &tInfo) { - direction = tInfo.direction(); - }); - spendProof->setVisible(direction == TransactionInfo::Direction_Out); - m_contextMenu->exec(ui->history->viewport()->mapToGlobal(point)); - } - }); + connect(ui->history, &QTreeView::customContextMenuRequested, this, &HistoryWidget::showContextMenu); connect(ui->search, &QLineEdit::textChanged, this, &HistoryWidget::setSearchFilter); connect(ui->history, &QTreeView::doubleClicked, [this](QModelIndex index){ @@ -50,6 +39,43 @@ HistoryWidget::HistoryWidget(QWidget *parent) } +void HistoryWidget::showContextMenu(const QPoint &point) { + QModelIndex index = ui->history->indexAt(point); + if (!index.isValid()) { + return; + } + + QMenu menu(this); + TransactionInfo::Direction direction; + QString txid; + bool unconfirmed; + m_txHistory->transaction(m_model->mapToSource(index).row(), [&direction, &txid, &unconfirmed](TransactionInfo &tInfo) { + direction = tInfo.direction(); + txid = tInfo.hash(); + unconfirmed = tInfo.isFailed() || tInfo.isPending(); + }); + + if (AppContext::txCache.contains(txid) && unconfirmed) { + menu.addAction(QIcon(":/assets/images/info.png"), "Resend transaction", this, &HistoryWidget::onResendTransaction); + } + + menu.addMenu(m_copyMenu); + menu.addAction(QIcon(":/assets/images/info.png"), "Show details", this, &HistoryWidget::showTxDetails); + menu.addAction(QIcon(":/assets/images/network.png"), "View on block explorer", this, &HistoryWidget::onViewOnBlockExplorer); + + menu.exec(ui->history->viewport()->mapToGlobal(point)); +} + +void HistoryWidget::onResendTransaction() { + QModelIndex index = ui->history->currentIndex(); + QString txid; + m_txHistory->transaction(m_model->mapToSource(index).row(), [&txid](TransactionInfo &tInfo) { + txid = tInfo.hash(); + }); + + emit resendTransaction(txid); +} + void HistoryWidget::setModel(TransactionHistoryProxyModel *model, Wallet *wallet) { m_model = model; @@ -86,14 +112,6 @@ void HistoryWidget::onViewOnBlockExplorer() { emit viewOnBlockExplorer(txid); } -void HistoryWidget::getSpendProof() { - QModelIndex index = ui->history->currentIndex(); - - m_txHistory->transaction(m_model->mapToSource(index).row(), [this](TransactionInfo &tInfo) { - emit spendProof(tInfo.hash()); - }); -} - void HistoryWidget::setSearchText(const QString &text) { ui->search->setText(text); } diff --git a/src/historywidget.h b/src/historywidget.h index a6c8b00..b866454 100644 --- a/src/historywidget.h +++ b/src/historywidget.h @@ -29,14 +29,14 @@ public slots: void setSearchText(const QString &text); signals: - void spendProof(QString txid); void viewOnBlockExplorer(QString txid); + void resendTransaction(QString txid); private slots: void showTxDetails(); void onViewOnBlockExplorer(); - void getSpendProof(); void setSearchFilter(const QString &filter); + void onResendTransaction(); private: enum copyField { @@ -46,6 +46,7 @@ private: }; void copy(copyField field); + void showContextMenu(const QPoint &point); Ui::HistoryWidget *ui; QMenu *m_contextMenu; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4681e3f..9eb0f5c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -289,11 +289,8 @@ MainWindow::MainWindow(AppContext *ctx, QWidget *parent) : }); // History - connect(ui->historyWidget, &HistoryWidget::spendProof, [&](const QString &txid){ - TxProof txproof = m_ctx->currentWallet->getSpendProof(txid, ""); - Utils::copyToClipboard(txproof.proof); - }); connect(ui->historyWidget, &HistoryWidget::viewOnBlockExplorer, this, &MainWindow::onViewOnBlockExplorer); + connect(ui->historyWidget, &HistoryWidget::resendTransaction, this, &MainWindow::onResendTransaction); // Contacts connect(ui->contactWidget, &ContactsWidget::addContact, this, &MainWindow::onAddContact); @@ -1055,6 +1052,20 @@ void MainWindow::onViewOnBlockExplorer(const QString &txid) { Utils::externalLinkWarning(this, blockExplorerLink); } +void MainWindow::onResendTransaction(const QString &txid) { + if (!AppContext::txCache.contains(txid)) { + QMessageBox::warning(this, "Unable to resend transaction", "Transaction was not found in transaction cache. Unable to resend."); + return; + } + + // Connect to a different node so chances of successful relay are higher + m_ctx->nodes->autoConnect(true); + + auto dialog = new BroadcastTxDialog(this, m_ctx, AppContext::txCache[txid]); + dialog->exec(); + dialog->deleteLater(); +} + void MainWindow::onAddContact(const QString &address, const QString &name) { bool addressValid = WalletManager::addressValid(address, m_ctx->currentWallet->nettype()); if (!addressValid) diff --git a/src/mainwindow.h b/src/mainwindow.h index 77128b9..d6234be 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -117,6 +117,7 @@ public slots: void menuWalletOpenClicked(); void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path); void onViewOnBlockExplorer(const QString &txid); + void onResendTransaction(const QString &txid); void onAddContact(const QString &address, const QString &name); void importContacts(); void showRestoreHeightDialog();