mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-11 15:48:05 +00:00
Merge pull request #683 from laanwj/ui_copy_amount
Context menu updates for TransactionView and AddressTablePage
This commit is contained in:
commit
3a6ede13f8
@ -7,7 +7,6 @@ AboutDialog::AboutDialog(QWidget *parent) :
|
||||
ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
void AboutDialog::setModel(ClientModel *model)
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include <QFont>
|
||||
#include <QLineEdit>
|
||||
#include <QUrl>
|
||||
#include <QTextDocument> // For Qt::escape
|
||||
#include <QAbstractItemView>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
|
||||
QString GUIUtil::dateTimeStr(qint64 nTime)
|
||||
{
|
||||
@ -72,3 +76,31 @@ 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);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ class QLineEdit;
|
||||
class QWidget;
|
||||
class QDateTime;
|
||||
class QUrl;
|
||||
class QAbstractItemView;
|
||||
QT_END_NAMESPACE
|
||||
class SendCoinsRecipient;
|
||||
|
||||
@ -31,6 +32,19 @@ 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);
|
||||
|
||||
/** 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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "transactiondescdialog.h"
|
||||
#include "editaddressdialog.h"
|
||||
#include "optionsmodel.h"
|
||||
#include "guiutil.h"
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QComboBox>
|
||||
@ -100,7 +101,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);
|
||||
@ -124,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);
|
||||
|
||||
@ -140,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()));
|
||||
}
|
||||
@ -303,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()
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user