mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 10:38:42 +01:00
Implement filter row instead of tabs, allows for more expressive filters
This commit is contained in:
parent
19a5975d5a
commit
ceb6d4e11d
@ -72,7 +72,9 @@ HEADERS += src/qt/bitcoingui.h \
|
|||||||
src/qt/transactiondescdialog.h \
|
src/qt/transactiondescdialog.h \
|
||||||
src/qt/bitcoinamountfield.h \
|
src/qt/bitcoinamountfield.h \
|
||||||
src/wallet.h \
|
src/wallet.h \
|
||||||
src/keystore.h
|
src/keystore.h \
|
||||||
|
src/qt/transactionfilterproxy.h \
|
||||||
|
src/qt/transactionview.h
|
||||||
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
||||||
src/qt/transactiontablemodel.cpp \
|
src/qt/transactiontablemodel.cpp \
|
||||||
src/qt/addresstablemodel.cpp \
|
src/qt/addresstablemodel.cpp \
|
||||||
@ -105,7 +107,9 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \
|
|||||||
src/qt/bitcoinstrings.cpp \
|
src/qt/bitcoinstrings.cpp \
|
||||||
src/qt/bitcoinamountfield.cpp \
|
src/qt/bitcoinamountfield.cpp \
|
||||||
src/wallet.cpp \
|
src/wallet.cpp \
|
||||||
src/keystore.cpp
|
src/keystore.cpp \
|
||||||
|
src/qt/transactionfilterproxy.cpp \
|
||||||
|
src/qt/transactionview.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
src/qt/bitcoin.qrc
|
src/qt/bitcoin.qrc
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "optionsmodel.h"
|
#include "optionsmodel.h"
|
||||||
#include "transactiondescdialog.h"
|
#include "transactiondescdialog.h"
|
||||||
#include "addresstablemodel.h"
|
#include "addresstablemodel.h"
|
||||||
|
#include "transactionview.h"
|
||||||
|
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
|
|
||||||
@ -29,12 +30,9 @@
|
|||||||
#include <QToolBar>
|
#include <QToolBar>
|
||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QTableView>
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QHeaderView>
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QSortFilterProxyModel>
|
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProgressBar>
|
#include <QProgressBar>
|
||||||
@ -104,7 +102,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
|
|||||||
vbox->addLayout(hbox_address);
|
vbox->addLayout(hbox_address);
|
||||||
vbox->addLayout(hbox_balance);
|
vbox->addLayout(hbox_balance);
|
||||||
|
|
||||||
vbox->addWidget(createTabs());
|
transactionView = new TransactionView(this);
|
||||||
|
connect(transactionView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(transactionDetails(const QModelIndex&)));
|
||||||
|
vbox->addWidget(transactionView);
|
||||||
|
|
||||||
QWidget *centralwidget = new QWidget(this);
|
QWidget *centralwidget = new QWidget(this);
|
||||||
centralwidget->setLayout(vbox);
|
centralwidget->setLayout(vbox);
|
||||||
@ -198,7 +198,11 @@ void BitcoinGUI::setModel(ClientModel *model)
|
|||||||
connect(model, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
|
connect(model, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString)));
|
||||||
|
|
||||||
// Put transaction list in tabs
|
// Put transaction list in tabs
|
||||||
setTabsModel(model->getTransactionTableModel());
|
transactionView->setModel(model->getTransactionTableModel());
|
||||||
|
|
||||||
|
// Balloon popup for new transaction
|
||||||
|
connect(model->getTransactionTableModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
||||||
|
this, SLOT(incomingTransaction(const QModelIndex &, int, int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitcoinGUI::createTrayIcon()
|
void BitcoinGUI::createTrayIcon()
|
||||||
@ -227,69 +231,6 @@ void BitcoinGUI::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *BitcoinGUI::createTabs()
|
|
||||||
{
|
|
||||||
QStringList tab_labels;
|
|
||||||
tab_labels << tr("All transactions")
|
|
||||||
<< tr("Sent/Received")
|
|
||||||
<< tr("Sent")
|
|
||||||
<< tr("Received");
|
|
||||||
|
|
||||||
QTabWidget *tabs = new QTabWidget(this);
|
|
||||||
for(int i = 0; i < tab_labels.size(); ++i)
|
|
||||||
{
|
|
||||||
QTableView *view = new QTableView(this);
|
|
||||||
tabs->addTab(view, tab_labels.at(i));
|
|
||||||
|
|
||||||
connect(view, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(transactionDetails(const QModelIndex&)));
|
|
||||||
transactionViews.append(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tabs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitcoinGUI::setTabsModel(QAbstractItemModel *transaction_model)
|
|
||||||
{
|
|
||||||
QStringList tab_filters;
|
|
||||||
tab_filters << "^."
|
|
||||||
<< "^["+TransactionTableModel::Sent+TransactionTableModel::Received+"]"
|
|
||||||
<< "^["+TransactionTableModel::Sent+"]"
|
|
||||||
<< "^["+TransactionTableModel::Received+"]";
|
|
||||||
|
|
||||||
for(int i = 0; i < transactionViews.size(); ++i)
|
|
||||||
{
|
|
||||||
QSortFilterProxyModel *proxy_model = new QSortFilterProxyModel(this);
|
|
||||||
proxy_model->setSourceModel(transaction_model);
|
|
||||||
proxy_model->setDynamicSortFilter(true);
|
|
||||||
proxy_model->setFilterRole(TransactionTableModel::TypeRole);
|
|
||||||
proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i)));
|
|
||||||
proxy_model->setSortRole(Qt::EditRole);
|
|
||||||
|
|
||||||
QTableView *transaction_table = transactionViews.at(i);
|
|
||||||
transaction_table->setModel(proxy_model);
|
|
||||||
transaction_table->setAlternatingRowColors(true);
|
|
||||||
transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
||||||
transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
|
||||||
transaction_table->setSortingEnabled(true);
|
|
||||||
transaction_table->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
|
|
||||||
transaction_table->verticalHeader()->hide();
|
|
||||||
|
|
||||||
transaction_table->horizontalHeader()->resizeSection(
|
|
||||||
TransactionTableModel::Status, 23);
|
|
||||||
transaction_table->horizontalHeader()->resizeSection(
|
|
||||||
TransactionTableModel::Date, 120);
|
|
||||||
transaction_table->horizontalHeader()->resizeSection(
|
|
||||||
TransactionTableModel::Type, 120);
|
|
||||||
transaction_table->horizontalHeader()->setResizeMode(
|
|
||||||
TransactionTableModel::ToAddress, QHeaderView::Stretch);
|
|
||||||
transaction_table->horizontalHeader()->resizeSection(
|
|
||||||
TransactionTableModel::Amount, 79);
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(transaction_model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
|
||||||
this, SLOT(incomingTransaction(const QModelIndex &, int, int)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void BitcoinGUI::sendcoinsClicked()
|
void BitcoinGUI::sendcoinsClicked()
|
||||||
{
|
{
|
||||||
SendCoinsDialog dlg;
|
SendCoinsDialog dlg;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
class TransactionTableModel;
|
class TransactionTableModel;
|
||||||
class ClientModel;
|
class ClientModel;
|
||||||
|
class TransactionView;
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QLabel;
|
class QLabel;
|
||||||
@ -56,12 +57,11 @@ private:
|
|||||||
QAction *openBitcoin;
|
QAction *openBitcoin;
|
||||||
|
|
||||||
QSystemTrayIcon *trayIcon;
|
QSystemTrayIcon *trayIcon;
|
||||||
QList<QTableView *> transactionViews;
|
TransactionView *transactionView;
|
||||||
|
|
||||||
void createActions();
|
void createActions();
|
||||||
QWidget *createTabs();
|
QWidget *createTabs();
|
||||||
void createTrayIcon();
|
void createTrayIcon();
|
||||||
void setTabsModel(QAbstractItemModel *transaction_model);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setBalance(qint64 balance);
|
void setBalance(qint64 balance);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "guiutil.h"
|
#include "guiutil.h"
|
||||||
#include "bitcoinaddressvalidator.h"
|
#include "bitcoinaddressvalidator.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@ -36,3 +37,12 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent)
|
|||||||
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
widget->setAlignment(Qt::AlignRight|Qt::AlignVCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GUIUtil::parseMoney(const QString &amount, qint64 *val_out)
|
||||||
|
{
|
||||||
|
return ParseMoney(amount.toStdString(), *val_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GUIUtil::formatMoney(qint64 amount, bool plussign)
|
||||||
|
{
|
||||||
|
return QString::fromStdString(FormatMoney(amount, plussign));
|
||||||
|
}
|
||||||
|
@ -14,12 +14,18 @@ class GUIUtil
|
|||||||
public:
|
public:
|
||||||
static QString DateTimeStr(qint64 nTime);
|
static QString DateTimeStr(qint64 nTime);
|
||||||
|
|
||||||
/* Render bitcoin addresses in monospace font */
|
// Render bitcoin addresses in monospace font
|
||||||
static QFont bitcoinAddressFont();
|
static QFont bitcoinAddressFont();
|
||||||
|
|
||||||
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
static void setupAddressWidget(QLineEdit *widget, QWidget *parent);
|
||||||
|
|
||||||
static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
static void setupAmountWidget(QLineEdit *widget, QWidget *parent);
|
||||||
|
|
||||||
|
// Convenience wrapper around ParseMoney that takes QString
|
||||||
|
static bool parseMoney(const QString &amount, qint64 *val_out);
|
||||||
|
|
||||||
|
// Convenience wrapper around FormatMoney that returns QString
|
||||||
|
static QString formatMoney(qint64 amount, bool plussign=false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GUIUTIL_H
|
#endif // GUIUTIL_H
|
||||||
|
@ -12,9 +12,6 @@
|
|||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "util.h"
|
|
||||||
#include "base58.h"
|
|
||||||
|
|
||||||
SendCoinsDialog::SendCoinsDialog(QWidget *parent, const QString &address) :
|
SendCoinsDialog::SendCoinsDialog(QWidget *parent, const QString &address) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
ui(new Ui::SendCoinsDialog),
|
ui(new Ui::SendCoinsDialog),
|
||||||
@ -49,7 +46,7 @@ void SendCoinsDialog::on_sendButton_clicked()
|
|||||||
QString label;
|
QString label;
|
||||||
qint64 payAmountParsed;
|
qint64 payAmountParsed;
|
||||||
|
|
||||||
valid = ParseMoney(payAmount.toStdString(), payAmountParsed);
|
valid = GUIUtil::parseMoney(payAmount, &payAmountParsed);
|
||||||
|
|
||||||
if(!valid)
|
if(!valid)
|
||||||
{
|
{
|
||||||
@ -88,7 +85,7 @@ void SendCoinsDialog::on_sendButton_clicked()
|
|||||||
case ClientModel::AmountWithFeeExceedsBalance:
|
case ClientModel::AmountWithFeeExceedsBalance:
|
||||||
QMessageBox::warning(this, tr("Send Coins"),
|
QMessageBox::warning(this, tr("Send Coins"),
|
||||||
tr("Total exceeds your balance when the %1 transaction fee is included").
|
tr("Total exceeds your balance when the %1 transaction fee is included").
|
||||||
arg(QString::fromStdString(FormatMoney(model->getOptionsModel()->getTransactionFee()))),
|
arg(GUIUtil::formatMoney(model->getOptionsModel()->getTransactionFee())),
|
||||||
QMessageBox::Ok, QMessageBox::Ok);
|
QMessageBox::Ok, QMessageBox::Ok);
|
||||||
ui->payAmount->setFocus();
|
ui->payAmount->setFocus();
|
||||||
break;
|
break;
|
||||||
|
67
src/qt/transactionfilterproxy.cpp
Normal file
67
src/qt/transactionfilterproxy.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "transactionfilterproxy.h"
|
||||||
|
#include "transactiontablemodel.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
// Earliest date that can be represented (far in the past)
|
||||||
|
const QDateTime TransactionFilterProxy::MIN_DATE = QDateTime::fromTime_t(0);
|
||||||
|
// Last date that can be represented (far in the future)
|
||||||
|
const QDateTime TransactionFilterProxy::MAX_DATE = QDateTime::fromTime_t(0xFFFFFFFF);
|
||||||
|
|
||||||
|
TransactionFilterProxy::TransactionFilterProxy(QObject *parent) :
|
||||||
|
QSortFilterProxyModel(parent),
|
||||||
|
dateFrom(MIN_DATE),
|
||||||
|
dateTo(MAX_DATE),
|
||||||
|
addrPrefix(),
|
||||||
|
typeFilter(ALL_TYPES),
|
||||||
|
minAmount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransactionFilterProxy::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
|
||||||
|
|
||||||
|
int type = index.data(TransactionTableModel::TypeRole).toInt();
|
||||||
|
QDateTime datetime = index.data(TransactionTableModel::DateRole).toDateTime();
|
||||||
|
QString address = index.data(TransactionTableModel::AddressRole).toString();
|
||||||
|
QString label = index.data(TransactionTableModel::LabelRole).toString();
|
||||||
|
qint64 amount = index.data(TransactionTableModel::AbsoluteAmountRole).toLongLong();
|
||||||
|
|
||||||
|
if(!(TYPE(type) & typeFilter))
|
||||||
|
return false;
|
||||||
|
if(datetime < dateFrom || datetime > dateTo)
|
||||||
|
return false;
|
||||||
|
if(!address.startsWith(addrPrefix) && !label.startsWith(addrPrefix))
|
||||||
|
return false;
|
||||||
|
if(amount < minAmount)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionFilterProxy::setDateRange(const QDateTime &from, const QDateTime &to)
|
||||||
|
{
|
||||||
|
this->dateFrom = from;
|
||||||
|
this->dateTo = to;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionFilterProxy::setAddressPrefix(const QString &addrPrefix)
|
||||||
|
{
|
||||||
|
this->addrPrefix = addrPrefix;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionFilterProxy::setTypeFilter(quint32 modes)
|
||||||
|
{
|
||||||
|
this->typeFilter = modes;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionFilterProxy::setMinAmount(qint64 minimum)
|
||||||
|
{
|
||||||
|
this->minAmount = minimum;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
45
src/qt/transactionfilterproxy.h
Normal file
45
src/qt/transactionfilterproxy.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef TRANSACTIONFILTERPROXY_H
|
||||||
|
#define TRANSACTIONFILTERPROXY_H
|
||||||
|
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
// Filter transaction list according to pre-specified rules
|
||||||
|
class TransactionFilterProxy : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TransactionFilterProxy(QObject *parent = 0);
|
||||||
|
|
||||||
|
// Earliest date that can be represented (far in the past)
|
||||||
|
static const QDateTime MIN_DATE;
|
||||||
|
// Last date that can be represented (far in the future)
|
||||||
|
static const QDateTime MAX_DATE;
|
||||||
|
// Type filter bit field (all types)
|
||||||
|
static const quint32 ALL_TYPES = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
static quint32 TYPE(int type) { return 1<<type; }
|
||||||
|
|
||||||
|
void setDateRange(const QDateTime &from, const QDateTime &to);
|
||||||
|
void setAddressPrefix(const QString &addrPrefix);
|
||||||
|
// Type filter takes a bitfield created with TYPE() or ALL_TYPES
|
||||||
|
void setTypeFilter(quint32 modes);
|
||||||
|
void setMinAmount(qint64 minimum);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QDateTime dateFrom;
|
||||||
|
QDateTime dateTo;
|
||||||
|
QString addrPrefix;
|
||||||
|
quint32 typeFilter;
|
||||||
|
qint64 minAmount;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSACTIONFILTERPROXY_H
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef TRANSACTIONRECORD_H
|
#ifndef TRANSACTIONRECORD_H
|
||||||
#define TRANSACTIONRECORD_H
|
#define TRANSACTIONRECORD_H
|
||||||
|
|
||||||
#include "main.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
class CWallet;
|
class CWallet;
|
||||||
|
class CWalletTx;
|
||||||
|
|
||||||
class TransactionStatus
|
class TransactionStatus
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <QDateTime>
|
||||||
#include <QtAlgorithms>
|
#include <QtAlgorithms>
|
||||||
|
|
||||||
const QString TransactionTableModel::Sent = "s";
|
const QString TransactionTableModel::Sent = "s";
|
||||||
@ -301,26 +302,37 @@ QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look up label for address in address book, if not found return empty string.
|
||||||
|
This should really move to the wallet class.
|
||||||
|
*/
|
||||||
|
QString TransactionTableModel::labelForAddress(const std::string &address) const
|
||||||
|
{
|
||||||
|
CRITICAL_BLOCK(wallet->cs_mapAddressBook)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string>::iterator mi = wallet->mapAddressBook.find(address);
|
||||||
|
if (mi != wallet->mapAddressBook.end())
|
||||||
|
{
|
||||||
|
return QString::fromStdString(mi->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
/* Look up address in address book, if found return
|
/* Look up address in address book, if found return
|
||||||
address[0:12]... (label)
|
address[0:12]... (label)
|
||||||
otherwise just return address
|
otherwise just return address
|
||||||
*/
|
*/
|
||||||
std::string TransactionTableModel::lookupAddress(const std::string &address) const
|
QString TransactionTableModel::lookupAddress(const std::string &address) const
|
||||||
{
|
{
|
||||||
std::string description;
|
QString label = labelForAddress(address);
|
||||||
CRITICAL_BLOCK(wallet->cs_mapAddressBook)
|
QString description;
|
||||||
|
if(label.isEmpty())
|
||||||
{
|
{
|
||||||
std::map<std::string, std::string>::iterator mi = wallet->mapAddressBook.find(address);
|
description = QString::fromStdString(address);
|
||||||
if (mi != wallet->mapAddressBook.end() && !(*mi).second.empty())
|
}
|
||||||
{
|
else
|
||||||
std::string label = (*mi).second;
|
{
|
||||||
description += address.substr(0,12) + "... ";
|
description = QString::fromStdString(address.substr(0,12)) + QString("... (") + label + QString(")");
|
||||||
description += "(" + label + ")";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
description += address;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@ -360,13 +372,13 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx)
|
|||||||
switch(wtx->type)
|
switch(wtx->type)
|
||||||
{
|
{
|
||||||
case TransactionRecord::RecvWithAddress:
|
case TransactionRecord::RecvWithAddress:
|
||||||
description = QString::fromStdString(lookupAddress(wtx->address));
|
description = lookupAddress(wtx->address);
|
||||||
break;
|
break;
|
||||||
case TransactionRecord::RecvFromIP:
|
case TransactionRecord::RecvFromIP:
|
||||||
description = QString::fromStdString(wtx->address);
|
description = QString::fromStdString(wtx->address);
|
||||||
break;
|
break;
|
||||||
case TransactionRecord::SendToAddress:
|
case TransactionRecord::SendToAddress:
|
||||||
description = QString::fromStdString(lookupAddress(wtx->address));
|
description = lookupAddress(wtx->address);
|
||||||
break;
|
break;
|
||||||
case TransactionRecord::SendToIP:
|
case TransactionRecord::SendToIP:
|
||||||
description = QString::fromStdString(wtx->address);
|
description = QString::fromStdString(wtx->address);
|
||||||
@ -502,24 +514,28 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
else if (role == TypeRole)
|
else if (role == TypeRole)
|
||||||
{
|
{
|
||||||
/* Role for filtering tabs by type */
|
return rec->type;
|
||||||
switch(rec->type)
|
}
|
||||||
{
|
else if (role == DateRole)
|
||||||
case TransactionRecord::RecvWithAddress:
|
{
|
||||||
case TransactionRecord::RecvFromIP:
|
return QDateTime::fromTime_t(static_cast<uint>(rec->time));
|
||||||
return TransactionTableModel::Received;
|
|
||||||
case TransactionRecord::SendToAddress:
|
|
||||||
case TransactionRecord::SendToIP:
|
|
||||||
case TransactionRecord::SendToSelf:
|
|
||||||
return TransactionTableModel::Sent;
|
|
||||||
default:
|
|
||||||
return TransactionTableModel::Other;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (role == LongDescriptionRole)
|
else if (role == LongDescriptionRole)
|
||||||
{
|
{
|
||||||
return priv->describe(rec);
|
return priv->describe(rec);
|
||||||
}
|
}
|
||||||
|
else if (role == AddressRole)
|
||||||
|
{
|
||||||
|
return QString::fromStdString(rec->address);
|
||||||
|
}
|
||||||
|
else if (role == LabelRole)
|
||||||
|
{
|
||||||
|
return labelForAddress(rec->address);
|
||||||
|
}
|
||||||
|
else if (role == AbsoluteAmountRole)
|
||||||
|
{
|
||||||
|
return llabs(rec->credit + rec->debit);
|
||||||
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,20 @@ public:
|
|||||||
Amount = 4
|
Amount = 4
|
||||||
} ColumnIndex;
|
} ColumnIndex;
|
||||||
|
|
||||||
|
// Roles to get specific information from a transaction row
|
||||||
enum {
|
enum {
|
||||||
|
// Type of transaction
|
||||||
TypeRole = Qt::UserRole,
|
TypeRole = Qt::UserRole,
|
||||||
LongDescriptionRole = Qt::UserRole+1
|
// Date and time this transaction was created
|
||||||
|
DateRole,
|
||||||
|
// Long description (HTML format)
|
||||||
|
LongDescriptionRole,
|
||||||
|
// Address of transaction
|
||||||
|
AddressRole,
|
||||||
|
// Label of address related to transaction
|
||||||
|
LabelRole,
|
||||||
|
// Absolute net amount of transaction
|
||||||
|
AbsoluteAmountRole
|
||||||
} RoleIndex;
|
} RoleIndex;
|
||||||
|
|
||||||
/* TypeRole values */
|
/* TypeRole values */
|
||||||
@ -44,7 +55,8 @@ private:
|
|||||||
QStringList columns;
|
QStringList columns;
|
||||||
TransactionTablePriv *priv;
|
TransactionTablePriv *priv;
|
||||||
|
|
||||||
std::string lookupAddress(const std::string &address) const;
|
QString labelForAddress(const std::string &address) const;
|
||||||
|
QString lookupAddress(const std::string &address) const;
|
||||||
QVariant formatTxStatus(const TransactionRecord *wtx) const;
|
QVariant formatTxStatus(const TransactionRecord *wtx) const;
|
||||||
QVariant formatTxDate(const TransactionRecord *wtx) const;
|
QVariant formatTxDate(const TransactionRecord *wtx) const;
|
||||||
QVariant formatTxType(const TransactionRecord *wtx) const;
|
QVariant formatTxType(const TransactionRecord *wtx) const;
|
||||||
|
182
src/qt/transactionview.cpp
Normal file
182
src/qt/transactionview.cpp
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
#include "transactionview.h"
|
||||||
|
|
||||||
|
// Temp includes for filtering prototype
|
||||||
|
// Move to TransactionFilterRow class
|
||||||
|
#include "transactionfilterproxy.h"
|
||||||
|
#include "transactionrecord.h"
|
||||||
|
#include "transactiontablemodel.h"
|
||||||
|
#include "guiutil.h"
|
||||||
|
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QDoubleValidator>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
TransactionView::TransactionView(QWidget *parent) :
|
||||||
|
QWidget(parent), model(0), transactionProxyModel(0),
|
||||||
|
transactionView(0)
|
||||||
|
{
|
||||||
|
// Build filter row
|
||||||
|
QHBoxLayout *hlayout = new QHBoxLayout();
|
||||||
|
hlayout->setContentsMargins(QMargins(0,0,0,0));
|
||||||
|
hlayout->setSpacing(0);
|
||||||
|
|
||||||
|
hlayout->addSpacing(23);
|
||||||
|
|
||||||
|
dateWidget = new QComboBox(this);
|
||||||
|
dateWidget->setMaximumWidth(120);
|
||||||
|
dateWidget->setMinimumWidth(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("This year"), ThisYear);
|
||||||
|
dateWidget->addItem(tr("Range..."), Range);
|
||||||
|
hlayout->addWidget(dateWidget);
|
||||||
|
|
||||||
|
typeWidget = new QComboBox(this);
|
||||||
|
typeWidget->setMaximumWidth(120);
|
||||||
|
typeWidget->setMinimumWidth(120);
|
||||||
|
|
||||||
|
typeWidget->addItem(tr("All"), TransactionFilterProxy::ALL_TYPES);
|
||||||
|
typeWidget->addItem(tr("Received with"), TransactionFilterProxy::TYPE(TransactionRecord::RecvWithAddress) |
|
||||||
|
TransactionFilterProxy::TYPE(TransactionRecord::RecvFromIP));
|
||||||
|
typeWidget->addItem(tr("Sent to"), TransactionFilterProxy::TYPE(TransactionRecord::SendToAddress) |
|
||||||
|
TransactionFilterProxy::TYPE(TransactionRecord::SendToIP));
|
||||||
|
typeWidget->addItem(tr("To yourself"), TransactionFilterProxy::TYPE(TransactionRecord::SendToSelf));
|
||||||
|
typeWidget->addItem(tr("Generated"), TransactionFilterProxy::TYPE(TransactionRecord::Generated));
|
||||||
|
typeWidget->addItem(tr("Other"), TransactionFilterProxy::TYPE(TransactionRecord::Other));
|
||||||
|
|
||||||
|
hlayout->addWidget(typeWidget);
|
||||||
|
|
||||||
|
addressWidget = new QLineEdit(this);
|
||||||
|
addressWidget->setPlaceholderText("Enter address or label to search");
|
||||||
|
hlayout->addWidget(addressWidget);
|
||||||
|
|
||||||
|
amountWidget = new QLineEdit(this);
|
||||||
|
amountWidget->setPlaceholderText("Min amount");
|
||||||
|
amountWidget->setMaximumWidth(79);
|
||||||
|
amountWidget->setMinimumWidth(79);
|
||||||
|
amountWidget->setValidator(new QDoubleValidator(0, 1e20, 8, this));
|
||||||
|
hlayout->addWidget(amountWidget);
|
||||||
|
|
||||||
|
QVBoxLayout *vlayout = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
QTableView *view = new QTableView(this);
|
||||||
|
vlayout->addLayout(hlayout);
|
||||||
|
vlayout->addWidget(view);
|
||||||
|
vlayout->setSpacing(0);
|
||||||
|
int width = view->verticalScrollBar()->sizeHint().width();
|
||||||
|
// Cover scroll bar width with spacing
|
||||||
|
hlayout->addSpacing(width);
|
||||||
|
// Always show scroll bar
|
||||||
|
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
|
||||||
|
transactionView = view;
|
||||||
|
|
||||||
|
connect(dateWidget, SIGNAL(activated(int)), this, SLOT(chooseDate(int)));
|
||||||
|
connect(typeWidget, SIGNAL(activated(int)), this, SLOT(chooseType(int)));
|
||||||
|
connect(addressWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedPrefix(const QString&)));
|
||||||
|
connect(amountWidget, SIGNAL(textChanged(const QString&)), this, SLOT(changedAmount(const QString&)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionView::setModel(TransactionTableModel *model)
|
||||||
|
{
|
||||||
|
this->model = model;
|
||||||
|
|
||||||
|
transactionProxyModel = new TransactionFilterProxy(this);
|
||||||
|
transactionProxyModel->setSourceModel(model);
|
||||||
|
transactionProxyModel->setDynamicSortFilter(true);
|
||||||
|
|
||||||
|
transactionProxyModel->setSortRole(Qt::EditRole);
|
||||||
|
|
||||||
|
transactionView->setModel(transactionProxyModel);
|
||||||
|
transactionView->setAlternatingRowColors(true);
|
||||||
|
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
transactionView->setSortingEnabled(true);
|
||||||
|
transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
|
||||||
|
transactionView->verticalHeader()->hide();
|
||||||
|
|
||||||
|
transactionView->horizontalHeader()->resizeSection(
|
||||||
|
TransactionTableModel::Status, 23);
|
||||||
|
transactionView->horizontalHeader()->resizeSection(
|
||||||
|
TransactionTableModel::Date, 120);
|
||||||
|
transactionView->horizontalHeader()->resizeSection(
|
||||||
|
TransactionTableModel::Type, 120);
|
||||||
|
transactionView->horizontalHeader()->setResizeMode(
|
||||||
|
TransactionTableModel::ToAddress, QHeaderView::Stretch);
|
||||||
|
transactionView->horizontalHeader()->resizeSection(
|
||||||
|
TransactionTableModel::Amount, 79);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionView::chooseDate(int idx)
|
||||||
|
{
|
||||||
|
QDate current = QDate::currentDate();
|
||||||
|
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 ThisYear:
|
||||||
|
transactionProxyModel->setDateRange(
|
||||||
|
QDateTime(QDate(current.year(), 1, 1)),
|
||||||
|
TransactionFilterProxy::MAX_DATE);
|
||||||
|
break;
|
||||||
|
case Range:
|
||||||
|
// TODO ask specific range
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionView::chooseType(int idx)
|
||||||
|
{
|
||||||
|
transactionProxyModel->setTypeFilter(
|
||||||
|
typeWidget->itemData(idx).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionView::changedPrefix(const QString &prefix)
|
||||||
|
{
|
||||||
|
transactionProxyModel->setAddressPrefix(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransactionView::changedAmount(const QString &amount)
|
||||||
|
{
|
||||||
|
qint64 amount_parsed;
|
||||||
|
if(GUIUtil::parseMoney(amount, &amount_parsed))
|
||||||
|
{
|
||||||
|
transactionProxyModel->setMinAmount(amount_parsed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transactionProxyModel->setMinAmount(0);
|
||||||
|
}
|
||||||
|
}
|
53
src/qt/transactionview.h
Normal file
53
src/qt/transactionview.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef TRANSACTIONVIEW_H
|
||||||
|
#define TRANSACTIONVIEW_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class TransactionTableModel;
|
||||||
|
class TransactionFilterProxy;
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QTableView;
|
||||||
|
class QComboBox;
|
||||||
|
class QLineEdit;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TransactionView : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit TransactionView(QWidget *parent = 0);
|
||||||
|
|
||||||
|
void setModel(TransactionTableModel *model);
|
||||||
|
|
||||||
|
enum DateEnum
|
||||||
|
{
|
||||||
|
All,
|
||||||
|
Today,
|
||||||
|
ThisWeek,
|
||||||
|
ThisMonth,
|
||||||
|
ThisYear,
|
||||||
|
Range
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
TransactionTableModel *model;
|
||||||
|
TransactionFilterProxy *transactionProxyModel;
|
||||||
|
QTableView *transactionView;
|
||||||
|
|
||||||
|
QComboBox *dateWidget;
|
||||||
|
QComboBox *typeWidget;
|
||||||
|
QLineEdit *addressWidget;
|
||||||
|
QLineEdit *amountWidget;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void chooseDate(int idx);
|
||||||
|
void chooseType(int idx);
|
||||||
|
void changedPrefix(const QString &prefix);
|
||||||
|
void changedAmount(const QString &amount);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TRANSACTIONVIEW_H
|
Loading…
Reference in New Issue
Block a user