Browse Source

WIP: Added Keva page.

kevaview
Just Wonder 5 years ago
parent
commit
e2dc322939
  1. 3
      src/Makefile.qt.include
  2. 22
      src/qt/bitcoingui.cpp
  3. 5
      src/qt/bitcoingui.h
  4. 7
      src/qt/bitcoinstrings.cpp
  5. 623
      src/qt/kevaview.cpp
  6. 122
      src/qt/kevaview.h
  7. 175
      src/qt/locale/bitcoin_en.ts
  8. 1
      src/qt/test/wallettests.cpp
  9. 7
      src/qt/walletframe.cpp
  10. 2
      src/qt/walletframe.h
  11. 29
      src/qt/walletview.cpp
  12. 6
      src/qt/walletview.h

3
src/Makefile.qt.include

@ -184,6 +184,7 @@ QT_MOC_CPP = \
qt/moc_transactionfilterproxy.cpp \ qt/moc_transactionfilterproxy.cpp \
qt/moc_transactiontablemodel.cpp \ qt/moc_transactiontablemodel.cpp \
qt/moc_transactionview.cpp \ qt/moc_transactionview.cpp \
qt/moc_kevaview.cpp \
qt/moc_utilitydialog.cpp \ qt/moc_utilitydialog.cpp \
qt/moc_walletframe.cpp \ qt/moc_walletframe.cpp \
qt/moc_walletmodel.cpp \ qt/moc_walletmodel.cpp \
@ -258,6 +259,7 @@ BITCOIN_QT_H = \
qt/transactionrecord.h \ qt/transactionrecord.h \
qt/transactiontablemodel.h \ qt/transactiontablemodel.h \
qt/transactionview.h \ qt/transactionview.h \
qt/kevaview.h \
qt/utilitydialog.h \ qt/utilitydialog.h \
qt/walletframe.h \ qt/walletframe.h \
qt/walletmodel.h \ qt/walletmodel.h \
@ -372,6 +374,7 @@ BITCOIN_QT_WALLET_CPP = \
qt/transactionrecord.cpp \ qt/transactionrecord.cpp \
qt/transactiontablemodel.cpp \ qt/transactiontablemodel.cpp \
qt/transactionview.cpp \ qt/transactionview.cpp \
qt/kevaview.cpp \
qt/walletframe.cpp \ qt/walletframe.cpp \
qt/walletmodel.cpp \ qt/walletmodel.cpp \
qt/walletmodeltransaction.cpp \ qt/walletmodeltransaction.cpp \

22
src/qt/bitcoingui.cpp

@ -313,6 +313,13 @@ void BitcoinGUI::createActions()
historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4)); historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
tabGroup->addAction(historyAction); tabGroup->addAction(historyAction);
kevaAction = new QAction(platformStyle->SingleColorIcon(":/icons/key"), tr("&Keva"), this);
kevaAction->setStatusTip(tr("Keva related operations"));
kevaAction->setToolTip(kevaAction->statusTip());
kevaAction->setCheckable(true);
kevaAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
tabGroup->addAction(kevaAction);
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
// These showNormalIfMinimized are needed because Send Coins and Receive Coins // These showNormalIfMinimized are needed because Send Coins and Receive Coins
// can be triggered from the tray menu, and need to show the GUI to be useful. // can be triggered from the tray menu, and need to show the GUI to be useful.
@ -328,6 +335,8 @@ void BitcoinGUI::createActions()
connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage())); connect(receiveCoinsMenuAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized())); connect(historyAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage())); connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
connect(kevaAction, SIGNAL(triggered()), this, SLOT(showNormalIfMinimized()));
connect(kevaAction, SIGNAL(triggered()), this, SLOT(gotoKevaPage()));
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this); quitAction = new QAction(platformStyle->TextColorIcon(":/icons/quit"), tr("E&xit"), this);
@ -462,6 +471,7 @@ void BitcoinGUI::createToolBars()
toolbar->addAction(sendCoinsAction); toolbar->addAction(sendCoinsAction);
toolbar->addAction(receiveCoinsAction); toolbar->addAction(receiveCoinsAction);
toolbar->addAction(historyAction); toolbar->addAction(historyAction);
toolbar->addAction(kevaAction);
overviewAction->setChecked(true); overviewAction->setChecked(true);
} }
} }
@ -498,13 +508,13 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
} }
#endif // ENABLE_WALLET #endif // ENABLE_WALLET
unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel()); unitDisplayControl->setOptionsModel(_clientModel->getOptionsModel());
OptionsModel* optionsModel = _clientModel->getOptionsModel(); OptionsModel* optionsModel = _clientModel->getOptionsModel();
if(optionsModel) if(optionsModel)
{ {
// be aware of the tray icon disable state change reported by the OptionsModel object. // be aware of the tray icon disable state change reported by the OptionsModel object.
connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool))); connect(optionsModel,SIGNAL(hideTrayIconChanged(bool)),this,SLOT(setTrayIconVisible(bool)));
// initialize the disable state of the tray icon with the current value in the model. // initialize the disable state of the tray icon with the current value in the model.
setTrayIconVisible(optionsModel->getHideTrayIcon()); setTrayIconVisible(optionsModel->getHideTrayIcon());
} }
@ -691,6 +701,12 @@ void BitcoinGUI::gotoHistoryPage()
if (walletFrame) walletFrame->gotoHistoryPage(); if (walletFrame) walletFrame->gotoHistoryPage();
} }
void BitcoinGUI::gotoKevaPage()
{
kevaAction->setChecked(true);
if (walletFrame) walletFrame->gotoKevaPage();
}
void BitcoinGUI::gotoReceiveCoinsPage() void BitcoinGUI::gotoReceiveCoinsPage()
{ {
receiveCoinsAction->setChecked(true); receiveCoinsAction->setChecked(true);
@ -1052,7 +1068,7 @@ void BitcoinGUI::setHDStatus(int hdEnabled)
labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE)); labelWalletHDStatusIcon->setPixmap(platformStyle->SingleColorIcon(hdEnabled ? ":/icons/hd_enabled" : ":/icons/hd_disabled").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>")); labelWalletHDStatusIcon->setToolTip(hdEnabled ? tr("HD key generation is <b>enabled</b>") : tr("HD key generation is <b>disabled</b>"));
// eventually disable the QLabel to set its opacity to 50% // eventually disable the QLabel to set its opacity to 50%
labelWalletHDStatusIcon->setEnabled(hdEnabled); labelWalletHDStatusIcon->setEnabled(hdEnabled);
} }

5
src/qt/bitcoingui.h

@ -91,6 +91,7 @@ private:
QMenuBar *appMenuBar; QMenuBar *appMenuBar;
QAction *overviewAction; QAction *overviewAction;
QAction *kevaAction;
QAction *historyAction; QAction *historyAction;
QAction *quitAction; QAction *quitAction;
QAction *sendCoinsAction; QAction *sendCoinsAction;
@ -195,6 +196,8 @@ private Q_SLOTS:
void gotoOverviewPage(); void gotoOverviewPage();
/** Switch to history (transactions) page */ /** Switch to history (transactions) page */
void gotoHistoryPage(); void gotoHistoryPage();
/** Switch to Keva page */
void gotoKevaPage();
/** Switch to receive coins page */ /** Switch to receive coins page */
void gotoReceiveCoinsPage(); void gotoReceiveCoinsPage();
/** Switch to send coins page */ /** Switch to send coins page */
@ -233,7 +236,7 @@ private Q_SLOTS:
/** Show progress dialog e.g. for verifychain */ /** Show progress dialog e.g. for verifychain */
void showProgress(const QString &title, int nProgress); void showProgress(const QString &title, int nProgress);
/** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */ /** When hideTrayIcon setting is changed in OptionsModel hide or show the icon accordingly. */
void setTrayIconVisible(bool); void setTrayIconVisible(bool);

7
src/qt/bitcoinstrings.cpp

@ -9,7 +9,7 @@
#define UNUSED #define UNUSED
#endif #endif
static const char UNUSED *bitcoin_strings[] = { static const char UNUSED *bitcoin_strings[] = {
QT_TRANSLATE_NOOP("bitcoin-core", "Bitcoin Core"), QT_TRANSLATE_NOOP("bitcoin-core", "Kevacoin Core"),
QT_TRANSLATE_NOOP("bitcoin-core", "The %s developers"), QT_TRANSLATE_NOOP("bitcoin-core", "The %s developers"),
QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", ""
"(1 = keep tx meta data e.g. account owner and payment request information, 2 " "(1 = keep tx meta data e.g. account owner and payment request information, 2 "
@ -156,7 +156,7 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"and enables automatic pruning of old blocks if a target size in MiB is " "and enables automatic pruning of old blocks if a target size in MiB is "
"provided. This mode is incompatible with -txindex and -rescan. Warning: " "provided. This mode is incompatible with -txindex and -rescan. Warning: "
"Reverting this setting requires re-downloading the entire blockchain. " "Reverting this setting requires re-downloading the entire blockchain. "
"(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u " "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u "
"= automatically prune block files to stay under the specified target size in " "= automatically prune block files to stay under the specified target size in "
"MiB)"), "MiB)"),
QT_TRANSLATE_NOOP("bitcoin-core", "" QT_TRANSLATE_NOOP("bitcoin-core", ""
@ -320,6 +320,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Include IP addresses in debug output (default
QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"), QT_TRANSLATE_NOOP("bitcoin-core", "Incorrect or no genesis block found. Wrong datadir for network?"),
QT_TRANSLATE_NOOP("bitcoin-core", "Information"), QT_TRANSLATE_NOOP("bitcoin-core", "Information"),
QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. %s is shutting down."), QT_TRANSLATE_NOOP("bitcoin-core", "Initialization sanity check failed. %s is shutting down."),
QT_TRANSLATE_NOOP("bitcoin-core", "Input tx is not a keva operation"),
QT_TRANSLATE_NOOP("bitcoin-core", "Input tx is not mine"),
QT_TRANSLATE_NOOP("bitcoin-core", "Input tx not found in wallet"),
QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"), QT_TRANSLATE_NOOP("bitcoin-core", "Insufficient funds"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address or hostname: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -onion address or hostname: '%s'"),
QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address or hostname: '%s'"), QT_TRANSLATE_NOOP("bitcoin-core", "Invalid -proxy address or hostname: '%s'"),

623
src/qt/kevaview.cpp

@ -0,0 +1,623 @@
// Copyright (c) 2011-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/kevaview.h>
#include <qt/addresstablemodel.h>
#include <qt/bitcoinunits.h>
#include <qt/csvmodelwriter.h>
#include <qt/editaddressdialog.h>
#include <qt/optionsmodel.h>
#include <qt/platformstyle.h>
#include <qt/sendcoinsdialog.h>
#include <qt/transactiondescdialog.h>
#include <qt/transactionfilterproxy.h>
#include <qt/transactionrecord.h>
#include <qt/transactiontablemodel.h>
#include <qt/walletmodel.h>
#include <ui_interface.h>
#include <QComboBox>
#include <QDateTimeEdit>
#include <QDesktopServices>
#include <QDoubleValidator>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QPoint>
#include <QScrollBar>
#include <QSignalMapper>
#include <QTableView>
#include <QTimer>
#include <QUrl>
#include <QVBoxLayout>
KevaView::KevaView(const PlatformStyle *platformStyle, QWidget *parent) :
QWidget(parent), model(0), transactionProxyModel(0),
kevaView(0), abandonAction(0), bumpFeeAction(0), columnResizingFixer(0)
{
// Build filter row
setContentsMargins(0,0,0,0);
QHBoxLayout *hlayout = new QHBoxLayout();
hlayout->setContentsMargins(0,0,0,0);
if (platformStyle->getUseExtraSpacing()) {
hlayout->setSpacing(5);
hlayout->addSpacing(26);
} else {
hlayout->setSpacing(0);
hlayout->addSpacing(23);
}
watchOnlyWidget = new QComboBox(this);
watchOnlyWidget->setFixedWidth(24);
watchOnlyWidget->addItem("", TransactionFilterProxy::WatchOnlyFilter_All);
watchOnlyWidget->addItem(platformStyle->SingleColorIcon(":/icons/eye_plus"), "", TransactionFilterProxy::WatchOnlyFilter_Yes);
watchOnlyWidget->addItem(platformStyle->SingleColorIcon(":/icons/eye_minus"), "", TransactionFilterProxy::WatchOnlyFilter_No);
hlayout->addWidget(watchOnlyWidget);
dateWidget = new QComboBox(this);
if (platformStyle->getUseExtraSpacing()) {
dateWidget->setFixedWidth(121);
} else {
dateWidget->setFixedWidth(120);
}
dateWidget->addItem(tr("All"), All);
dateWidget->addItem(tr("Today"), Today);
dateWidget->addItem(tr("This week"), ThisWeek);
dateWidget->addItem(tr("This month"), ThisMonth);
dateWidget->addItem(tr("Last month"), LastMonth);
dateWidget->addItem(tr("This year"), ThisYear);
dateWidget->addItem(tr("Range..."), Range);
hlayout->addWidget(dateWidget);
typeWidget = new QComboBox(this);
if (platformStyle->getUseExtraSpacing()) {
typeWidget->setFixedWidth(121);
} else {
typeWidget->setFixedWidth(120);
}
typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
TransactionFilterProxy::TYPE(TransactionRecord::RecvFromOther));
typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
TransactionFilterProxy::TYPE(TransactionRecord::SendToOther));
typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
typeWidget->addItem(tr("Mined"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));
hlayout->addWidget(typeWidget);
search_widget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
search_widget->setPlaceholderText(tr("Enter address, transaction id, or label to search"));
#endif
hlayout->addWidget(search_widget);
amountWidget = new QLineEdit(this);
#if QT_VERSION >= 0x040700
amountWidget->setPlaceholderText(tr("Min amount"));
#endif
if (platformStyle->getUseExtraSpacing()) {
amountWidget->setFixedWidth(97);
} else {
amountWidget->setFixedWidth(100);
}
amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
hlayout->addWidget(amountWidget);
// Delay before filtering transactions in ms
static const int input_filter_delay = 200;
QTimer* amount_typing_delay = new QTimer(this);
amount_typing_delay->setSingleShot(true);
amount_typing_delay->setInterval(input_filter_delay);
QTimer* prefix_typing_delay = new QTimer(this);
prefix_typing_delay->setSingleShot(true);
prefix_typing_delay->setInterval(input_filter_delay);
QVBoxLayout *vlayout = new QVBoxLayout(this);
vlayout->setContentsMargins(0,0,0,0);
vlayout->setSpacing(0);
QTableView *view = new QTableView(this);
vlayout->addLayout(hlayout);
vlayout->addWidget(createDateRangeWidget());
vlayout->addWidget(view);
vlayout->setSpacing(0);
int width = view->verticalScrollBar()->sizeHint().width();
// Cover scroll bar width with spacing
if (platformStyle->getUseExtraSpacing()) {
hlayout->addSpacing(width+2);
} else {
hlayout->addSpacing(width);
}
// Always show scroll bar
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
view->setTabKeyNavigation(false);
view->setContextMenuPolicy(Qt::CustomContextMenu);
view->installEventFilter(this);
kevaView = view;
kevaView->setObjectName("KevaView");
// Actions
abandonAction = new QAction(tr("Abandon transaction"), this);
bumpFeeAction = new QAction(tr("Increase transaction fee"), this);
bumpFeeAction->setObjectName("bumpFeeAction");
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 *copyTxIDAction = new QAction(tr("Copy transaction ID"), this);
QAction *copyTxHexAction = new QAction(tr("Copy raw transaction"), this);
QAction *copyTxPlainText = new QAction(tr("Copy full transaction details"), this);
QAction *editLabelAction = new QAction(tr("Edit label"), this);
QAction *showDetailsAction = new QAction(tr("Show transaction details"), this);
contextMenu = new QMenu(this);
contextMenu->setObjectName("contextMenu");
contextMenu->addAction(copyAddressAction);
contextMenu->addAction(copyLabelAction);
contextMenu->addAction(copyAmountAction);
contextMenu->addAction(copyTxIDAction);
contextMenu->addAction(copyTxHexAction);
contextMenu->addAction(copyTxPlainText);
contextMenu->addAction(showDetailsAction);
contextMenu->addSeparator();
contextMenu->addAction(bumpFeeAction);
contextMenu->addAction(abandonAction);
contextMenu->addAction(editLabelAction);
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(watchOnlyWidget, SIGNAL(activated(int)), this, SLOT(chooseWatchonly(int)));
connect(amountWidget, SIGNAL(textChanged(QString)), amount_typing_delay, SLOT(start()));
connect(amount_typing_delay, SIGNAL(timeout()), this, SLOT(changedAmount()));
connect(search_widget, SIGNAL(textChanged(QString)), prefix_typing_delay, SLOT(start()));
connect(prefix_typing_delay, SIGNAL(timeout()), this, SLOT(changedSearch()));
connect(view, SIGNAL(doubleClicked(QModelIndex)), this, SIGNAL(doubleClicked(QModelIndex)));
connect(view, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
connect(bumpFeeAction, SIGNAL(triggered()), this, SLOT(bumpFee()));
connect(abandonAction, SIGNAL(triggered()), this, SLOT(abandonTx()));
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(copyAddress()));
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(copyLabel()));
connect(copyAmountAction, SIGNAL(triggered()), this, SLOT(copyAmount()));
connect(copyTxIDAction, SIGNAL(triggered()), this, SLOT(copyTxID()));
connect(copyTxHexAction, SIGNAL(triggered()), this, SLOT(copyTxHex()));
connect(copyTxPlainText, SIGNAL(triggered()), this, SLOT(copyTxPlainText()));
connect(editLabelAction, SIGNAL(triggered()), this, SLOT(editLabel()));
connect(showDetailsAction, SIGNAL(triggered()), this, SLOT(showDetails()));
}
void KevaView::setModel(WalletModel *_model)
{
this->model = _model;
if(_model)
{
transactionProxyModel = new TransactionFilterProxy(this);
transactionProxyModel->setSourceModel(_model->getTransactionTableModel());
transactionProxyModel->setDynamicSortFilter(true);
transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
transactionProxyModel->setSortRole(Qt::EditRole);
kevaView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
kevaView->setModel(transactionProxyModel);
kevaView->setAlternatingRowColors(true);
kevaView->setSelectionBehavior(QAbstractItemView::SelectRows);
kevaView->setSelectionMode(QAbstractItemView::ExtendedSelection);
kevaView->setSortingEnabled(true);
kevaView->sortByColumn(TransactionTableModel::Date, Qt::DescendingOrder);
kevaView->verticalHeader()->hide();
kevaView->setColumnWidth(TransactionTableModel::Status, STATUS_COLUMN_WIDTH);
kevaView->setColumnWidth(TransactionTableModel::Watchonly, WATCHONLY_COLUMN_WIDTH);
kevaView->setColumnWidth(TransactionTableModel::Date, DATE_COLUMN_WIDTH);
kevaView->setColumnWidth(TransactionTableModel::Type, TYPE_COLUMN_WIDTH);
kevaView->setColumnWidth(TransactionTableModel::Amount, AMOUNT_MINIMUM_COLUMN_WIDTH);
columnResizingFixer = new GUIUtil::TableViewLastColumnResizingFixer(kevaView, AMOUNT_MINIMUM_COLUMN_WIDTH, MINIMUM_COLUMN_WIDTH, this);
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());
}
}
}
// show/hide column Watch-only
updateWatchOnlyColumn(_model->haveWatchOnly());
// Watch-only signal
connect(_model, SIGNAL(notifyWatchonlyChanged(bool)), this, SLOT(updateWatchOnlyColumn(bool)));
}
}
void KevaView::chooseDate(int idx)
{
if(!transactionProxyModel)
return;
QDate current = QDate::currentDate();
dateRangeWidget->setVisible(false);
switch(dateWidget->itemData(idx).toInt())
{
case All:
transactionProxyModel->setDateRange(
TransactionFilterProxy::MIN_DATE,
TransactionFilterProxy::MAX_DATE);
break;
case Today:
transactionProxyModel->setDateRange(
QDateTime(current),
TransactionFilterProxy::MAX_DATE);
break;
case ThisWeek: {
// Find last Monday
QDate startOfWeek = current.addDays(-(current.dayOfWeek()-1));
transactionProxyModel->setDateRange(
QDateTime(startOfWeek),
TransactionFilterProxy::MAX_DATE);
} break;
case ThisMonth:
transactionProxyModel->setDateRange(
QDateTime(QDate(current.year(), current.month(), 1)),
TransactionFilterProxy::MAX_DATE);
break;
case LastMonth:
transactionProxyModel->setDateRange(
QDateTime(QDate(current.year(), current.month(), 1).addMonths(-1)),
QDateTime(QDate(current.year(), current.month(), 1)));
break;
case ThisYear:
transactionProxyModel->setDateRange(
QDateTime(QDate(current.year(), 1, 1)),
TransactionFilterProxy::MAX_DATE);
break;
case Range:
dateRangeWidget->setVisible(true);
dateRangeChanged();
break;
}
}
void KevaView::chooseType(int idx)
{
if(!transactionProxyModel)
return;
transactionProxyModel->setTypeFilter(
typeWidget->itemData(idx).toInt());
}
void KevaView::chooseWatchonly(int idx)
{
if(!transactionProxyModel)
return;
transactionProxyModel->setWatchOnlyFilter(
(TransactionFilterProxy::WatchOnlyFilter)watchOnlyWidget->itemData(idx).toInt());
}
void KevaView::changedSearch()
{
if(!transactionProxyModel)
return;
transactionProxyModel->setSearchString(search_widget->text());
}
void KevaView::changedAmount()
{
if(!transactionProxyModel)
return;
CAmount amount_parsed = 0;
if (BitcoinUnits::parse(model->getOptionsModel()->getDisplayUnit(), amountWidget->text(), &amount_parsed)) {
transactionProxyModel->setMinAmount(amount_parsed);
}
else
{
transactionProxyModel->setMinAmount(0);
}
}
void KevaView::exportClicked()
{
if (!model || !model->getOptionsModel()) {
return;
}
// CSV is currently the only supported format
QString filename = GUIUtil::getSaveFileName(this,
tr("Export Transaction History"), QString(),
tr("Comma separated file (*.csv)"), nullptr);
if (filename.isNull())
return;
CSVModelWriter writer(filename);
// name, column, role
writer.setModel(transactionProxyModel);
writer.addColumn(tr("Confirmed"), 0, TransactionTableModel::ConfirmedRole);
if (model->haveWatchOnly())
writer.addColumn(tr("Watch-only"), TransactionTableModel::Watchonly);
writer.addColumn(tr("Date"), 0, TransactionTableModel::DateRole);
writer.addColumn(tr("Type"), TransactionTableModel::Type, Qt::EditRole);
writer.addColumn(tr("Label"), 0, TransactionTableModel::LabelRole);
writer.addColumn(tr("Address"), 0, TransactionTableModel::AddressRole);
writer.addColumn(BitcoinUnits::getAmountColumnTitle(model->getOptionsModel()->getDisplayUnit()), 0, TransactionTableModel::FormattedAmountRole);
writer.addColumn(tr("ID"), 0, TransactionTableModel::TxIDRole);
if(!writer.write()) {
Q_EMIT message(tr("Exporting Failed"), tr("There was an error trying to save the transaction history to %1.").arg(filename),
CClientUIInterface::MSG_ERROR);
}
else {
Q_EMIT message(tr("Exporting Successful"), tr("The transaction history was successfully saved to %1.").arg(filename),
CClientUIInterface::MSG_INFORMATION);
}
}
void KevaView::contextualMenu(const QPoint &point)
{
QModelIndex index = kevaView->indexAt(point);
QModelIndexList selection = kevaView->selectionModel()->selectedRows(0);
if (selection.empty())
return;
// check if transaction can be abandoned, disable context menu action in case it doesn't
uint256 hash;
hash.SetHex(selection.at(0).data(TransactionTableModel::TxHashRole).toString().toStdString());
abandonAction->setEnabled(model->transactionCanBeAbandoned(hash));
bumpFeeAction->setEnabled(model->transactionCanBeBumped(hash));
if(index.isValid())
{
contextMenu->popup(kevaView->viewport()->mapToGlobal(point));
}
}
void KevaView::abandonTx()
{
if(!kevaView || !kevaView->selectionModel())
return;
QModelIndexList selection = kevaView->selectionModel()->selectedRows(0);
// get the hash from the TxHashRole (QVariant / QString)
uint256 hash;
QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
hash.SetHex(hashQStr.toStdString());
// Abandon the wallet transaction over the walletModel
model->abandonTransaction(hash);
// Update the table
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
}
void KevaView::bumpFee()
{
if(!kevaView || !kevaView->selectionModel())
return;
QModelIndexList selection = kevaView->selectionModel()->selectedRows(0);
// get the hash from the TxHashRole (QVariant / QString)
uint256 hash;
QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString();
hash.SetHex(hashQStr.toStdString());
// Bump tx fee over the walletModel
if (model->bumpFee(hash)) {
// Update the table
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, true);
}
}
void KevaView::copyAddress()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::AddressRole);
}
void KevaView::copyLabel()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::LabelRole);
}
void KevaView::copyAmount()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::FormattedAmountRole);
}
void KevaView::copyTxID()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::TxIDRole);
}
void KevaView::copyTxHex()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::TxHexRole);
}
void KevaView::copyTxPlainText()
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::TxPlainTextRole);
}
void KevaView::editLabel()
{
if(!kevaView->selectionModel() ||!model)
return;
QModelIndexList selection = kevaView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
AddressTableModel *addressBook = model->getAddressTableModel();
if(!addressBook)
return;
QString address = selection.at(0).data(TransactionTableModel::AddressRole).toString();
if(address.isEmpty())
{
// If this transaction has no associated address, exit
return;
}
// Is address in address book? Address book can miss address when a transaction is
// sent from outside the UI.
int idx = addressBook->lookupAddress(address);
if(idx != -1)
{
// Edit sending / receiving address
QModelIndex modelIdx = addressBook->index(idx, 0, QModelIndex());
// Determine type of address, launch appropriate editor dialog type
QString type = modelIdx.data(AddressTableModel::TypeRole).toString();
EditAddressDialog dlg(
type == AddressTableModel::Receive
? EditAddressDialog::EditReceivingAddress
: EditAddressDialog::EditSendingAddress, this);
dlg.setModel(addressBook);
dlg.loadRow(idx);
dlg.exec();
}
else
{
// Add sending address
EditAddressDialog dlg(EditAddressDialog::NewSendingAddress,
this);
dlg.setModel(addressBook);
dlg.setAddress(address);
dlg.exec();
}
}
}
void KevaView::showDetails()
{
if(!kevaView->selectionModel())
return;
QModelIndexList selection = kevaView->selectionModel()->selectedRows();
if(!selection.isEmpty())
{
TransactionDescDialog *dlg = new TransactionDescDialog(selection.at(0));
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->show();
}
}
void KevaView::openThirdPartyTxUrl(QString url)
{
if(!kevaView || !kevaView->selectionModel())
return;
QModelIndexList selection = kevaView->selectionModel()->selectedRows(0);
if(!selection.isEmpty())
QDesktopServices::openUrl(QUrl::fromUserInput(url.replace("%s", selection.at(0).data(TransactionTableModel::TxHashRole).toString())));
}
QWidget *KevaView::createDateRangeWidget()
{
dateRangeWidget = new QFrame();
dateRangeWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
dateRangeWidget->setContentsMargins(1,1,1,1);
QHBoxLayout *layout = new QHBoxLayout(dateRangeWidget);
layout->setContentsMargins(0,0,0,0);
layout->addSpacing(23);
layout->addWidget(new QLabel(tr("Range:")));
dateFrom = new QDateTimeEdit(this);
dateFrom->setDisplayFormat("dd/MM/yy");
dateFrom->setCalendarPopup(true);
dateFrom->setMinimumWidth(100);
dateFrom->setDate(QDate::currentDate().addDays(-7));
layout->addWidget(dateFrom);
layout->addWidget(new QLabel(tr("to")));
dateTo = new QDateTimeEdit(this);
dateTo->setDisplayFormat("dd/MM/yy");
dateTo->setCalendarPopup(true);
dateTo->setMinimumWidth(100);
dateTo->setDate(QDate::currentDate());
layout->addWidget(dateTo);
layout->addStretch();
// Hide by default
dateRangeWidget->setVisible(false);
// Notify on change
connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
connect(dateTo, SIGNAL(dateChanged(QDate)), this, SLOT(dateRangeChanged()));
return dateRangeWidget;
}
void KevaView::dateRangeChanged()
{
if(!transactionProxyModel)
return;
transactionProxyModel->setDateRange(
QDateTime(dateFrom->date()),
QDateTime(dateTo->date()).addDays(1));
}
void KevaView::focusTransaction(const QModelIndex &idx)
{
if(!transactionProxyModel)
return;
QModelIndex targetIdx = transactionProxyModel->mapFromSource(idx);
kevaView->scrollTo(targetIdx);
kevaView->setCurrentIndex(targetIdx);
kevaView->setFocus();
}
// We override the virtual resizeEvent of the QWidget to adjust tables column
// sizes as the tables width is proportional to the dialogs width.
void KevaView::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
columnResizingFixer->stretchColumnWidth(TransactionTableModel::ToAddress);
}
// Need to override default Ctrl+C action for amount as default behaviour is just to copy DisplayRole text
bool KevaView::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_C && ke->modifiers().testFlag(Qt::ControlModifier))
{
GUIUtil::copyEntryData(kevaView, 0, TransactionTableModel::TxPlainTextRole);
return true;
}
}
return QWidget::eventFilter(obj, event);
}
// show/hide column Watch-only
void KevaView::updateWatchOnlyColumn(bool fHaveWatchOnly)
{
watchOnlyWidget->setVisible(fHaveWatchOnly);
kevaView->setColumnHidden(TransactionTableModel::Watchonly, !fHaveWatchOnly);
}

122
src/qt/kevaview.h

@ -0,0 +1,122 @@
// Copyright (c) 2011-2017 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_QT_KevaView_H
#define BITCOIN_QT_KevaView_H
#include <qt/guiutil.h>
#include <QWidget>
#include <QKeyEvent>
class PlatformStyle;
class TransactionFilterProxy;
class WalletModel;
QT_BEGIN_NAMESPACE
class QComboBox;
class QDateTimeEdit;
class QFrame;
class QLineEdit;
class QMenu;
class QModelIndex;
class QSignalMapper;
class QTableView;
QT_END_NAMESPACE
/** Widget showing the transaction list for a wallet, including a filter row.
Using the filter row, the user can view or export a subset of the transactions.
*/
class KevaView : public QWidget
{
Q_OBJECT
public:
explicit KevaView(const PlatformStyle *platformStyle, QWidget *parent = 0);
void setModel(WalletModel *model);
// Date ranges for filter
enum DateEnum
{
All,
Today,
ThisWeek,
ThisMonth,
LastMonth,
ThisYear,
Range
};
enum ColumnWidths {
STATUS_COLUMN_WIDTH = 30,
WATCHONLY_COLUMN_WIDTH = 23,
DATE_COLUMN_WIDTH = 120,
TYPE_COLUMN_WIDTH = 113,
AMOUNT_MINIMUM_COLUMN_WIDTH = 120,
MINIMUM_COLUMN_WIDTH = 23
};
private:
WalletModel *model;
TransactionFilterProxy *transactionProxyModel;
QTableView *kevaView;
QComboBox *dateWidget;
QComboBox *typeWidget;
QComboBox *watchOnlyWidget;
QLineEdit *search_widget;
QLineEdit *amountWidget;
QMenu *contextMenu;
QSignalMapper *mapperThirdPartyTxUrls;
QFrame *dateRangeWidget;
QDateTimeEdit *dateFrom;
QDateTimeEdit *dateTo;
QAction *abandonAction;
QAction *bumpFeeAction;
QWidget *createDateRangeWidget();
GUIUtil::TableViewLastColumnResizingFixer *columnResizingFixer;
virtual void resizeEvent(QResizeEvent* event);
bool eventFilter(QObject *obj, QEvent *event);
private Q_SLOTS:
void contextualMenu(const QPoint &);
void dateRangeChanged();
void showDetails();
void copyAddress();
void editLabel();
void copyLabel();
void copyAmount();
void copyTxID();
void copyTxHex();
void copyTxPlainText();
void openThirdPartyTxUrl(QString url);
void updateWatchOnlyColumn(bool fHaveWatchOnly);
void abandonTx();
void bumpFee();
Q_SIGNALS:
void doubleClicked(const QModelIndex&);
/** Fired when a message should be reported to the user */
void message(const QString &title, const QString &message, unsigned int style);
public Q_SLOTS:
void chooseDate(int idx);
void chooseType(int idx);
void chooseWatchonly(int idx);
void changedAmount();
void changedSearch();
void exportClicked();
void focusTransaction(const QModelIndex&);
};
#endif // BITCOIN_QT_KevaView_H

175
src/qt/locale/bitcoin_en.ts

@ -85,7 +85,7 @@
</message> </message>
<message> <message>
<location line="+4"/> <location line="+4"/>
<source>These are your Kevacoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source> <source>These are your Kevaoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
@ -304,17 +304,17 @@
<context> <context>
<name>BitcoinGUI</name> <name>BitcoinGUI</name>
<message> <message>
<location filename="../bitcoingui.cpp" line="+358"/> <location filename="../bitcoingui.cpp" line="+365"/>
<source>Sign &amp;message...</source> <source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation> <translation>Sign &amp;message...</translation>
</message> </message>
<message> <message>
<location line="+430"/> <location line="+431"/>
<source>Synchronizing with network...</source> <source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation> <translation>Synchronizing with network...</translation>
</message> </message>
<message> <message>
<location line="-508"/> <location line="-516"/>
<source>&amp;Overview</source> <source>&amp;Overview</source>
<translation>&amp;Overview</translation> <translation>&amp;Overview</translation>
</message> </message>
@ -338,6 +338,16 @@
<source>Browse transaction history</source> <source>Browse transaction history</source>
<translation>Browse transaction history</translation> <translation>Browse transaction history</translation>
</message> </message>
<message>
<location line="+6"/>
<source>&amp;Keva</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>Keva related operations</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location line="+23"/> <location line="+23"/>
<source>E&amp;xit</source> <source>E&amp;xit</source>
@ -409,7 +419,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+360"/> <location line="+361"/>
<source>Click to disable network activity.</source> <source>Click to disable network activity.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -434,12 +444,12 @@
<translation>Reindexing blocks on disk...</translation> <translation>Reindexing blocks on disk...</translation>
</message> </message>
<message> <message>
<location line="-511"/> <location line="-519"/>
<source>Send coins to a Kevacoin address</source> <source>Send coins to a Kevacoin address</source>
<translation>Send coins to a Kevacoin address</translation> <translation>Send coins to a Kevacoin address</translation>
</message> </message>
<message> <message>
<location line="+67"/> <location line="+74"/>
<source>Backup wallet to another location</source> <source>Backup wallet to another location</source>
<translation>Backup wallet to another location</translation> <translation>Backup wallet to another location</translation>
</message> </message>
@ -464,12 +474,12 @@
<translation>&amp;Verify message...</translation> <translation>&amp;Verify message...</translation>
</message> </message>
<message> <message>
<location line="+517"/> <location line="+518"/>
<source>Kevacoin</source> <source>Kevacoin</source>
<translation>Kevacoin</translation> <translation>Kevacoin</translation>
</message> </message>
<message> <message>
<location line="-743"/> <location line="-751"/>
<source>Wallet</source> <source>Wallet</source>
<translation>Wallet</translation> <translation>Wallet</translation>
</message> </message>
@ -484,7 +494,7 @@
<translation>&amp;Receive</translation> <translation>&amp;Receive</translation>
</message> </message>
<message> <message>
<location line="+50"/> <location line="+57"/>
<source>&amp;Show / Hide</source> <source>&amp;Show / Hide</source>
<translation>&amp;Show / Hide</translation> <translation>&amp;Show / Hide</translation>
</message> </message>
@ -529,12 +539,12 @@
<translation>Tabs toolbar</translation> <translation>Tabs toolbar</translation>
</message> </message>
<message> <message>
<location line="-158"/> <location line="-165"/>
<source>Request payments (generates QR codes and kevacoin: URIs)</source> <source>Request payments (generates QR codes and kevacoin: URIs)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+70"/> <location line="+77"/>
<source>Show the list of used sending addresses and labels</source> <source>Show the list of used sending addresses and labels</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -554,7 +564,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location line="+357"/> <location line="+358"/>
<source>%n active connection(s) to Kevacoin network</source> <source>%n active connection(s) to Kevacoin network</source>
<translation> <translation>
<numerusform>%n active connection to Kevacoin network</numerusform> <numerusform>%n active connection to Kevacoin network</numerusform>
@ -615,12 +625,12 @@
<translation>Up to date</translation> <translation>Up to date</translation>
</message> </message>
<message> <message>
<location line="-441"/> <location line="-442"/>
<source>Show the %1 help message to get a list with possible Kevacoin command-line options</source> <source>Show the %1 help message to get a list with possible Kevacoin command-line options</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+200"/> <location line="+201"/>
<source>%1 client</source> <source>%1 client</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -635,7 +645,7 @@
<translation>Catching up...</translation> <translation>Catching up...</translation>
</message> </message>
<message> <message>
<location line="+150"/> <location line="+151"/>
<source>Date: %1 <source>Date: %1
</source> </source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -1671,7 +1681,7 @@
<context> <context>
<name>PaymentServer</name> <name>PaymentServer</name>
<message> <message>
<location filename="../paymentserver.cpp" line="+326"/> <location filename="../paymentserver.cpp" line="+327"/>
<location line="+214"/> <location line="+214"/>
<location line="+42"/> <location line="+42"/>
<location line="+111"/> <location line="+111"/>
@ -1950,7 +1960,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../bitcoin.cpp" line="+178"/> <location filename="../bitcoin.cpp" line="+171"/>
<source>%1 didn&apos;t yet exit safely...</source> <source>%1 didn&apos;t yet exit safely...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2623,7 +2633,7 @@
<name>SendCoinsDialog</name> <name>SendCoinsDialog</name>
<message> <message>
<location filename="../forms/sendcoinsdialog.ui" line="+14"/> <location filename="../forms/sendcoinsdialog.ui" line="+14"/>
<location filename="../sendcoinsdialog.cpp" line="+578"/> <location filename="../sendcoinsdialog.cpp" line="+588"/>
<source>Send Coins</source> <source>Send Coins</source>
<translation>Send Coins</translation> <translation>Send Coins</translation>
</message> </message>
@ -2754,7 +2764,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+185"/> <location line="+175"/>
<source>Send to multiple recipients at once</source> <source>Send to multiple recipients at once</source>
<translation>Send to multiple recipients at once</translation> <translation>Send to multiple recipients at once</translation>
</message> </message>
@ -2769,7 +2779,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-833"/> <location line="-823"/>
<source>Dust:</source> <source>Dust:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2779,17 +2789,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+74"/> <location line="+132"/>
<source>Enable Replace-By-Fee</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+3"/>
<source>With Replace-By-Fee (BIP-125) you can increase a transaction&apos;s fee after it is sent. Without this, a higher fee may be recommended to compensate for increased transaction delay risk.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+65"/>
<source>Clear &amp;All</source> <source>Clear &amp;All</source>
<translation>Clear &amp;All</translation> <translation>Clear &amp;All</translation>
</message> </message>
@ -2809,7 +2809,7 @@
<translation>S&amp;end</translation> <translation>S&amp;end</translation>
</message> </message>
<message> <message>
<location filename="../sendcoinsdialog.cpp" line="-494"/> <location filename="../sendcoinsdialog.cpp" line="-504"/>
<source>Copy quantity</source> <source>Copy quantity</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2849,7 +2849,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+127"/> <location line="+129"/>
<location line="+5"/> <location line="+5"/>
<location line="+5"/> <location line="+5"/>
<location line="+4"/> <location line="+4"/>
@ -2877,22 +2877,12 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+4"/> <location line="+13"/>
<source>You can increase the fee later (signals Replace-By-Fee, BIP-125).</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+2"/>
<source>Not signalling Replace-By-Fee, BIP-125.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+5"/>
<source>Confirm send coins</source> <source>Confirm send coins</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+192"/> <location line="+198"/>
<source>The recipient address is not valid. Please recheck.</source> <source>The recipient address is not valid. Please recheck.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -2942,7 +2932,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message numerus="yes"> <message numerus="yes">
<location line="+42"/> <location line="+43"/>
<source>Estimated to begin confirmation within %n block(s).</source> <source>Estimated to begin confirmation within %n block(s).</source>
<translation> <translation>
<numerusform>Estimated to begin confirmation within %n block.</numerusform> <numerusform>Estimated to begin confirmation within %n block.</numerusform>
@ -3329,11 +3319,6 @@
<source>conflicted with a transaction with %1 confirmations</source> <source>conflicted with a transaction with %1 confirmations</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location line="+2"/>
<source>%1/offline</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location line="+2"/> <location line="+2"/>
<source>0/unconfirmed, %1</source> <source>0/unconfirmed, %1</source>
@ -3370,20 +3355,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+5"/> <location line="+3"/>
<source>, has not been successfully broadcast yet</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location line="+2"/>
<source>, broadcast through %n node(s)</source>
<translation>
<numerusform>, broadcast through %n node</numerusform>
<numerusform>, broadcast through %n nodes</numerusform>
</translation>
</message>
<message>
<location line="+4"/>
<source>Date</source> <source>Date</source>
<translation type="unfinished">Date</translation> <translation type="unfinished">Date</translation>
</message> </message>
@ -3593,11 +3565,6 @@
<source>Open until %1</source> <source>Open until %1</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location line="+3"/>
<source>Offline</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location line="+3"/> <location line="+3"/>
<source>Unconfirmed</source> <source>Unconfirmed</source>
@ -3628,11 +3595,6 @@
<source>Immature (%1 confirmations, will be available after %2)</source> <source>Immature (%1 confirmations, will be available after %2)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location line="+3"/>
<source>This block was not received by any other nodes and will probably not be accepted!</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location line="+3"/> <location line="+3"/>
<source>Generated but not accepted</source> <source>Generated but not accepted</source>
@ -3674,7 +3636,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+213"/> <location line="+210"/>
<source>(no label)</source> <source>(no label)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -3927,7 +3889,7 @@
<context> <context>
<name>WalletModel</name> <name>WalletModel</name>
<message> <message>
<location filename="../walletmodel.cpp" line="+290"/> <location filename="../walletmodel.cpp" line="+291"/>
<source>Send Coins</source> <source>Send Coins</source>
<translation type="unfinished">Send Coins</translation> <translation type="unfinished">Send Coins</translation>
</message> </message>
@ -4025,7 +3987,7 @@
<context> <context>
<name>bitcoin-core</name> <name>bitcoin-core</name>
<message> <message>
<location filename="../bitcoinstrings.cpp" line="+349"/> <location filename="../bitcoinstrings.cpp" line="+352"/>
<source>Options:</source> <source>Options:</source>
<translation>Options:</translation> <translation>Options:</translation>
</message> </message>
@ -4035,17 +3997,17 @@
<translation>Specify data directory</translation> <translation>Specify data directory</translation>
</message> </message>
<message> <message>
<location line="-99"/> <location line="-102"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source> <source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation> <translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message> </message>
<message> <message>
<location line="+102"/> <location line="+105"/>
<source>Specify your own public address</source> <source>Specify your own public address</source>
<translation>Specify your own public address</translation> <translation>Specify your own public address</translation>
</message> </message>
<message> <message>
<location line="-116"/> <location line="-119"/>
<source>Accept command line and JSON-RPC commands</source> <source>Accept command line and JSON-RPC commands</source>
<translation>Accept command line and JSON-RPC commands</translation> <translation>Accept command line and JSON-RPC commands</translation>
</message> </message>
@ -4085,7 +4047,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+41"/> <location line="+44"/>
<source>Pruning blockstore...</source> <source>Pruning blockstore...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -4100,7 +4062,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-395"/> <location line="-398"/>
<source>Kevacoin Core</source> <source>Kevacoin Core</source>
<translation type="unfinished">Kevacoin Core</translation> <translation type="unfinished">Kevacoin Core</translation>
</message> </message>
@ -4200,12 +4162,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+6"/> <location line="+18"/>
<source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;%u = automatically prune block files to stay under the specified target size in MiB)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+12"/>
<source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source> <source>Set lowest fee rate (in %s/kB) for transactions to be included in block creation. (default: %s)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -4449,6 +4406,21 @@
<source>Initialization sanity check failed. %s is shutting down.</source> <source>Initialization sanity check failed. %s is shutting down.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location line="+1"/>
<source>Input tx is not a keva operation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>Input tx is not mine</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>Input tx not found in wallet</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location line="+4"/> <location line="+4"/>
<source>Invalid amount for -%s=&lt;amount&gt;: &apos;%s&apos;</source> <source>Invalid amount for -%s=&lt;amount&gt;: &apos;%s&apos;</source>
@ -4625,7 +4597,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-395"/> <location line="-398"/>
<source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source> <source>Allow JSON-RPC connections from specified source. Valid for &lt;ip&gt; are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -4740,7 +4712,7 @@
<translation>Information</translation> <translation>Information</translation>
</message> </message>
<message> <message>
<location line="+3"/> <location line="+6"/>
<source>Invalid -onion address or hostname: &apos;%s&apos;</source> <source>Invalid -onion address or hostname: &apos;%s&apos;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -4925,7 +4897,7 @@
<translation>Password for JSON-RPC connections</translation> <translation>Password for JSON-RPC connections</translation>
</message> </message>
<message> <message>
<location line="-261"/> <location line="-264"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source> <source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation> <translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message> </message>
@ -5000,7 +4972,12 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+37"/> <location line="+19"/>
<source>Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. Warning: Reverting this setting requires re-downloading the entire blockchain. (default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, &gt;=%u = automatically prune block files to stay under the specified target size in MiB)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+18"/>
<source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source> <source>Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -5115,7 +5092,7 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="+14"/> <location line="+17"/>
<source>Keypool ran out, please call keypoolrefill first</source> <source>Keypool ran out, please call keypoolrefill first</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -5260,17 +5237,17 @@
<translation>Loading wallet...</translation> <translation>Loading wallet...</translation>
</message> </message>
<message> <message>
<location line="-61"/> <location line="-64"/>
<source>Cannot downgrade wallet</source> <source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation> <translation>Cannot downgrade wallet</translation>
</message> </message>
<message> <message>
<location line="+87"/> <location line="+90"/>
<source>Rescanning...</source> <source>Rescanning...</source>
<translation>Rescanning...</translation> <translation>Rescanning...</translation>
</message> </message>
<message> <message>
<location line="-75"/> <location line="-78"/>
<source>Done loading</source> <source>Done loading</source>
<translation>Done loading</translation> <translation>Done loading</translation>
</message> </message>
@ -5280,4 +5257,4 @@
<translation>Error</translation> <translation>Error</translation>
</message> </message>
</context> </context>
</TS> </TS>

1
src/qt/test/wallettests.cpp

@ -9,6 +9,7 @@
#include <qt/sendcoinsentry.h> #include <qt/sendcoinsentry.h>
#include <qt/transactiontablemodel.h> #include <qt/transactiontablemodel.h>
#include <qt/transactionview.h> #include <qt/transactionview.h>
#include <qt/kevaview.h>
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <test/test_bitcoin.h> #include <test/test_bitcoin.h>
#include <validation.h> #include <validation.h>

7
src/qt/walletframe.cpp

@ -124,6 +124,13 @@ void WalletFrame::gotoHistoryPage()
i.value()->gotoHistoryPage(); i.value()->gotoHistoryPage();
} }
void WalletFrame::gotoKevaPage()
{
QMap<QString, WalletView*>::const_iterator i;
for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
i.value()->gotoKevaPage();
}
void WalletFrame::gotoReceiveCoinsPage() void WalletFrame::gotoReceiveCoinsPage()
{ {
QMap<QString, WalletView*>::const_iterator i; QMap<QString, WalletView*>::const_iterator i;

2
src/qt/walletframe.h

@ -66,6 +66,8 @@ public Q_SLOTS:
void gotoOverviewPage(); void gotoOverviewPage();
/** Switch to history (transactions) page */ /** Switch to history (transactions) page */
void gotoHistoryPage(); void gotoHistoryPage();
/** Switch to Keva page */
void gotoKevaPage();
/** Switch to receive coins page */ /** Switch to receive coins page */
void gotoReceiveCoinsPage(); void gotoReceiveCoinsPage();
/** Switch to send coins page */ /** Switch to send coins page */

29
src/qt/walletview.cpp

@ -17,6 +17,7 @@
#include <qt/signverifymessagedialog.h> #include <qt/signverifymessagedialog.h>
#include <qt/transactiontablemodel.h> #include <qt/transactiontablemodel.h>
#include <qt/transactionview.h> #include <qt/transactionview.h>
#include <qt/kevaview.h>
#include <qt/walletmodel.h> #include <qt/walletmodel.h>
#include <ui_interface.h> #include <ui_interface.h>
@ -53,6 +54,25 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
vbox->addLayout(hbox_buttons); vbox->addLayout(hbox_buttons);
transactionsPage->setLayout(vbox); transactionsPage->setLayout(vbox);
#if 1
{
kevaPage = new QWidget(this);
QVBoxLayout *vbox = new QVBoxLayout();
QHBoxLayout *hbox_buttons = new QHBoxLayout();
kevaView = new KevaView(platformStyle, this);
vbox->addWidget(kevaView);
QPushButton *exportButton = new QPushButton(tr("&Export"), this);
exportButton->setToolTip(tr("Export the data in the current tab to a file"));
if (platformStyle->getImagesOnButtons()) {
exportButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
}
hbox_buttons->addStretch();
hbox_buttons->addWidget(exportButton);
vbox->addLayout(hbox_buttons);
kevaPage->setLayout(vbox);
}
#endif
receiveCoinsPage = new ReceiveCoinsDialog(platformStyle); receiveCoinsPage = new ReceiveCoinsDialog(platformStyle);
sendCoinsPage = new SendCoinsDialog(platformStyle); sendCoinsPage = new SendCoinsDialog(platformStyle);
@ -61,6 +81,7 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent):
addWidget(overviewPage); addWidget(overviewPage);
addWidget(transactionsPage); addWidget(transactionsPage);
addWidget(kevaPage);
addWidget(receiveCoinsPage); addWidget(receiveCoinsPage);
addWidget(sendCoinsPage); addWidget(sendCoinsPage);
@ -100,7 +121,7 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
// Pass through transaction notifications // Pass through transaction notifications
connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString))); connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString,QString)));
// Connect HD enabled state signal // Connect HD enabled state signal
connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int))); connect(this, SIGNAL(hdEnabledStatusChanged(int)), gui, SLOT(setHDStatus(int)));
} }
} }
@ -119,6 +140,7 @@ void WalletView::setWalletModel(WalletModel *_walletModel)
// Put transaction list in tabs // Put transaction list in tabs
transactionView->setModel(_walletModel); transactionView->setModel(_walletModel);
kevaView->setModel(_walletModel);
overviewPage->setWalletModel(_walletModel); overviewPage->setWalletModel(_walletModel);
receiveCoinsPage->setModel(_walletModel); receiveCoinsPage->setModel(_walletModel);
sendCoinsPage->setModel(_walletModel); sendCoinsPage->setModel(_walletModel);
@ -179,6 +201,11 @@ void WalletView::gotoHistoryPage()
setCurrentWidget(transactionsPage); setCurrentWidget(transactionsPage);
} }
void WalletView::gotoKevaPage()
{
setCurrentWidget(kevaPage);
}
void WalletView::gotoReceiveCoinsPage() void WalletView::gotoReceiveCoinsPage()
{ {
setCurrentWidget(receiveCoinsPage); setCurrentWidget(receiveCoinsPage);

6
src/qt/walletview.h

@ -17,6 +17,7 @@ class ReceiveCoinsDialog;
class SendCoinsDialog; class SendCoinsDialog;
class SendCoinsRecipient; class SendCoinsRecipient;
class TransactionView; class TransactionView;
class KevaView;
class WalletModel; class WalletModel;
class AddressBookPage; class AddressBookPage;
@ -60,6 +61,7 @@ private:
OverviewPage *overviewPage; OverviewPage *overviewPage;
QWidget *transactionsPage; QWidget *transactionsPage;
QWidget *kevaPage;
ReceiveCoinsDialog *receiveCoinsPage; ReceiveCoinsDialog *receiveCoinsPage;
SendCoinsDialog *sendCoinsPage; SendCoinsDialog *sendCoinsPage;
AddressBookPage *usedSendingAddressesPage; AddressBookPage *usedSendingAddressesPage;
@ -67,6 +69,8 @@ private:
TransactionView *transactionView; TransactionView *transactionView;
KevaView *kevaView;
QProgressDialog *progressDialog; QProgressDialog *progressDialog;
const PlatformStyle *platformStyle; const PlatformStyle *platformStyle;
@ -75,6 +79,8 @@ public Q_SLOTS:
void gotoOverviewPage(); void gotoOverviewPage();
/** Switch to history (transactions) page */ /** Switch to history (transactions) page */
void gotoHistoryPage(); void gotoHistoryPage();
/** Switch to Keva page */
void gotoKevaPage();
/** Switch to receive coins page */ /** Switch to receive coins page */
void gotoReceiveCoinsPage(); void gotoReceiveCoinsPage();
/** Switch to send coins page */ /** Switch to send coins page */

Loading…
Cancel
Save