Skip to content

Commit d69427a

Browse files
committed
Merge pull request #4092
40c5b93 [Qt] Optionally add third party links to transaction context menu (Cozz Lovan)
2 parents 191b087 + 40c5b93 commit d69427a

File tree

8 files changed

+87
-0
lines changed

8 files changed

+87
-0
lines changed

src/qt/forms/optionsdialog.ui

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,30 @@
471471
</property>
472472
</widget>
473473
</item>
474+
<item>
475+
<layout class="QHBoxLayout" name="horizontalLayout_3_Display">
476+
<item>
477+
<widget class="QLabel" name="thirdPartyTxUrlsLabel">
478+
<property name="toolTip">
479+
<string>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 |.</string>
480+
</property>
481+
<property name="text">
482+
<string>Third party transaction URLs</string>
483+
</property>
484+
<property name="buddy">
485+
<cstring>thirdPartyTxUrls</cstring>
486+
</property>
487+
</widget>
488+
</item>
489+
<item>
490+
<widget class="QLineEdit" name="thirdPartyTxUrls">
491+
<property name="toolTip">
492+
<string>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 |.</string>
493+
</property>
494+
</widget>
495+
</item>
496+
</layout>
497+
</item>
474498
<item>
475499
<spacer name="verticalSpacer_Display">
476500
<property name="orientation">

src/qt/optionsdialog.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) :
9696
#endif
9797
}
9898
}
99+
#if QT_VERSION >= 0x040700
100+
ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
101+
#endif
99102

100103
ui->unit->setModel(new BitcoinUnits(this));
101104
ui->transactionFee->setSingleStep(CTransaction::nMinTxFee);
@@ -151,6 +154,7 @@ void OptionsDialog::setModel(OptionsModel *model)
151154
connect(ui->connectSocks, SIGNAL(clicked(bool)), this, SLOT(showRestartWarning()));
152155
/* Display */
153156
connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
157+
connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this, SLOT(showRestartWarning()));
154158
}
155159

156160
void OptionsDialog::setMapper()
@@ -183,6 +187,7 @@ void OptionsDialog::setMapper()
183187
mapper->addMapping(ui->lang, OptionsModel::Language);
184188
mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
185189
mapper->addMapping(ui->displayAddresses, OptionsModel::DisplayAddresses);
190+
mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
186191
}
187192

188193
void OptionsDialog::enableOkButton()

src/qt/optionsmodel.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ void OptionsModel::Init()
6363
settings.setValue("bDisplayAddresses", false);
6464
bDisplayAddresses = settings.value("bDisplayAddresses", false).toBool();
6565

66+
if (!settings.contains("strThirdPartyTxUrls"))
67+
settings.setValue("strThirdPartyTxUrls", "");
68+
strThirdPartyTxUrls = settings.value("strThirdPartyTxUrls", "").toString();
69+
6670
if (!settings.contains("fCoinControlFeatures"))
6771
settings.setValue("fCoinControlFeatures", false);
6872
fCoinControlFeatures = settings.value("fCoinControlFeatures", false).toBool();
@@ -203,6 +207,8 @@ QVariant OptionsModel::data(const QModelIndex & index, int role) const
203207
return nDisplayUnit;
204208
case DisplayAddresses:
205209
return bDisplayAddresses;
210+
case ThirdPartyTxUrls:
211+
return strThirdPartyTxUrls;
206212
case Language:
207213
return settings.value("language");
208214
case CoinControlFeatures:
@@ -304,6 +310,13 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
304310
bDisplayAddresses = value.toBool();
305311
settings.setValue("bDisplayAddresses", bDisplayAddresses);
306312
break;
313+
case ThirdPartyTxUrls:
314+
if (strThirdPartyTxUrls != value.toString()) {
315+
strThirdPartyTxUrls = value.toString();
316+
settings.setValue("strThirdPartyTxUrls", strThirdPartyTxUrls);
317+
setRestartRequired(true);
318+
}
319+
break;
307320
case Language:
308321
if (settings.value("language") != value) {
309322
settings.setValue("language", value);

src/qt/optionsmodel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class OptionsModel : public QAbstractListModel
3636
Fee, // qint64
3737
DisplayUnit, // BitcoinUnits::Unit
3838
DisplayAddresses, // bool
39+
ThirdPartyTxUrls, // QString
3940
Language, // QString
4041
CoinControlFeatures, // bool
4142
ThreadsScriptVerif, // int
@@ -56,6 +57,7 @@ class OptionsModel : public QAbstractListModel
5657
bool getMinimizeOnClose() { return fMinimizeOnClose; }
5758
int getDisplayUnit() { return nDisplayUnit; }
5859
bool getDisplayAddresses() { return bDisplayAddresses; }
60+
QString getThirdPartyTxUrls() { return strThirdPartyTxUrls; }
5961
bool getProxySettings(QNetworkProxy& proxy) const;
6062
bool getCoinControlFeatures() { return fCoinControlFeatures; }
6163
const QString& getOverriddenByCommandLine() { return strOverriddenByCommandLine; }
@@ -71,6 +73,7 @@ class OptionsModel : public QAbstractListModel
7173
QString language;
7274
int nDisplayUnit;
7375
bool bDisplayAddresses;
76+
QString strThirdPartyTxUrls;
7477
bool fCoinControlFeatures;
7578
/* settings that were overriden by command-line */
7679
QString strOverriddenByCommandLine;

src/qt/transactiontablemodel.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,8 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
564564
return rec->credit + rec->debit;
565565
case TxIDRole:
566566
return rec->getTxID();
567+
case TxHashRole:
568+
return QString::fromStdString(rec->hash.ToString());
567569
case ConfirmedRole:
568570
return rec->status.countsForBalance;
569571
case FormattedAmountRole:

src/qt/transactiontablemodel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class TransactionTableModel : public QAbstractTableModel
5050
AmountRole,
5151
/** Unique identifier */
5252
TxIDRole,
53+
/** Transaction hash */
54+
TxHashRole,
5355
/** Is transaction confirmed? */
5456
ConfirmedRole,
5557
/** Formatted amount, without brackets when unconfirmed */

src/qt/transactionview.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <QComboBox>
2222
#include <QDateTimeEdit>
23+
#include <QDesktopServices>
2324
#include <QDoubleValidator>
2425
#include <QHBoxLayout>
2526
#include <QHeaderView>
@@ -28,7 +29,9 @@
2829
#include <QMenu>
2930
#include <QPoint>
3031
#include <QScrollBar>
32+
#include <QSignalMapper>
3133
#include <QTableView>
34+
#include <QUrl>
3235
#include <QVBoxLayout>
3336

3437
TransactionView::TransactionView(QWidget *parent) :
@@ -138,7 +141,11 @@ TransactionView::TransactionView(QWidget *parent) :
138141
contextMenu->addAction(editLabelAction);
139142
contextMenu->addAction(showDetailsAction);
140143

144+
mapperThirdPartyTxUrls = new QSignalMapper(this);
145+
141146
// Connect actions
147+
connect(mapperThirdPartyTxUrls, SIGNAL(mapped(QString)), this, SLOT(openThirdPartyTxUrl(QString)));
148+
142149
connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
143150
connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
144151
connect(addressWidget, SIGNAL(textChanged(QString)), this, SLOT(changedPrefix(QString)));
@@ -183,6 +190,25 @@ void TransactionView::setModel(WalletModel *model)
183190
transactionView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
184191

185192
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(transactionView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH);
193+
194+
if (model->getOptionsModel())
195+
{
196+
// Add third party transaction URLs to context menu
197+
QStringList listUrls = model->getOptionsModel()->getThirdPartyTxUrls().split("|", QString::SkipEmptyParts);
198+
for (int i = 0; i < listUrls.size(); ++i)
199+
{
200+
QString host = QUrl(listUrls[i].trimmed(), QUrl::StrictMode).host();
201+
if (!host.isEmpty())
202+
{
203+
QAction *thirdPartyTxUrlAction = new QAction(host, this); // use host as menu item label
204+
if (i == 0)
205+
contextMenu->addSeparator();
206+
contextMenu->addAction(thirdPartyTxUrlAction);
207+
connect(thirdPartyTxUrlAction, SIGNAL(triggered()), mapperThirdPartyTxUrls, SLOT(map()));
208+
mapperThirdPartyTxUrls->setMapping(thirdPartyTxUrlAction, listUrls[i].trimmed());
209+
}
210+
}
211+
}
186212
}
187213
}
188214

@@ -383,6 +409,15 @@ void TransactionView::showDetails()
383409
}
384410
}
385411

412+
void TransactionView::openThirdPartyTxUrl(QString url)
413+
{
414+
if(!transactionView || !transactionView->selectionModel())
415+
return;
416+
QModelIndexList selection = transactionView->selectionModel()->selectedRows(0);
417+
if(!selection.isEmpty())
418+
QDesktopServices::openUrl(QUrl::fromUserInput(url.replace("%s", selection.at(0).data(TransactionTableModel::TxHashRole).toString())));
419+
}
420+
386421
QWidget *TransactionView::createDateRangeWidget()
387422
{
388423
dateRangeWidget = new QFrame();

src/qt/transactionview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ class QFrame;
1919
class QLineEdit;
2020
class QMenu;
2121
class QModelIndex;
22+
class QSignalMapper;
2223
class QTableView;
2324
QT_END_NAMESPACE
2425

@@ -65,6 +66,7 @@ class TransactionView : public QWidget
6566
QLineEdit *amountWidget;
6667

6768
QMenu *contextMenu;
69+
QSignalMapper *mapperThirdPartyTxUrls;
6870

6971
QFrame *dateRangeWidget;
7072
QDateTimeEdit *dateFrom;
@@ -85,6 +87,7 @@ private slots:
8587
void copyLabel();
8688
void copyAmount();
8789
void copyTxID();
90+
void openThirdPartyTxUrl(QString url);
8891

8992
signals:
9093
void doubleClicked(const QModelIndex&);

0 commit comments

Comments
 (0)