Simple transaction history

This commit is contained in:
Ilya Kitaev 2016-10-04 23:12:58 +03:00
parent 9cc92bf9d6
commit 522b0671ad
9 changed files with 110 additions and 36 deletions

View file

@ -29,10 +29,12 @@
import QtQuick 2.0 import QtQuick 2.0
import moneroComponents.Clipboard 1.0 import moneroComponents.Clipboard 1.0
ListView { ListView {
id: listView id: listView
clip: true clip: true
boundsBehavior: ListView.StopAtBounds boundsBehavior: ListView.StopAtBounds
property var previousItem
footer: Rectangle { footer: Rectangle {
height: 127 height: 127
@ -48,7 +50,7 @@ ListView {
} }
} }
property var previousItem
delegate: Rectangle { delegate: Rectangle {
id: delegate id: delegate
height: 114 height: 114
@ -63,13 +65,13 @@ ListView {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.topMargin: 14 anchors.topMargin: 14
// -- direction indicator
Rectangle { Rectangle {
id: dot id: dot
width: 14 width: 14
height: width height: width
radius: width / 2 radius: width / 2
color: out ? "#FF4F41" : "#36B05B" color: isOut ? "#FF4F41" : "#36B05B"
} }
Item { //separator Item { //separator
@ -77,6 +79,7 @@ ListView {
height: 14 height: 14
} }
// -- description aka recepient name from address book (TODO)
Text { Text {
id: descriptionText id: descriptionText
width: text.length ? (descriptionArea.containsMouse ? parent.width - x - 12 : 120) : 0 width: text.length ? (descriptionArea.containsMouse ? parent.width - x - 12 : 120) : 0
@ -100,7 +103,7 @@ ListView {
height: 14 height: 14
visible: !descriptionArea.containsMouse visible: !descriptionArea.containsMouse
} }
// -- address (in case outgoing transaction) - N/A in case of incoming
Text { Text {
id: addressText id: addressText
anchors.verticalCenter: dot.verticalCenter anchors.verticalCenter: dot.verticalCenter
@ -109,11 +112,11 @@ ListView {
font.family: "Arial" font.family: "Arial"
font.pixelSize: 14 font.pixelSize: 14
color: "#545454" color: "#545454"
text: address text: hash
visible: !descriptionArea.containsMouse visible: !descriptionArea.containsMouse
} }
} }
// -- "PaymentID" title
Text { Text {
id: paymentLabel id: paymentLabel
anchors.left: parent.left anchors.left: parent.left
@ -128,7 +131,7 @@ ListView {
color: "#535353" color: "#535353"
text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : "" text: paymentId !== "" ? qsTr("Payment ID:") + translationManager.emptyString : ""
} }
// -- "PaymentID" value
Text { Text {
anchors.bottom: paymentLabel.bottom anchors.bottom: paymentLabel.bottom
anchors.left: paymentLabel.right anchors.left: paymentLabel.right
@ -143,7 +146,7 @@ ListView {
color: "#545454" color: "#545454"
text: paymentId text: paymentId
} }
// -- "Date", "Balance" and "Amound" section
Row { Row {
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -155,6 +158,7 @@ ListView {
height: 14 height: 14
} }
// -- "Date" column
Column { Column {
anchors.top: parent.top anchors.top: parent.top
width: 215 width: 215
@ -189,10 +193,13 @@ ListView {
} }
} }
} }
// -- "Balance" column
// XXX: we don't have a balance
/*
Column { Column {
anchors.top: parent.top anchors.top: parent.top
width: 148 width: 148
visible: false
Text { Text {
anchors.left: parent.left anchors.left: parent.left
@ -210,7 +217,9 @@ ListView {
text: balance text: balance
} }
} }
*/
// -- "Amount column
Column { Column {
anchors.top: parent.top anchors.top: parent.top
width: 148 width: 148
@ -230,8 +239,8 @@ ListView {
anchors.bottomMargin: 3 anchors.bottomMargin: 3
font.family: "Arial" font.family: "Arial"
font.pixelSize: 16 font.pixelSize: 16
color: out ? "#FF4F41" : "#36B05B" color: isOut ? "#FF4F41" : "#36B05B"
text: out ? "↓" : "↑" text: isOut ? "↓" : "↑"
} }
Text { Text {
@ -239,22 +248,16 @@ ListView {
font.family: "Arial" font.family: "Arial"
font.pixelSize: 18 font.pixelSize: 18
font.letterSpacing: -1 font.letterSpacing: -1
color: out ? "#FF4F41" : "#36B05B" color: isOut ? "#FF4F41" : "#36B05B"
text: amount text: amount
} }
} }
} }
} }
ListModel {
id: dropModel
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
ListElement { name: "<b>Add to address book</b>"; icon: "../images/dropdownAdd.png" }
ListElement { name: "<b>Send to same destination</b>"; icon: "../images/dropdownSend.png" }
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
}
Clipboard { id: clipboard }
TableDropdown { TableDropdown {
id: dropdown id: dropdown
anchors.right: parent.right anchors.right: parent.right
@ -283,4 +286,14 @@ ListView {
color: "#DBDBDB" color: "#DBDBDB"
} }
} }
ListModel {
id: dropModel
ListElement { name: "<b>Copy address to clipboard</b>"; icon: "../images/dropdownCopy.png" }
ListElement { name: "<b>Add to address book</b>"; icon: "../images/dropdownAdd.png" }
ListElement { name: "<b>Send to same destination</b>"; icon: "../images/dropdownSend.png" }
ListElement { name: "<b>Find similar transactions</b>"; icon: "../images/dropdownSearch.png" }
}
Clipboard { id: clipboard }
} }

View file

@ -39,6 +39,7 @@
#include "Wallet.h" #include "Wallet.h"
#include "PendingTransaction.h" #include "PendingTransaction.h"
#include "TranslationManager.h" #include "TranslationManager.h"
#include "TransactionInfo.h"
#include "model/TransactionHistoryModel.h" #include "model/TransactionHistoryModel.h"
@ -72,6 +73,8 @@ int main(int argc, char *argv[])
qRegisterMetaType<PendingTransaction::Priority>(); qRegisterMetaType<PendingTransaction::Priority>();
qRegisterMetaType<TransactionInfo::Direction>();
qmlRegisterUncreatableType<TransactionHistoryModel>("moneroComponents", 1, 0, "TransactionHistoryModel", qmlRegisterUncreatableType<TransactionHistoryModel>("moneroComponents", 1, 0, "TransactionHistoryModel",
"TranslationManager can't be instantiated directly"); "TranslationManager can't be instantiated directly");

View file

@ -33,10 +33,13 @@ import moneroComponents.WalletManager 1.0
Rectangle { Rectangle {
id: root id: root
property ListModel model: testModel property var model: testModel
color: "#F0EEEE" color: "#F0EEEE"
onModelChanged: {
console.log("model.rowCount: " + model.rowCount())
}
Text { Text {

View file

@ -2,11 +2,18 @@
#include "TransactionInfo.h" #include "TransactionInfo.h"
#include <wallet/wallet2_api.h> #include <wallet/wallet2_api.h>
#include <QDebug>
TransactionInfo *TransactionHistory::transaction(int index) TransactionInfo *TransactionHistory::transaction(int index)
{ {
// box up Bitmonero::TransactionInfo // box up Bitmonero::TransactionInfo
Bitmonero::TransactionInfo * impl = m_pimpl->transaction(index); Bitmonero::TransactionInfo * impl = m_pimpl->transaction(index);
if (!impl) {
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
qCritical("%s: there's %d transactions in backend", __FUNCTION__, m_pimpl->count());
return nullptr;
}
TransactionInfo * result = new TransactionInfo(impl, this); TransactionInfo * result = new TransactionInfo(impl, this);
return result; return result;
} }
@ -34,6 +41,7 @@ QList<TransactionInfo *> TransactionHistory::getAll() const
void TransactionHistory::refresh() void TransactionHistory::refresh()
{ {
// XXX this invalidates previously saved history that might be used by clients // XXX this invalidates previously saved history that might be used by clients
emit refreshStarted(); emit refreshStarted();
m_pimpl->refresh(); m_pimpl->refresh();
emit refreshFinished(); emit refreshFinished();

View file

@ -39,13 +39,23 @@ QString TransactionInfo::hash() const
return QString::fromStdString(m_pimpl->hash()); return QString::fromStdString(m_pimpl->hash());
} }
QString TransactionInfo::timestamp() QDateTime TransactionInfo::timestamp() const
{ {
QString result = QDateTime::fromTime_t(m_pimpl->timestamp()).toString(Qt::ISODate); QDateTime result = QDateTime::fromTime_t(m_pimpl->timestamp());
return result; return result;
} }
QString TransactionInfo::paymentId() QString TransactionInfo::date() const
{
return timestamp().date().toString(Qt::ISODate);
}
QString TransactionInfo::time() const
{
return timestamp().time().toString(Qt::ISODate);
}
QString TransactionInfo::paymentId() const
{ {
return QString::fromStdString(m_pimpl->paymentId()); return QString::fromStdString(m_pimpl->paymentId());
} }

View file

@ -1,8 +1,9 @@
#ifndef TRANSACTIONINFO_H #ifndef TRANSACTIONINFO_H
#define TRANSACTIONINFO_H #define TRANSACTIONINFO_H
#include <QObject>
#include <wallet/wallet2_api.h> #include <wallet/wallet2_api.h>
#include <QObject>
#include <QDateTime>
class TransactionInfo : public QObject class TransactionInfo : public QObject
{ {
@ -14,7 +15,9 @@ class TransactionInfo : public QObject
Q_PROPERTY(QString fee READ fee) Q_PROPERTY(QString fee READ fee)
Q_PROPERTY(quint64 blockHeight READ blockHeight) Q_PROPERTY(quint64 blockHeight READ blockHeight)
Q_PROPERTY(QString hash READ hash) Q_PROPERTY(QString hash READ hash)
Q_PROPERTY(QString timestamp READ timestamp) Q_PROPERTY(QDateTime timestamp READ timestamp)
Q_PROPERTY(QString date READ date)
Q_PROPERTY(QString time READ time)
Q_PROPERTY(QString paymentId READ paymentId) Q_PROPERTY(QString paymentId READ paymentId)
public: public:
@ -41,8 +44,11 @@ public:
quint64 blockHeight() const; quint64 blockHeight() const;
//! transaction_id //! transaction_id
QString hash() const; QString hash() const;
QString timestamp(); QDateTime timestamp() const;
QString paymentId(); QString date() const;
QString time() const;
QString paymentId() const;
// TODO: implement it // TODO: implement it
//! only applicable for output transactions //! only applicable for output transactions
@ -57,4 +63,5 @@ private:
// in order to wrap it to QVariant // in order to wrap it to QVariant
Q_DECLARE_METATYPE(TransactionInfo*) Q_DECLARE_METATYPE(TransactionInfo*)
#endif // TRANSACTIONINFO_H #endif // TRANSACTIONINFO_H

View file

@ -40,12 +40,14 @@ public:
virtual void newBlock(uint64_t height) virtual void newBlock(uint64_t height)
{ {
// qDebug() << __FUNCTION__; // qDebug() << __FUNCTION__;
m_wallet->m_history->refresh();
emit m_wallet->newBlock(height); emit m_wallet->newBlock(height);
} }
virtual void updated() virtual void updated()
{ {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
m_wallet->m_history->refresh();
emit m_wallet->updated(); emit m_wallet->updated();
} }
@ -53,6 +55,7 @@ public:
virtual void refreshed() virtual void refreshed()
{ {
qDebug() << __FUNCTION__; qDebug() << __FUNCTION__;
emit m_wallet->refreshed(); emit m_wallet->refreshed();
} }
@ -166,6 +169,7 @@ quint64 Wallet::daemonBlockChainTargetHeight() const
bool Wallet::refresh() bool Wallet::refresh()
{ {
bool result = m_walletImpl->refresh(); bool result = m_walletImpl->refresh();
m_history->refresh();
if (result) if (result)
emit updated(); emit updated();
return result; return result;
@ -205,10 +209,10 @@ void Wallet::disposeTransaction(PendingTransaction *t)
TransactionHistory *Wallet::history() TransactionHistory *Wallet::history()
{ {
if (!m_history) { // if (m_history->count() == 0) {
Bitmonero::TransactionHistory * impl = m_walletImpl->history(); // m_history->refresh();
m_history = new TransactionHistory(impl, this); // }
}
return m_history; return m_history;
} }
@ -252,6 +256,7 @@ Wallet::Wallet(Bitmonero::Wallet *w, QObject *parent)
, m_daemonBlockChainHeight(0) , m_daemonBlockChainHeight(0)
, m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS) , m_daemonBlockChainHeightTtl(DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this);
m_walletImpl->setListener(new WalletListenerImpl(this)); m_walletImpl->setListener(new WalletListenerImpl(this));
} }

View file

@ -2,6 +2,8 @@
#include "TransactionHistory.h" #include "TransactionHistory.h"
#include "TransactionInfo.h" #include "TransactionInfo.h"
#include <QDateTime>
TransactionHistoryModel::TransactionHistoryModel(QObject *parent) TransactionHistoryModel::TransactionHistoryModel(QObject *parent)
: QAbstractListModel(parent), m_transactionHistory(nullptr) : QAbstractListModel(parent), m_transactionHistory(nullptr)
@ -14,6 +16,12 @@ void TransactionHistoryModel::setTransactionHistory(TransactionHistory *th)
beginResetModel(); beginResetModel();
m_transactionHistory = th; m_transactionHistory = th;
endResetModel(); endResetModel();
connect(m_transactionHistory, &TransactionHistory::refreshStarted,
this, &TransactionHistoryModel::beginResetModel);
connect(m_transactionHistory, &TransactionHistory::refreshFinished,
this, &TransactionHistoryModel::endResetModel);
emit transactionHistoryChanged(); emit transactionHistoryChanged();
} }
@ -72,6 +80,15 @@ QVariant TransactionHistoryModel::data(const QModelIndex &index, int role) const
case TransactionPaymentIdRole: case TransactionPaymentIdRole:
result = tInfo->paymentId(); result = tInfo->paymentId();
break; break;
case TransactionIsOutRole:
result = tInfo->direction() == TransactionInfo::Direction_Out;
break;
case TransactionDateRole:
result = tInfo->date();
break;
case TransactionTimeRole:
result = tInfo->time();
break;
} }
return result; return result;
@ -96,6 +113,9 @@ QHash<int, QByteArray> TransactionHistoryModel::roleNames() const
roleNames.insert(TransactionHashRole, "hash"); roleNames.insert(TransactionHashRole, "hash");
roleNames.insert(TransactionTimeStampRole, "timeStamp"); roleNames.insert(TransactionTimeStampRole, "timeStamp");
roleNames.insert(TransactionPaymentIdRole, "paymentId"); roleNames.insert(TransactionPaymentIdRole, "paymentId");
roleNames.insert(TransactionIsOutRole, "isOut");
roleNames.insert(TransactionDateRole, "date");
roleNames.insert(TransactionTimeRole, "time");
return roleNames; return roleNames;
} }

View file

@ -25,7 +25,12 @@ public:
TransactionBlockHeightRole, TransactionBlockHeightRole,
TransactionHashRole, TransactionHashRole,
TransactionTimeStampRole, TransactionTimeStampRole,
TransactionPaymentIdRole TransactionPaymentIdRole,
// extra role (alias) for TransactionDirectionRole (as UI currently wants just boolean "out")
TransactionIsOutRole,
// extra roles for date and time (as UI wants date and time separately)
TransactionDateRole,
TransactionTimeRole
}; };
TransactionHistoryModel(QObject * parent = 0); TransactionHistoryModel(QObject * parent = 0);
@ -33,9 +38,9 @@ public:
TransactionHistory * transactionHistory() const; TransactionHistory * transactionHistory() const;
/// QAbstractListModel /// QAbstractListModel
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override; virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override;
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override; virtual int rowCount(const QModelIndex & parent = QModelIndex()) const override;
virtual QHash<int, QByteArray> roleNames() const override; virtual QHash<int, QByteArray> roleNames() const override;
signals: signals:
void transactionHistoryChanged(); void transactionHistoryChanged();