From c75abc9f7e84dd16c9f748802fd82ab2c49ec558 Mon Sep 17 00:00:00 2001
From: "Wladimir J. van der Laan" <laanwj@gmail.com>
Date: Sat, 12 Nov 2011 12:20:34 +0100
Subject: [PATCH 1/4] Comments update

---
 src/qt/bitcoin.cpp         | 1 +
 src/qt/bitcoingui.cpp      | 1 -
 src/qt/transactionview.cpp | 1 -
 3 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index cba4e851b..894bbb9d1 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -114,6 +114,7 @@ std::string _(const char* psz)
 
 int main(int argc, char *argv[])
 {
+    // Internal string conversion is all UTF-8
     QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
     QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
 
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 1c4968336..d4ce8a79e 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -112,7 +112,6 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
 
     // Status bar notification icons
     QFrame *frameBlocks = new QFrame();
-    //frameBlocks->setFrameStyle(QFrame::Panel | QFrame::Sunken);
     frameBlocks->setContentsMargins(0,0,0,0);
     frameBlocks->setMinimumWidth(56);
     frameBlocks->setMaximumWidth(56);
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 2dcbf1ea8..0e1b22e01 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -100,7 +100,6 @@ TransactionView::TransactionView(QWidget *parent) :
     QVBoxLayout *vlayout = new QVBoxLayout(this);
     vlayout->setContentsMargins(0,0,0,0);
     vlayout->setSpacing(0);
-    //vlayout->addLayout(hlayout2);
 
     QTableView *view = new QTableView(this);
     vlayout->addLayout(hlayout);

From e0734571912736356839fde75fd10993b0df81d5 Mon Sep 17 00:00:00 2001
From: "Wladimir J. van der Laan" <laanwj@gmail.com>
Date: Fri, 11 Nov 2011 10:13:25 +0100
Subject: [PATCH 2/4] Move HtmlEscape (escape for qt rich text controls) to qt
 gui utilities

---
 src/qt/aboutdialog.cpp     |  1 -
 src/qt/guiutil.cpp         | 16 ++++++++++++++++
 src/qt/guiutil.h           |  4 ++++
 src/qt/transactiondesc.cpp | 38 +++++++++++---------------------------
 src/qt/transactiondesc.h   |  2 --
 5 files changed, 31 insertions(+), 30 deletions(-)

diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp
index a3aa6de84..08d777406 100644
--- a/src/qt/aboutdialog.cpp
+++ b/src/qt/aboutdialog.cpp
@@ -7,7 +7,6 @@ AboutDialog::AboutDialog(QWidget *parent) :
     ui(new Ui::AboutDialog)
 {
     ui->setupUi(this);
-
 }
 
 void AboutDialog::setModel(ClientModel *model)
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 158b84a28..f72fe1ef4 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -11,6 +11,7 @@
 #include <QFont>
 #include <QLineEdit>
 #include <QUrl>
+#include <QTextDocument> // For Qt::escape
 
 QString GUIUtil::dateTimeStr(qint64 nTime)
 {
@@ -72,3 +73,18 @@ bool GUIUtil::parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out)
     }
     return true;
 }
+
+QString GUIUtil::HtmlEscape(const QString& str, bool fMultiLine)
+{
+    QString escaped = Qt::escape(str);
+    if(fMultiLine)
+    {
+        escaped = escaped.replace("\n", "<br>\n");
+    }
+    return escaped;
+}
+
+QString GUIUtil::HtmlEscape(const std::string& str, bool fMultiLine)
+{
+    return HtmlEscape(QString::fromStdString(str), fMultiLine);
+}
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index 94e3314d1..acd327728 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -31,6 +31,10 @@ public:
     // Parse "bitcoin:" URL into recipient object, return true on succesful parsing
     // See Bitcoin URL definition discussion here: https://bitcointalk.org/index.php?topic=33490.0
     static bool parseBitcoinURL(const QUrl *url, SendCoinsRecipient *out);
+
+    // HTML escaping for rich text controls
+    static QString HtmlEscape(const QString& str, bool fMultiLine=false);
+    static QString HtmlEscape(const std::string& str, bool fMultiLine=false);
 };
 
 #endif // GUIUTIL_H
diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp
index 821ef9813..8de63c1de 100644
--- a/src/qt/transactiondesc.cpp
+++ b/src/qt/transactiondesc.cpp
@@ -7,25 +7,9 @@
 #include "qtui.h"
 
 #include <QString>
-#include <QTextDocument> // For Qt::escape
 
 using namespace std;
 
-QString TransactionDesc::HtmlEscape(const QString& str, bool fMultiLine)
-{
-    QString escaped = Qt::escape(str);
-    if(fMultiLine)
-    {
-        escaped = escaped.replace("\n", "<br>\n");
-    }
-    return escaped;
-}
-
-QString TransactionDesc::HtmlEscape(const std::string& str, bool fMultiLine)
-{
-    return HtmlEscape(QString::fromStdString(str), fMultiLine);
-}
-
 QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
 {
     if (!wtx.IsFinal())
@@ -86,7 +70,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
         {
             // Online transaction
             if (!wtx.mapValue["from"].empty())
-                strHTML += tr("<b>From:</b> ") + HtmlEscape(wtx.mapValue["from"]) + "<br>";
+                strHTML += tr("<b>From:</b> ") + GUIUtil::HtmlEscape(wtx.mapValue["from"]) + "<br>";
         }
         else
         {
@@ -105,9 +89,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
                             {
                                 strHTML += tr("<b>From:</b> ") + tr("unknown") + "<br>";
                                 strHTML += tr("<b>To:</b> ");
-                                strHTML += HtmlEscape(address.ToString());
+                                strHTML += GUIUtil::HtmlEscape(address.ToString());
                                 if (!wallet->mapAddressBook[address].empty())
-                                    strHTML += tr(" (yours, label: ") + HtmlEscape(wallet->mapAddressBook[address]) + ")";
+                                    strHTML += tr(" (yours, label: ") + GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + ")";
                                 else
                                     strHTML += tr(" (yours)");
                                 strHTML += "<br>";
@@ -129,8 +113,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
             strAddress = wtx.mapValue["to"];
             strHTML += tr("<b>To:</b> ");
             if (wallet->mapAddressBook.count(strAddress) && !wallet->mapAddressBook[strAddress].empty())
-                strHTML += HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
-            strHTML += HtmlEscape(strAddress) + "<br>";
+                strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[strAddress]) + " ";
+            strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>";
         }
 
         //
@@ -188,8 +172,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
                         {
                             strHTML += tr("<b>To:</b> ");
                             if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
-                                strHTML += HtmlEscape(wallet->mapAddressBook[address]) + " ";
-                            strHTML += HtmlEscape(address.ToString());
+                                strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
+                            strHTML += GUIUtil::HtmlEscape(address.ToString());
                             strHTML += "<br>";
                         }
                     }
@@ -230,9 +214,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
         // Message
         //
         if (!wtx.mapValue["message"].empty())
-            strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + HtmlEscape(wtx.mapValue["message"], true) + "<br>";
+            strHTML += QString("<br><b>") + tr("Message:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["message"], true) + "<br>";
         if (!wtx.mapValue["comment"].empty())
-            strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
+            strHTML += QString("<br><b>") + tr("Comment:") + "</b><br>" + GUIUtil::HtmlEscape(wtx.mapValue["comment"], true) + "<br>";
 
         if (wtx.IsCoinBase())
             strHTML += QString("<br>") + tr("Generated coins must wait 120 blocks before they can be spent.  When you generated this block, it was broadcast to the network to be added to the block chain.  If it fails to get into the chain, it will change to \"not accepted\" and not be spendable.  This may occasionally happen if another node generates a block within a few seconds of yours.") + "<br>";
@@ -251,7 +235,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
                     strHTML += "<b>Credit:</b> " + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,wallet->GetCredit(txout)) + "<br>";
 
             strHTML += "<br><b>Transaction:</b><br>";
-            strHTML += HtmlEscape(wtx.ToString(), true);
+            strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
 
             CTxDB txdb("r"); // To fetch source txouts
 
@@ -274,7 +258,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx)
                             if (ExtractAddress(vout.scriptPubKey, address))
                             {
                                 if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].empty())
-                                    strHTML += HtmlEscape(wallet->mapAddressBook[address]) + " ";
+                                    strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address]) + " ";
                                 strHTML += QString::fromStdString(address.ToString());
                             }
                             strHTML = strHTML + " Amount=" + BitcoinUnits::formatWithUnit(BitcoinUnits::BTC,vout.nValue);
diff --git a/src/qt/transactiondesc.h b/src/qt/transactiondesc.h
index 55b9eaf48..2523f9aa6 100644
--- a/src/qt/transactiondesc.h
+++ b/src/qt/transactiondesc.h
@@ -18,8 +18,6 @@ public:
 private:
     TransactionDesc() {}
 
-    static QString HtmlEscape(const QString& str, bool fMultiLine=false);
-    static QString HtmlEscape(const std::string &str, bool fMultiLine=false);
     static QString FormatTxStatus(const CWalletTx& wtx);
 };
 

From c4a4a4b886b3bd8933cf96c0d66d647a2b32a68b Mon Sep 17 00:00:00 2001
From: "Wladimir J. van der Laan" <laanwj@gmail.com>
Date: Sun, 4 Dec 2011 18:01:53 +0100
Subject: [PATCH 3/4] Add context menu for address book page (implements part 1
 of issue #648)

---
 src/qt/addressbookpage.cpp | 70 ++++++++++++++++++++++++++++++++------
 src/qt/addressbookpage.h   | 11 ++++++
 2 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/src/qt/addressbookpage.cpp b/src/qt/addressbookpage.cpp
index d207fe30f..91412fcc1 100644
--- a/src/qt/addressbookpage.cpp
+++ b/src/qt/addressbookpage.cpp
@@ -4,11 +4,13 @@
 #include "addresstablemodel.h"
 #include "editaddressdialog.h"
 #include "csvmodelwriter.h"
+#include "guiutil.h"
 
 #include <QSortFilterProxyModel>
 #include <QClipboard>
 #include <QFileDialog>
 #include <QMessageBox>
+#include <QMenu>
 
 #ifdef USE_QRCODE
 #include "qrcodedialog.h"
@@ -53,7 +55,28 @@ AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
         break;
     }
     ui->tableView->setTabKeyNavigation(false);
+    ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
 
+    // Context menu actions
+    QAction *copyAddressAction = new QAction(tr("Copy address"), this);
+    QAction *copyLabelAction = new QAction(tr("Copy label"), this);
+    QAction *editAction = new QAction(tr("Edit"), this);
+    deleteAction = new QAction(tr("Delete"), this);
+
+    contextMenu = new QMenu();
+    contextMenu->addAction(copyAddressAction);
+    contextMenu->addAction(copyLabelAction);
+    contextMenu->addAction(editAction);
+    contextMenu->addAction(deleteAction);
+
+    connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyToClipboard_clicked()));
+    connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
+    connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
+    connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteButton_clicked()));
+
+    connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
+
+    // Pass through accept action from button box
     connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
 }
 
@@ -108,18 +131,29 @@ void AddressBookPage::setModel(AddressTableModel *model)
 
 void AddressBookPage::on_copyToClipboard_clicked()
 {
-    // Copy currently selected address to clipboard
-    //   (or nothing, if nothing selected)
-    QTableView *table = ui->tableView;
-    if(!table->selectionModel())
-        return;
-    QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
+    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
+}
+void AddressBookPage::onCopyLabelAction()
+{
+    GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
+}
 
-    foreach (QModelIndex index, indexes)
-    {
-        QVariant address = index.data();
-        QApplication::clipboard()->setText(address.toString());
-    }
+void AddressBookPage::onEditAction()
+{
+    if(!ui->tableView->selectionModel())
+        return;
+    QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
+    if(indexes.isEmpty())
+        return;
+
+    EditAddressDialog dlg(
+            tab == SendingTab ?
+            EditAddressDialog::EditSendingAddress :
+            EditAddressDialog::EditReceivingAddress);
+    dlg.setModel(model);
+    QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
+    dlg.loadRow(origIndex.row());
+    dlg.exec();
 }
 
 void AddressBookPage::on_newAddressButton_clicked()
@@ -170,10 +204,14 @@ void AddressBookPage::selectionChanged()
         switch(tab)
         {
         case SendingTab:
+            // In sending tab, allow deletion of selection
             ui->deleteButton->setEnabled(true);
+            deleteAction->setEnabled(true);
             break;
         case ReceivingTab:
+            // Deleting receiving addresses, however, is not allowed
             ui->deleteButton->setEnabled(false);
+            deleteAction->setEnabled(false);
             break;
         }
         ui->copyToClipboard->setEnabled(true);
@@ -207,6 +245,7 @@ void AddressBookPage::done(int retval)
 
     if(returnValue.isEmpty())
     {
+        // If no address entry selected, return rejected
         retval = Rejected;
     }
 
@@ -257,3 +296,12 @@ void AddressBookPage::on_showQRCode_clicked()
     }
 #endif
 }
+
+void AddressBookPage::contextualMenu(const QPoint &point)
+{
+    QModelIndex index = ui->tableView->indexAt(point);
+    if(index.isValid())
+    {
+        contextMenu->exec(QCursor::pos());
+    }
+}
diff --git a/src/qt/addressbookpage.h b/src/qt/addressbookpage.h
index 2538f319d..6b08f8415 100644
--- a/src/qt/addressbookpage.h
+++ b/src/qt/addressbookpage.h
@@ -12,6 +12,7 @@ QT_BEGIN_NAMESPACE
 class QTableView;
 class QItemSelection;
 class QSortFilterProxyModel;
+class QMenu;
 QT_END_NAMESPACE
 
 /** Widget that shows a list of sending or receiving addresses.
@@ -48,13 +49,23 @@ private:
     Tabs tab;
     QString returnValue;
     QSortFilterProxyModel *proxyModel;
+    QMenu *contextMenu;
+    QAction *deleteAction;
 
 private slots:
     void on_deleteButton_clicked();
     void on_newAddressButton_clicked();
+    /** Copy address of currently selected address entry to clipboard */
     void on_copyToClipboard_clicked();
     void selectionChanged();
     void on_showQRCode_clicked();
+    /** Spawn contextual menu (right mouse menu) for address book entry */
+    void contextualMenu(const QPoint &point);
+
+    /** Copy label of currently selected address entry to clipboard */
+    void onCopyLabelAction();
+    /** Edit currently selected address entry */
+    void onEditAction();
 };
 
 #endif // ADDRESSBOOKDIALOG_H

From c58e7d4e013f21e38fb1501d896d32e8407a9c3c Mon Sep 17 00:00:00 2001
From: "Wladimir J. van der Laan" <laanwj@gmail.com>
Date: Sun, 4 Dec 2011 14:14:10 +0100
Subject: [PATCH 4/4] Copy amount to clipboard (implements #657) - Also, unify
 similar code related to copying transaction fields to clipboard

---
 src/qt/guiutil.cpp         | 16 ++++++++++++++++
 src/qt/guiutil.h           | 10 ++++++++++
 src/qt/transactionview.cpp | 31 ++++++++++++-------------------
 src/qt/transactionview.h   |  9 +++++----
 4 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index f72fe1ef4..22d9cc738 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -12,6 +12,9 @@
 #include <QLineEdit>
 #include <QUrl>
 #include <QTextDocument> // For Qt::escape
+#include <QAbstractItemView>
+#include <QApplication>
+#include <QClipboard>
 
 QString GUIUtil::dateTimeStr(qint64 nTime)
 {
@@ -88,3 +91,16 @@ QString GUIUtil::HtmlEscape(const std::string& str, bool fMultiLine)
 {
     return HtmlEscape(QString::fromStdString(str), fMultiLine);
 }
+
+void GUIUtil::copyEntryData(QAbstractItemView *view, int column, int role)
+{
+    if(!view || !view->selectionModel())
+        return;
+    QModelIndexList selection = view->selectionModel()->selectedRows(column);
+
+    if(!selection.isEmpty())
+    {
+        // Copy first item
+        QApplication::clipboard()->setText(selection.at(0).data(role).toString());
+    }
+}
diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h
index acd327728..3a81bd2f0 100644
--- a/src/qt/guiutil.h
+++ b/src/qt/guiutil.h
@@ -9,6 +9,7 @@ class QLineEdit;
 class QWidget;
 class QDateTime;
 class QUrl;
+class QAbstractItemView;
 QT_END_NAMESPACE
 class SendCoinsRecipient;
 
@@ -35,6 +36,15 @@ public:
     // HTML escaping for rich text controls
     static QString HtmlEscape(const QString& str, bool fMultiLine=false);
     static QString HtmlEscape(const std::string& str, bool fMultiLine=false);
+
+    /** Copy a field of the currently selected entry of a view to the clipboard. Does nothing if nothing
+        is selected.
+       @param[in] column  Data column to extract from the model
+       @param[in] role    Data role to extract from the model
+       @see  TransactionView::copyLabel, TransactionView::copyAmount, TransactionView::copyAddress
+     */
+    static void copyEntryData(QAbstractItemView *view, int column, int role=Qt::EditRole);
+
 };
 
 #endif // GUIUTIL_H
diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp
index 0e1b22e01..cba06298d 100644
--- a/src/qt/transactionview.cpp
+++ b/src/qt/transactionview.cpp
@@ -10,6 +10,7 @@
 #include "transactiondescdialog.h"
 #include "editaddressdialog.h"
 #include "optionsmodel.h"
+#include "guiutil.h"
 
 #include <QScrollBar>
 #include <QComboBox>
@@ -123,12 +124,14 @@ TransactionView::TransactionView(QWidget *parent) :
     // Actions
     QAction *copyAddressAction = new QAction(tr("Copy address"), this);
     QAction *copyLabelAction = new QAction(tr("Copy label"), this);
+    QAction *copyAmountAction = new QAction(tr("Copy amount"), this);
     QAction *editLabelAction = new QAction(tr("Edit label"), this);
     QAction *showDetailsAction = new QAction(tr("Show details..."), this);
 
     contextMenu = new QMenu();
     contextMenu->addAction(copyAddressAction);
     contextMenu->addAction(copyLabelAction);
+    contextMenu->addAction(copyAmountAction);
     contextMenu->addAction(editLabelAction);
     contextMenu->addAction(showDetailsAction);
 
@@ -139,14 +142,11 @@ TransactionView::TransactionView(QWidget *parent) :
     connect(amountWidget, SIGNAL(textChanged(QString)), this, SLOT(changedAmount(QString)));
 
     connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
-
-    connect(view,
-            SIGNAL(customContextMenuRequested(QPoint)),
-            this,
-            SLOT(contextualMenu(QPoint)));
+    connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
 
     connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
     connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
+    connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
     connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
     connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
 }
@@ -302,24 +302,17 @@ void TransactionView::contextualMenu(const QPoint &point)
 
 void TransactionView::copyAddress()
 {
-    if(!transactionView->selectionModel())
-        return;
-    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
-    if(!selection.isEmpty())
-    {
-        QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::AddressRole).toString());
-    }
+    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole);
 }
 
 void TransactionView::copyLabel()
 {
-    if(!transactionView->selectionModel())
-        return;
-    QModelIndexList selection = transactionView->selectionModel()->selectedRows();
-    if(!selection.isEmpty())
-    {
-        QApplication::clipboard()->setText(selection.at(0).data(TransactionTableModel::LabelRole).toString());
-    }
+    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::LabelRole);
+}
+
+void TransactionView::copyAmount()
+{
+    GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::FormattedAmountRole);
 }
 
 void TransactionView::editLabel()
diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h
index 67d0b46f3..bc6e1e4e0 100644
--- a/src/qt/transactionview.h
+++ b/src/qt/transactionview.h
@@ -60,6 +60,11 @@ private:
 private slots:
     void contextualMenu(const QPoint &);
     void dateRangeChanged();
+    void showDetails();
+    void copyAddress();
+    void editLabel();
+    void copyLabel();
+    void copyAmount();
 
 signals:
     void doubleClicked(const QModelIndex&);
@@ -70,10 +75,6 @@ public slots:
     void changedPrefix(const QString &prefix);
     void changedAmount(const QString &amount);
     void exportClicked();
-    void showDetails();
-    void copyAddress();
-    void editLabel();
-    void copyLabel();
 
 };