Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615150
transactionview.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
transactionview.cpp
View Options
#include
"transactionview.h"
#include
"transactionfilterproxy.h"
#include
"transactionrecord.h"
#include
"walletmodel.h"
#include
"addresstablemodel.h"
#include
"transactiontablemodel.h"
#include
"bitcoinunits.h"
#include
"csvmodelwriter.h"
#include
"transactiondescdialog.h"
#include
"editaddressdialog.h"
#include
"optionsmodel.h"
#include
<QtGlobal>
#include
<QScrollBar>
#include
<QComboBox>
#include
<QDoubleValidator>
#include
<QHBoxLayout>
#include
<QVBoxLayout>
#include
<QLineEdit>
#include
<QTableView>
#include
<QHeaderView>
#include
<QPushButton>
#include
<QFileDialog>
#include
<QMessageBox>
#include
<QPoint>
#include
<QMenu>
#include
<QApplication>
#include
<QClipboard>
#include
<QLabel>
#include
<QDateTimeEdit>
TransactionView
::
TransactionView
(
QWidget
*
parent
)
:
QWidget
(
parent
),
model
(
0
),
transactionProxyModel
(
0
),
transactionView
(
0
)
{
// Build filter row
setContentsMargins
(
0
,
0
,
0
,
0
);
QHBoxLayout
*
hlayout
=
new
QHBoxLayout
();
hlayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
#ifdef Q_WS_MAC
hlayout
->
setSpacing
(
5
);
hlayout
->
addSpacing
(
26
);
#else
hlayout
->
setSpacing
(
0
);
hlayout
->
addSpacing
(
23
);
#endif
dateWidget
=
new
QComboBox
(
this
);
#ifdef Q_WS_MAC
dateWidget
->
setFixedWidth
(
121
);
#else
dateWidget
->
setFixedWidth
(
120
);
#endif
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
);
#ifdef Q_WS_MAC
typeWidget
->
setFixedWidth
(
121
);
#else
typeWidget
->
setFixedWidth
(
120
);
#endif
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
(
"Mined"
),
TransactionFilterProxy
::
TYPE
(
TransactionRecord
::
Generated
));
typeWidget
->
addItem
(
tr
(
"Other"
),
TransactionFilterProxy
::
TYPE
(
TransactionRecord
::
Other
));
hlayout
->
addWidget
(
typeWidget
);
addressWidget
=
new
QLineEdit
(
this
);
#if QT_VERSION >= 0x040700
addressWidget
->
setPlaceholderText
(
tr
(
"Enter address or label to search"
));
#endif
hlayout
->
addWidget
(
addressWidget
);
amountWidget
=
new
QLineEdit
(
this
);
#if QT_VERSION >= 0x040700
amountWidget
->
setPlaceholderText
(
tr
(
"Min amount"
));
#endif
#ifdef Q_WS_MAC
amountWidget
->
setFixedWidth
(
97
);
#else
amountWidget
->
setFixedWidth
(
100
);
#endif
amountWidget
->
setValidator
(
new
QDoubleValidator
(
0
,
1e20
,
8
,
this
));
hlayout
->
addWidget
(
amountWidget
);
QVBoxLayout
*
vlayout
=
new
QVBoxLayout
(
this
);
vlayout
->
setContentsMargins
(
0
,
0
,
0
,
0
);
vlayout
->
setSpacing
(
0
);
//vlayout->addLayout(hlayout2);
QTableView
*
view
=
new
QTableView
(
this
);
vlayout
->
addLayout
(
hlayout
);
vlayout
->
addWidget
(
createDateRangeWidget
());
vlayout
->
addWidget
(
view
);
vlayout
->
setSpacing
(
0
);
int
width
=
view
->
verticalScrollBar
()
->
sizeHint
().
width
();
// Cover scroll bar width with spacing
#ifdef Q_WS_MAC
hlayout
->
addSpacing
(
width
+
2
);
#else
hlayout
->
addSpacing
(
width
);
#endif
// Always show scroll bar
view
->
setVerticalScrollBarPolicy
(
Qt
::
ScrollBarAlwaysOn
);
view
->
setTabKeyNavigation
(
false
);
view
->
setContextMenuPolicy
(
Qt
::
CustomContextMenu
);
transactionView
=
view
;
// Actions
QAction
*
copyAddressAction
=
new
QAction
(
tr
(
"Copy address"
),
this
);
QAction
*
copyLabelAction
=
new
QAction
(
tr
(
"Copy label"
),
this
);
QAction
*
editLabelAction
=
new
QAction
(
tr
(
"Edit label"
),
this
);
QAction
*
showDetailsAction
=
new
QAction
(
tr
(
"Show details..."
),
this
);
contextMenu
=
new
QMenu
();
contextMenu
->
addAction
(
copyAddressAction
);
contextMenu
->
addAction
(
copyLabelAction
);
contextMenu
->
addAction
(
editLabelAction
);
contextMenu
->
addAction
(
showDetailsAction
);
// Connect actions
connect
(
dateWidget
,
SIGNAL
(
activated
(
int
)),
this
,
SLOT
(
chooseDate
(
int
)));
connect
(
typeWidget
,
SIGNAL
(
activated
(
int
)),
this
,
SLOT
(
chooseType
(
int
)));
connect
(
addressWidget
,
SIGNAL
(
textChanged
(
QString
)),
this
,
SLOT
(
changedPrefix
(
QString
)));
connect
(
amountWidget
,
SIGNAL
(
textChanged
(
QString
)),
this
,
SLOT
(
changedAmount
(
QString
)));
connect
(
view
,
SIGNAL
(
doubleClicked
(
QModelIndex
)),
this
,
SIGNAL
(
doubleClicked
(
QModelIndex
)));
connect
(
view
,
SIGNAL
(
customContextMenuRequested
(
QPoint
)),
this
,
SLOT
(
contextualMenu
(
QPoint
)));
connect
(
copyAddressAction
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
copyAddress
()));
connect
(
copyLabelAction
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
copyLabel
()));
connect
(
editLabelAction
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
editLabel
()));
connect
(
showDetailsAction
,
SIGNAL
(
triggered
()),
this
,
SLOT
(
showDetails
()));
}
void
TransactionView
::
setModel
(
WalletModel
*
model
)
{
this
->
model
=
model
;
if
(
model
)
{
transactionProxyModel
=
new
TransactionFilterProxy
(
this
);
transactionProxyModel
->
setSourceModel
(
model
->
getTransactionTableModel
());
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
,
100
);
}
}
void
TransactionView
::
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
,
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
TransactionView
::
chooseType
(
int
idx
)
{
if
(
!
transactionProxyModel
)
return
;
transactionProxyModel
->
setTypeFilter
(
typeWidget
->
itemData
(
idx
).
toInt
());
}
void
TransactionView
::
changedPrefix
(
const
QString
&
prefix
)
{
if
(
!
transactionProxyModel
)
return
;
transactionProxyModel
->
setAddressPrefix
(
prefix
);
}
void
TransactionView
::
changedAmount
(
const
QString
&
amount
)
{
if
(
!
transactionProxyModel
)
return
;
qint64
amount_parsed
=
0
;
if
(
BitcoinUnits
::
parse
(
model
->
getOptionsModel
()
->
getDisplayUnit
(),
amount
,
&
amount_parsed
))
{
transactionProxyModel
->
setMinAmount
(
amount_parsed
);
}
else
{
transactionProxyModel
->
setMinAmount
(
0
);
}
}
void
TransactionView
::
exportClicked
()
{
// CSV is currently the only supported format
QString
filename
=
QFileDialog
::
getSaveFileName
(
this
,
tr
(
"Export Transaction Data"
),
QDir
::
currentPath
(),
tr
(
"Comma separated file (*.csv)"
));
if
(
filename
.
isNull
())
return
;
CSVModelWriter
writer
(
filename
);
// name, column, role
writer
.
setModel
(
transactionProxyModel
);
writer
.
addColumn
(
tr
(
"Confirmed"
),
0
,
TransactionTableModel
::
ConfirmedRole
);
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
(
tr
(
"Amount"
),
0
,
TransactionTableModel
::
FormattedAmountRole
);
writer
.
addColumn
(
tr
(
"ID"
),
0
,
TransactionTableModel
::
TxIDRole
);
if
(
!
writer
.
write
())
{
QMessageBox
::
critical
(
this
,
tr
(
"Error exporting"
),
tr
(
"Could not write to file %1."
).
arg
(
filename
),
QMessageBox
::
Abort
,
QMessageBox
::
Abort
);
}
}
void
TransactionView
::
contextualMenu
(
const
QPoint
&
point
)
{
QModelIndex
index
=
transactionView
->
indexAt
(
point
);
if
(
index
.
isValid
())
{
contextMenu
->
exec
(
QCursor
::
pos
());
}
}
void
TransactionView
::
copyAddress
()
{
if
(
!
transactionView
->
selectionModel
())
return
;
QModelIndexList
selection
=
transactionView
->
selectionModel
()
->
selectedRows
();
if
(
!
selection
.
isEmpty
())
{
QApplication
::
clipboard
()
->
setText
(
selection
.
at
(
0
).
data
(
TransactionTableModel
::
AddressRole
).
toString
());
}
}
void
TransactionView
::
copyLabel
()
{
if
(
!
transactionView
->
selectionModel
())
return
;
QModelIndexList
selection
=
transactionView
->
selectionModel
()
->
selectedRows
();
if
(
!
selection
.
isEmpty
())
{
QApplication
::
clipboard
()
->
setText
(
selection
.
at
(
0
).
data
(
TransactionTableModel
::
LabelRole
).
toString
());
}
}
void
TransactionView
::
editLabel
()
{
if
(
!
transactionView
->
selectionModel
()
||!
model
)
return
;
QModelIndexList
selection
=
transactionView
->
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
TransactionView
::
showDetails
()
{
if
(
!
transactionView
->
selectionModel
())
return
;
QModelIndexList
selection
=
transactionView
->
selectionModel
()
->
selectedRows
();
if
(
!
selection
.
isEmpty
())
{
TransactionDescDialog
dlg
(
selection
.
at
(
0
));
dlg
.
exec
();
}
}
QWidget
*
TransactionView
::
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
TransactionView
::
dateRangeChanged
()
{
if
(
!
transactionProxyModel
)
return
;
transactionProxyModel
->
setDateRange
(
QDateTime
(
dateFrom
->
date
()),
QDateTime
(
dateTo
->
date
()).
addDays
(
1
));
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 23, 09:59 (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4556632
Default Alt Text
transactionview.cpp (14 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment