diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 4036c1419..76841f846 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -72,7 +72,9 @@ HEADERS += src/qt/bitcoingui.h \ src/qt/transactiondescdialog.h \ src/qt/bitcoinamountfield.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 \ src/qt/transactiontablemodel.cpp \ src/qt/addresstablemodel.cpp \ @@ -105,7 +107,9 @@ SOURCES += src/qt/bitcoin.cpp src/qt/bitcoingui.cpp \ src/qt/bitcoinstrings.cpp \ src/qt/bitcoinamountfield.cpp \ src/wallet.cpp \ - src/keystore.cpp + src/keystore.cpp \ + src/qt/transactionfilterproxy.cpp \ + src/qt/transactionview.cpp RESOURCES += \ src/qt/bitcoin.qrc diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 5bf79ee6d..44f77460e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -15,6 +15,7 @@ #include "optionsmodel.h" #include "transactiondescdialog.h" #include "addresstablemodel.h" +#include "transactionview.h" #include "headers.h" @@ -29,12 +30,9 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include @@ -104,7 +102,9 @@ BitcoinGUI::BitcoinGUI(QWidget *parent): vbox->addLayout(hbox_address); 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); centralwidget->setLayout(vbox); @@ -198,7 +198,11 @@ void BitcoinGUI::setModel(ClientModel *model) connect(model, SIGNAL(error(QString,QString)), this, SLOT(error(QString,QString))); // 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() @@ -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() { SendCoinsDialog dlg; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index b3559c3bc..f6241a476 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -6,6 +6,7 @@ class TransactionTableModel; class ClientModel; +class TransactionView; QT_BEGIN_NAMESPACE class QLabel; @@ -56,12 +57,11 @@ private: QAction *openBitcoin; QSystemTrayIcon *trayIcon; - QList transactionViews; + TransactionView *transactionView; void createActions(); QWidget *createTabs(); void createTrayIcon(); - void setTabsModel(QAbstractItemModel *transaction_model); public slots: void setBalance(qint64 balance); diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp index ec8b43526..c68532b87 100644 --- a/src/qt/guiutil.cpp +++ b/src/qt/guiutil.cpp @@ -1,5 +1,6 @@ #include "guiutil.h" #include "bitcoinaddressvalidator.h" +#include "util.h" #include #include @@ -36,3 +37,12 @@ void GUIUtil::setupAmountWidget(QLineEdit *widget, QWidget *parent) 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)); +} diff --git a/src/qt/guiutil.h b/src/qt/guiutil.h index 748e29bf3..58f897951 100644 --- a/src/qt/guiutil.h +++ b/src/qt/guiutil.h @@ -14,12 +14,18 @@ class GUIUtil public: static QString DateTimeStr(qint64 nTime); - /* Render bitcoin addresses in monospace font */ + // Render bitcoin addresses in monospace font static QFont bitcoinAddressFont(); static void setupAddressWidget(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 diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 67c270e6f..33d9a2547 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -12,9 +12,6 @@ #include #include -#include "util.h" -#include "base58.h" - SendCoinsDialog::SendCoinsDialog(QWidget *parent, const QString &address) : QDialog(parent), ui(new Ui::SendCoinsDialog), @@ -49,7 +46,7 @@ void SendCoinsDialog::on_sendButton_clicked() QString label; qint64 payAmountParsed; - valid = ParseMoney(payAmount.toStdString(), payAmountParsed); + valid = GUIUtil::parseMoney(payAmount, &payAmountParsed); if(!valid) { @@ -88,7 +85,7 @@ void SendCoinsDialog::on_sendButton_clicked() case ClientModel::AmountWithFeeExceedsBalance: QMessageBox::warning(this, tr("Send Coins"), 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); ui->payAmount->setFocus(); break; diff --git a/src/qt/transactionfilterproxy.cpp b/src/qt/transactionfilterproxy.cpp new file mode 100644 index 000000000..cd1194d99 --- /dev/null +++ b/src/qt/transactionfilterproxy.cpp @@ -0,0 +1,67 @@ +#include "transactionfilterproxy.h" +#include "transactiontablemodel.h" + +#include +#include + +// 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(); +} diff --git a/src/qt/transactionfilterproxy.h b/src/qt/transactionfilterproxy.h new file mode 100644 index 000000000..a44c9c4df --- /dev/null +++ b/src/qt/transactionfilterproxy.h @@ -0,0 +1,45 @@ +#ifndef TRANSACTIONFILTERPROXY_H +#define TRANSACTIONFILTERPROXY_H + +#include +#include + +// 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< class CWallet; +class CWalletTx; class TransactionStatus { diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index e49629c9a..28d22b853 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include const QString TransactionTableModel::Sent = "s"; @@ -301,27 +302,38 @@ QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const } } -/* Look up address in address book, if found return - address[0:12]... (label) - otherwise just return address +/* Look up label for address in address book, if not found return empty string. + This should really move to the wallet class. */ -std::string TransactionTableModel::lookupAddress(const std::string &address) const +QString TransactionTableModel::labelForAddress(const std::string &address) const { - std::string description; CRITICAL_BLOCK(wallet->cs_mapAddressBook) { std::map::iterator mi = wallet->mapAddressBook.find(address); - if (mi != wallet->mapAddressBook.end() && !(*mi).second.empty()) - { - std::string label = (*mi).second; - description += address.substr(0,12) + "... "; - description += "(" + label + ")"; - } - else + if (mi != wallet->mapAddressBook.end()) { - description += address; + return QString::fromStdString(mi->second); } } + return QString(); +} + +/* Look up address in address book, if found return + address[0:12]... (label) + otherwise just return address + */ +QString TransactionTableModel::lookupAddress(const std::string &address) const +{ + QString label = labelForAddress(address); + QString description; + if(label.isEmpty()) + { + description = QString::fromStdString(address); + } + else + { + description = QString::fromStdString(address.substr(0,12)) + QString("... (") + label + QString(")"); + } return description; } @@ -360,13 +372,13 @@ QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx) switch(wtx->type) { case TransactionRecord::RecvWithAddress: - description = QString::fromStdString(lookupAddress(wtx->address)); + description = lookupAddress(wtx->address); break; case TransactionRecord::RecvFromIP: description = QString::fromStdString(wtx->address); break; case TransactionRecord::SendToAddress: - description = QString::fromStdString(lookupAddress(wtx->address)); + description = lookupAddress(wtx->address); break; case TransactionRecord::SendToIP: description = QString::fromStdString(wtx->address); @@ -502,24 +514,28 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const } else if (role == TypeRole) { - /* Role for filtering tabs by type */ - switch(rec->type) - { - case TransactionRecord::RecvWithAddress: - case TransactionRecord::RecvFromIP: - return TransactionTableModel::Received; - case TransactionRecord::SendToAddress: - case TransactionRecord::SendToIP: - case TransactionRecord::SendToSelf: - return TransactionTableModel::Sent; - default: - return TransactionTableModel::Other; - } + return rec->type; + } + else if (role == DateRole) + { + return QDateTime::fromTime_t(static_cast(rec->time)); } else if (role == LongDescriptionRole) { 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(); } diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index d19e1a3af..c26acbc10 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -23,9 +23,20 @@ public: Amount = 4 } ColumnIndex; + // Roles to get specific information from a transaction row enum { + // Type of transaction 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; /* TypeRole values */ @@ -44,7 +55,8 @@ private: QStringList columns; 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 formatTxDate(const TransactionRecord *wtx) const; QVariant formatTxType(const TransactionRecord *wtx) const; diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp new file mode 100644 index 000000000..bf7d55d7d --- /dev/null +++ b/src/qt/transactionview.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#include + +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); + } +} diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h new file mode 100644 index 000000000..e75dcc259 --- /dev/null +++ b/src/qt/transactionview.h @@ -0,0 +1,53 @@ +#ifndef TRANSACTIONVIEW_H +#define TRANSACTIONVIEW_H + +#include + +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