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