2018-01-02 18:12:05 +01:00
// Copyright (c) 2011-2017 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2013-11-04 16:20:43 +01:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2013-05-28 01:55:01 +02:00
# if defined(HAVE_CONFIG_H)
2017-11-10 01:57:53 +01:00
# include <config/bitcoin-config.h>
2013-05-28 01:55:01 +02:00
# endif
2017-11-10 01:57:53 +01:00
# include <qt/addressbookpage.h>
2017-08-15 17:31:26 +02:00
# include <qt/forms/ui_addressbookpage.h>
2011-07-07 17:33:15 +02:00
2017-11-10 01:57:53 +01:00
# include <qt/addresstablemodel.h>
# include <qt/bitcoingui.h>
# include <qt/csvmodelwriter.h>
# include <qt/editaddressdialog.h>
# include <qt/guiutil.h>
# include <qt/platformstyle.h>
2011-07-07 17:33:15 +02:00
2013-04-13 07:13:08 +02:00
# include <QIcon>
2011-12-04 18:01:53 +01:00
# include <QMenu>
2013-04-13 07:13:08 +02:00
# include <QMessageBox>
# include <QSortFilterProxyModel>
2011-07-07 17:33:15 +02:00
2018-01-03 17:00:18 +01:00
class AddressBookSortFilterProxyModel final : public QSortFilterProxyModel
{
const QString m_type ;
public :
AddressBookSortFilterProxyModel ( const QString & type , QObject * parent )
: QSortFilterProxyModel ( parent )
, m_type ( type )
{
setDynamicSortFilter ( true ) ;
setFilterCaseSensitivity ( Qt : : CaseInsensitive ) ;
setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
}
protected :
bool filterAcceptsRow ( int row , const QModelIndex & parent ) const
{
auto model = sourceModel ( ) ;
auto label = model - > index ( row , AddressTableModel : : Label , parent ) ;
if ( model - > data ( label , AddressTableModel : : TypeRole ) . toString ( ) ! = m_type ) {
return false ;
}
auto address = model - > index ( row , AddressTableModel : : Address , parent ) ;
if ( filterRegExp ( ) . indexIn ( model - > data ( address ) . toString ( ) ) < 0 & &
filterRegExp ( ) . indexIn ( model - > data ( label ) . toString ( ) ) < 0 ) {
return false ;
}
return true ;
}
} ;
2016-09-09 13:43:29 +02:00
AddressBookPage : : AddressBookPage ( const PlatformStyle * platformStyle , Mode _mode , Tabs _tab , QWidget * parent ) :
2011-07-07 17:33:15 +02:00
QDialog ( parent ) ,
ui ( new Ui : : AddressBookPage ) ,
model ( 0 ) ,
2016-09-09 13:43:29 +02:00
mode ( _mode ) ,
tab ( _tab )
2011-07-07 17:33:15 +02:00
{
ui - > setupUi ( this ) ;
2011-10-07 13:21:45 +02:00
2015-07-28 15:20:14 +02:00
if ( ! platformStyle - > getImagesOnButtons ( ) ) {
ui - > newAddress - > setIcon ( QIcon ( ) ) ;
ui - > copyAddress - > setIcon ( QIcon ( ) ) ;
ui - > deleteAddress - > setIcon ( QIcon ( ) ) ;
ui - > exportButton - > setIcon ( QIcon ( ) ) ;
} else {
ui - > newAddress - > setIcon ( platformStyle - > SingleColorIcon ( " :/icons/add " ) ) ;
ui - > copyAddress - > setIcon ( platformStyle - > SingleColorIcon ( " :/icons/editcopy " ) ) ;
ui - > deleteAddress - > setIcon ( platformStyle - > SingleColorIcon ( " :/icons/remove " ) ) ;
ui - > exportButton - > setIcon ( platformStyle - > SingleColorIcon ( " :/icons/export " ) ) ;
}
2011-10-07 13:21:45 +02:00
2011-07-07 17:33:15 +02:00
switch ( mode )
{
2013-10-16 15:14:26 +02:00
case ForSelection :
switch ( tab )
{
case SendingTab : setWindowTitle ( tr ( " Choose the address to send coins to " ) ) ; break ;
case ReceivingTab : setWindowTitle ( tr ( " Choose the address to receive coins with " ) ) ; break ;
}
2011-07-07 18:25:27 +02:00
connect ( ui - > tableView , SIGNAL ( doubleClicked ( QModelIndex ) ) , this , SLOT ( accept ( ) ) ) ;
ui - > tableView - > setEditTriggers ( QAbstractItemView : : NoEditTriggers ) ;
2011-07-07 17:33:15 +02:00
ui - > tableView - > setFocus ( ) ;
2013-10-18 19:42:40 +02:00
ui - > closeButton - > setText ( tr ( " C&hoose " ) ) ;
2013-04-12 12:24:41 +02:00
ui - > exportButton - > hide ( ) ;
2011-07-07 17:33:15 +02:00
break ;
case ForEditing :
2013-10-16 15:14:26 +02:00
switch ( tab )
{
case SendingTab : setWindowTitle ( tr ( " Sending addresses " ) ) ; break ;
case ReceivingTab : setWindowTitle ( tr ( " Receiving addresses " ) ) ; break ;
}
2011-07-07 17:33:15 +02:00
break ;
}
switch ( tab )
{
case SendingTab :
2013-04-02 12:08:13 +02:00
ui - > labelExplanation - > setText ( tr ( " These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins. " ) ) ;
ui - > deleteAddress - > setVisible ( true ) ;
2011-07-07 17:33:15 +02:00
break ;
case ReceivingTab :
2013-10-16 15:14:26 +02:00
ui - > labelExplanation - > setText ( tr ( " These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction. " ) ) ;
2013-04-02 12:08:13 +02:00
ui - > deleteAddress - > setVisible ( false ) ;
2011-07-07 17:33:15 +02:00
break ;
}
2011-07-07 18:25:27 +02:00
2011-12-04 18:01:53 +01:00
// Context menu actions
2013-10-25 14:19:44 +02:00
QAction * copyAddressAction = new QAction ( tr ( " &Copy Address " ) , this ) ;
2013-01-10 08:52:39 +01:00
QAction * copyLabelAction = new QAction ( tr ( " Copy &Label " ) , this ) ;
2012-05-04 17:56:29 +02:00
QAction * editAction = new QAction ( tr ( " &Edit " ) , this ) ;
2013-04-02 12:08:13 +02:00
deleteAction = new QAction ( ui - > deleteAddress - > text ( ) , this ) ;
2011-12-04 18:01:53 +01:00
2012-05-04 17:56:29 +02:00
// Build context menu
2016-11-18 15:47:20 +01:00
contextMenu = new QMenu ( this ) ;
2011-12-04 18:01:53 +01:00
contextMenu - > addAction ( copyAddressAction ) ;
contextMenu - > addAction ( copyLabelAction ) ;
contextMenu - > addAction ( editAction ) ;
2012-05-04 17:56:29 +02:00
if ( tab = = SendingTab )
contextMenu - > addAction ( deleteAction ) ;
contextMenu - > addSeparator ( ) ;
2011-12-04 18:01:53 +01:00
2012-05-04 17:56:29 +02:00
// Connect signals for context menu actions
2013-04-02 12:08:13 +02:00
connect ( copyAddressAction , SIGNAL ( triggered ( ) ) , this , SLOT ( on_copyAddress_clicked ( ) ) ) ;
2011-12-04 18:01:53 +01:00
connect ( copyLabelAction , SIGNAL ( triggered ( ) ) , this , SLOT ( onCopyLabelAction ( ) ) ) ;
connect ( editAction , SIGNAL ( triggered ( ) ) , this , SLOT ( onEditAction ( ) ) ) ;
2013-04-02 12:08:13 +02:00
connect ( deleteAction , SIGNAL ( triggered ( ) ) , this , SLOT ( on_deleteAddress_clicked ( ) ) ) ;
2011-12-04 18:01:53 +01:00
connect ( ui - > tableView , SIGNAL ( customContextMenuRequested ( QPoint ) ) , this , SLOT ( contextualMenu ( QPoint ) ) ) ;
2013-10-18 19:42:40 +02:00
connect ( ui - > closeButton , SIGNAL ( clicked ( ) ) , this , SLOT ( accept ( ) ) ) ;
2011-07-07 17:33:15 +02:00
}
AddressBookPage : : ~ AddressBookPage ( )
{
delete ui ;
}
2016-09-09 13:43:29 +02:00
void AddressBookPage : : setModel ( AddressTableModel * _model )
2011-07-07 17:33:15 +02:00
{
2016-09-09 13:43:29 +02:00
this - > model = _model ;
if ( ! _model )
2011-11-08 21:18:36 +01:00
return ;
2011-07-07 17:33:15 +02:00
2018-01-03 17:00:18 +01:00
auto type = tab = = ReceivingTab ? AddressTableModel : : Receive : AddressTableModel : : Send ;
proxyModel = new AddressBookSortFilterProxyModel ( type , this ) ;
2016-09-09 13:43:29 +02:00
proxyModel - > setSourceModel ( _model ) ;
2018-01-03 17:00:18 +01:00
connect ( ui - > searchLineEdit , SIGNAL ( textChanged ( QString ) ) , proxyModel , SLOT ( setFilterWildcard ( QString ) ) ) ;
2011-07-09 10:53:55 +02:00
ui - > tableView - > setModel ( proxyModel ) ;
ui - > tableView - > sortByColumn ( 0 , Qt : : AscendingOrder ) ;
2011-07-07 17:33:15 +02:00
// Set column widths
2013-05-31 14:02:24 +02:00
# if QT_VERSION < 0x050000
2013-04-02 12:08:13 +02:00
ui - > tableView - > horizontalHeader ( ) - > setResizeMode ( AddressTableModel : : Label , QHeaderView : : Stretch ) ;
ui - > tableView - > horizontalHeader ( ) - > setResizeMode ( AddressTableModel : : Address , QHeaderView : : ResizeToContents ) ;
2013-05-31 14:02:24 +02:00
# else
ui - > tableView - > horizontalHeader ( ) - > setSectionResizeMode ( AddressTableModel : : Label , QHeaderView : : Stretch ) ;
ui - > tableView - > horizontalHeader ( ) - > setSectionResizeMode ( AddressTableModel : : Address , QHeaderView : : ResizeToContents ) ;
# endif
2011-07-07 17:33:15 +02:00
connect ( ui - > tableView - > selectionModel ( ) , SIGNAL ( selectionChanged ( QItemSelection , QItemSelection ) ) ,
2013-10-26 18:45:50 +02:00
this , SLOT ( selectionChanged ( ) ) ) ;
2011-07-07 17:33:15 +02:00
2012-05-06 22:41:35 +02:00
// Select row for newly created address
2016-09-09 13:43:29 +02:00
connect ( _model , SIGNAL ( rowsInserted ( QModelIndex , int , int ) ) , this , SLOT ( selectNewAddress ( QModelIndex , int , int ) ) ) ;
2012-05-06 22:41:35 +02:00
2011-07-07 17:33:15 +02:00
selectionChanged ( ) ;
}
2013-04-02 12:08:13 +02:00
void AddressBookPage : : on_copyAddress_clicked ( )
2011-07-07 17:33:15 +02:00
{
2011-12-04 18:01:53 +01:00
GUIUtil : : copyEntryData ( ui - > tableView , AddressTableModel : : Address ) ;
}
2012-04-01 13:22:13 +02:00
2011-12-04 18:01:53 +01:00
void AddressBookPage : : onCopyLabelAction ( )
{
GUIUtil : : copyEntryData ( ui - > tableView , AddressTableModel : : Label ) ;
}
void AddressBookPage : : onEditAction ( )
{
2013-11-14 19:47:45 +01:00
if ( ! model )
return ;
2011-12-04 18:01:53 +01:00
if ( ! ui - > tableView - > selectionModel ( ) )
return ;
QModelIndexList indexes = ui - > tableView - > selectionModel ( ) - > selectedRows ( ) ;
if ( indexes . isEmpty ( ) )
2011-11-08 21:18:36 +01:00
return ;
2011-07-07 17:33:15 +02:00
2011-12-04 18:01:53 +01:00
EditAddressDialog dlg (
2013-11-14 19:47:45 +01:00
tab = = SendingTab ?
EditAddressDialog : : EditSendingAddress :
EditAddressDialog : : EditReceivingAddress , this ) ;
2011-12-04 18:01:53 +01:00
dlg . setModel ( model ) ;
QModelIndex origIndex = proxyModel - > mapToSource ( indexes . at ( 0 ) ) ;
dlg . loadRow ( origIndex . row ( ) ) ;
dlg . exec ( ) ;
2011-07-07 17:33:15 +02:00
}
2013-04-02 12:08:13 +02:00
void AddressBookPage : : on_newAddress_clicked ( )
2011-07-07 17:33:15 +02:00
{
2011-11-08 21:18:36 +01:00
if ( ! model )
return ;
2013-01-10 08:52:39 +01:00
2011-07-07 17:33:15 +02:00
EditAddressDialog dlg (
2013-11-14 19:47:45 +01:00
tab = = SendingTab ?
EditAddressDialog : : NewSendingAddress :
EditAddressDialog : : NewReceivingAddress , this ) ;
2011-07-07 17:33:15 +02:00
dlg . setModel ( model ) ;
2011-08-04 21:31:47 +02:00
if ( dlg . exec ( ) )
{
2012-05-06 22:41:35 +02:00
newAddressToSelect = dlg . getAddress ( ) ;
2011-08-04 21:31:47 +02:00
}
2011-07-07 17:33:15 +02:00
}
2013-04-02 12:08:13 +02:00
void AddressBookPage : : on_deleteAddress_clicked ( )
2011-07-07 17:33:15 +02:00
{
2011-11-08 21:18:36 +01:00
QTableView * table = ui - > tableView ;
if ( ! table - > selectionModel ( ) )
return ;
2013-01-10 08:52:39 +01:00
2011-07-07 17:33:15 +02:00
QModelIndexList indexes = table - > selectionModel ( ) - > selectedRows ( ) ;
if ( ! indexes . isEmpty ( ) )
{
table - > model ( ) - > removeRow ( indexes . at ( 0 ) . row ( ) ) ;
}
}
void AddressBookPage : : selectionChanged ( )
{
// Set button states based on selected tab and selection
2011-11-08 21:18:36 +01:00
QTableView * table = ui - > tableView ;
if ( ! table - > selectionModel ( ) )
return ;
2011-07-07 17:33:15 +02:00
if ( table - > selectionModel ( ) - > hasSelection ( ) )
{
switch ( tab )
{
case SendingTab :
2011-12-04 18:01:53 +01:00
// In sending tab, allow deletion of selection
2013-04-02 12:08:13 +02:00
ui - > deleteAddress - > setEnabled ( true ) ;
ui - > deleteAddress - > setVisible ( true ) ;
2011-12-04 18:01:53 +01:00
deleteAction - > setEnabled ( true ) ;
2011-07-07 17:33:15 +02:00
break ;
case ReceivingTab :
2011-12-04 18:01:53 +01:00
// Deleting receiving addresses, however, is not allowed
2013-04-02 12:08:13 +02:00
ui - > deleteAddress - > setEnabled ( false ) ;
ui - > deleteAddress - > setVisible ( false ) ;
2011-12-04 18:01:53 +01:00
deleteAction - > setEnabled ( false ) ;
2011-07-07 17:33:15 +02:00
break ;
}
2013-04-02 12:08:13 +02:00
ui - > copyAddress - > setEnabled ( true ) ;
2011-07-07 17:33:15 +02:00
}
else
{
2013-04-02 12:08:13 +02:00
ui - > deleteAddress - > setEnabled ( false ) ;
ui - > copyAddress - > setEnabled ( false ) ;
2011-07-07 17:33:15 +02:00
}
}
void AddressBookPage : : done ( int retval )
{
2011-11-08 21:18:36 +01:00
QTableView * table = ui - > tableView ;
if ( ! table - > selectionModel ( ) | | ! table - > model ( ) )
return ;
2011-07-07 18:25:27 +02:00
// Figure out which address was selected, and return it
QModelIndexList indexes = table - > selectionModel ( ) - > selectedRows ( AddressTableModel : : Address ) ;
2017-06-02 03:25:02 +02:00
for ( const QModelIndex & index : indexes ) {
2011-07-07 18:25:27 +02:00
QVariant address = table - > model ( ) - > data ( index ) ;
returnValue = address . toString ( ) ;
}
if ( returnValue . isEmpty ( ) )
{
2011-12-04 18:01:53 +01:00
// If no address entry selected, return rejected
2011-07-07 18:25:27 +02:00
retval = Rejected ;
}
2011-07-07 17:33:15 +02:00
QDialog : : done ( retval ) ;
}
2011-07-09 10:53:55 +02:00
2013-04-12 12:24:41 +02:00
void AddressBookPage : : on_exportButton_clicked ( )
2011-07-09 10:53:55 +02:00
{
// CSV is currently the only supported format
2013-11-11 22:57:25 +01:00
QString filename = GUIUtil : : getSaveFileName ( this ,
tr ( " Export Address List " ) , QString ( ) ,
2017-08-07 07:36:37 +02:00
tr ( " Comma separated file (*.csv) " ) , nullptr ) ;
2011-07-09 10:53:55 +02:00
2013-10-26 18:45:50 +02:00
if ( filename . isNull ( ) )
return ;
2011-07-15 02:11:11 +02:00
2011-07-09 10:53:55 +02:00
CSVModelWriter writer ( filename ) ;
// name, column, role
writer . setModel ( proxyModel ) ;
writer . addColumn ( " Label " , AddressTableModel : : Label , Qt : : EditRole ) ;
writer . addColumn ( " Address " , AddressTableModel : : Address , Qt : : EditRole ) ;
2013-10-26 18:45:50 +02:00
if ( ! writer . write ( ) ) {
QMessageBox : : critical ( this , tr ( " Exporting Failed " ) ,
2014-07-14 20:22:35 +02:00
tr ( " There was an error trying to save the address list to %1. Please try again. " ) . arg ( filename ) ) ;
2011-07-09 10:53:55 +02:00
}
}
2011-11-10 15:20:17 +01:00
2011-12-04 18:01:53 +01:00
void AddressBookPage : : contextualMenu ( const QPoint & point )
{
QModelIndex index = ui - > tableView - > indexAt ( point ) ;
if ( index . isValid ( ) )
{
contextMenu - > exec ( QCursor : : pos ( ) ) ;
}
}
2012-05-06 22:41:35 +02:00
2012-12-15 11:15:19 +01:00
void AddressBookPage : : selectNewAddress ( const QModelIndex & parent , int begin , int /*end*/ )
2012-05-06 22:41:35 +02:00
{
QModelIndex idx = proxyModel - > mapFromSource ( model - > index ( begin , AddressTableModel : : Address , parent ) ) ;
if ( idx . isValid ( ) & & ( idx . data ( Qt : : EditRole ) . toString ( ) = = newAddressToSelect ) )
{
// Select row of newly created address, once
ui - > tableView - > setFocus ( ) ;
ui - > tableView - > selectRow ( idx . row ( ) ) ;
newAddressToSelect . clear ( ) ;
}
}