diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui
index 9fbc86518..0103842e0 100644
--- a/src/qt/forms/optionsdialog.ui
+++ b/src/qt/forms/optionsdialog.ui
@@ -471,6 +471,30 @@
+ -
+
+
-
+
+
+ Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.
+
+
+ Third party transaction URLs
+
+
+ thirdPartyTxUrls
+
+
+
+ -
+
+
+ Third party URLs (e.g. a block explorer) that appear in the transactions tab as context menu items. %s in the URL is replaced by transaction hash. Multiple URLs are separated by vertical bar |.
+
+
+
+
+
-
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index 394b5f3ae..96464d2cc 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -96,6 +96,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
#endif
}
}
+#if QT_VERSION >= 0x040700
+ ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
+#endif
ui->unit->setModel(new BitcoinUnits(this));
ui->transactionFee->setSingleStep(CTransaction::nMinTxFee);
@@ -151,6 +154,7 @@ void OptionsDialog::setModel(OptionsModel *model)
connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
/* Display */
connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
+ connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning()));
}
void OptionsDialog::setMapper()
@@ -183,6 +187,7 @@ void OptionsDialog::setMapper()
mapper->addMapping(ui->lang, OptionsModel::Language);
mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
+ mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
}
void OptionsDialog::enableOkButton()
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 9abe9351b..74c6b10ce 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -63,6 +63,10 @@ void OptionsModel::Init()
settings.setValue("bDisplayAddresses", false);
bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool();
+ if (!settings.contains("strThirdPartyTxUrls"))
+ settings.setValue("strThirdPartyTxUrls", "");
+ strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
+
if (!settings.contains("fCoinControlFeatures"))
settings.setValue("fCoinControlFeatures", false);
fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();
@@ -203,6 +207,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
return nDisplayUnit;
case DisplayAddresses:
return bDisplayAddresses;
+ case ThirdPartyTxUrls:
+ return strThirdPartyTxUrls;
case Language:
return settings.value("language");
case CoinControlFeatures:
@@ -304,6 +310,13 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
bDisplayAddresses = value.toBool();
settings.setValue("bDisplayAddresses", bDisplayAddresses);
break;
+ case ThirdPartyTxUrls:
+ if (strThirdPartyTxUrls != value.toString()) {
+ strThirdPartyTxUrls = value.toString();
+ settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
+ setRestartRequired(true);
+ }
+ break;
case Language:
if (settings.value("language") != value) {
settings.setValue("language", value);
diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h
index ece5ef78a..f05e3e92d 100644
--- a/src/qt/optionsmodel.h
+++ b/src/qt/optionsmodel.h
@@ -36,6 +36,7 @@ public:
Fee, // qint64
DisplayUnit, // BitcoinUnits::Unit
DisplayAddresses, // bool
+ ThirdPartyTxUrls, // QString
Language, // QString
CoinControlFeatures, // bool
ThreadsScriptVerif, // int
@@ -56,6 +57,7 @@ public:
bool getMinimizeOnClose() { return fMinimizeOnClose; }
int getDisplayUnit() { return nDisplayUnit; }
bool getDisplayAddresses() { return bDisplayAddresses; }
+ QString getThirdPartyTxUrls() { return strThirdPartyTxUrls; }
bool getProxySettings(QNetworkProxy& proxy) const;
bool getCoinControlFeatures() { return fCoinControlFeatures; }
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
@@ -71,6 +73,7 @@ private:
QString language;
int nDisplayUnit;
bool bDisplayAddresses;
+ QString strThirdPartyTxUrls;
bool fCoinControlFeatures;
/* settings that were overriden by command-line */
QString strOverriddenByCommandLine;
diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp
index df412650d..8cf2b0a1b 100644
--- a/src/qt/transactiontablemodel.cpp
+++ b/src/qt/transactiontablemodel.cpp
@@ -564,6 +564,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
return rec->credit + rec->debit;
case TxIDRole:
return rec->getTxID();
+ case TxHashRole:
+ return QString::fromStdString(rec->hash.ToString());
case ConfirmedRole:
return rec->status.countsForBalance;
case FormattedAmountRole:
diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h
index 04b5291f4..333e6bc6e 100644
--- a/src/qt/transactiontablemodel.h
+++ b/src/qt/transactiontablemodel.h
@@ -50,6 +50,8 @@ public:
AmountRole,
/** Unique identifier */
TxIDRole,
+ /** Transaction hash */
+ TxHashRole,
/** Is transaction confirmed? */
ConfirmedRole,
/** Formatted amount, without brackets when unconfirmed */
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index a36315091..d4d29416c 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#include
#include
@@ -28,7 +29,9 @@
#include
#include
#include
+#include
#include
+#include
#include
TransactionView::TransactionView(QWidget *parent) :
@@ -138,7 +141,11 @@ TransactionView::TransactionView(QWidget *parent) :
contextMenu->addAction(editLabelAction);
contextMenu->addAction(showDetailsAction);
+ mapperThirdPartyTxUrls = new QSignalMapper(this);
+
// Connect actions
+ connect(mapperThirdPartyTxUrls, SIGNAL(mapped(QString)), this, SLOT(openThirdPartyTxUrl(QString)));
+
connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
@@ -183,6 +190,25 @@ void TransactionView::setModel(WalletModel *model)
transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
+
+ if (model->getOptionsModel())
+ {
+ // Add third party transaction URLs to context menu
+ QStringList listUrls = model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts);
+ for (int i = 0; i < listUrls.size(); ++i)
+ {
+ QString host = QUrl(listUrls[i].trimmed(), QUrl::StrictMode).host();
+ if (!host.isEmpty())
+ {
+ QAction *thirdPartyTxUrlAction = new QAction(host, this); // use host as menu item label
+ if (i == 0)
+ contextMenu->addSeparator();
+ contextMenu->addAction(thirdPartyTxUrlAction);
+ connect(thirdPartyTxUrlAction, SIGNAL(triggered()), mapperThirdPartyTxUrls, SLOT(map()));
+ mapperThirdPartyTxUrls->setMapping(thirdPartyTxUrlAction, listUrls[i].trimmed());
+ }
+ }
+ }
}
}
@@ -383,6 +409,15 @@ void TransactionView::showDetails()
}
}
+void TransactionView::openThirdPartyTxUrl(QString url)
+{
+ if(!transactionView || !transactionView->selectionModel())
+ return;
+ QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
+ if(!selection.isEmpty())
+ QDesktopServices::openUrl(QUrl::fromUserInput(url.replace("%s", selection.at(0).data(TransactionTableModel::TxHashRole).toString())));
+}
+
QWidget *TransactionView::createDateRangeWidget()
{
dateRangeWidget = new QFrame();
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index ef4f9d6f3..7a89fa11c 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -19,6 +19,7 @@ class QFrame;
class QLineEdit;
class QMenu;
class QModelIndex;
+class QSignalMapper;
class QTableView;
QT_END_NAMESPACE
@@ -65,6 +66,7 @@ private:
QLineEdit *amountWidget;
QMenu *contextMenu;
+ QSignalMapper *mapperThirdPartyTxUrls;
QFrame *dateRangeWidget;
QDateTimeEdit *dateFrom;
@@ -85,6 +87,7 @@ private slots:
void copyLabel();
void copyAmount();
void copyTxID();
+ void openThirdPartyTxUrl(QString url);
signals:
void doubleClicked(const QModelIndex&);