1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 #if defined(HAVE_CONFIG_H)
6 #include "config/bitcoin-config.h"
9 #include "addressbookpage.h"
10 #include "ui_addressbookpage.h"
12 #include "addresstablemodel.h"
13 #include "bitcoingui.h"
14 #include "csvmodelwriter.h"
15 #include "editaddressdialog.h"
17 #include "platformstyle.h"
21 #include <QMessageBox>
22 #include <QSortFilterProxyModel>
24 AddressBookPage::AddressBookPage(const PlatformStyle
*platformStyle
, Mode _mode
, Tabs _tab
, QWidget
*parent
) :
26 ui(new Ui::AddressBookPage
),
33 if (!platformStyle
->getImagesOnButtons()) {
34 ui
->newAddress
->setIcon(QIcon());
35 ui
->copyAddress
->setIcon(QIcon());
36 ui
->deleteAddress
->setIcon(QIcon());
37 ui
->exportButton
->setIcon(QIcon());
39 ui
->newAddress
->setIcon(platformStyle
->SingleColorIcon(":/icons/add"));
40 ui
->copyAddress
->setIcon(platformStyle
->SingleColorIcon(":/icons/editcopy"));
41 ui
->deleteAddress
->setIcon(platformStyle
->SingleColorIcon(":/icons/remove"));
42 ui
->exportButton
->setIcon(platformStyle
->SingleColorIcon(":/icons/export"));
50 case SendingTab
: setWindowTitle(tr("Choose the address to send coins to")); break;
51 case ReceivingTab
: setWindowTitle(tr("Choose the address to receive coins with")); break;
53 connect(ui
->tableView
, SIGNAL(doubleClicked(QModelIndex
)), this, SLOT(accept()));
54 ui
->tableView
->setEditTriggers(QAbstractItemView::NoEditTriggers
);
55 ui
->tableView
->setFocus();
56 ui
->closeButton
->setText(tr("C&hoose"));
57 ui
->exportButton
->hide();
62 case SendingTab
: setWindowTitle(tr("Sending addresses")); break;
63 case ReceivingTab
: setWindowTitle(tr("Receiving addresses")); break;
70 ui
->labelExplanation
->setText(tr("These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins."));
71 ui
->deleteAddress
->setVisible(true);
74 ui
->labelExplanation
->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction."));
75 ui
->deleteAddress
->setVisible(false);
79 // Context menu actions
80 QAction
*copyAddressAction
= new QAction(tr("&Copy Address"), this);
81 QAction
*copyLabelAction
= new QAction(tr("Copy &Label"), this);
82 QAction
*editAction
= new QAction(tr("&Edit"), this);
83 deleteAction
= new QAction(ui
->deleteAddress
->text(), this);
86 contextMenu
= new QMenu(this);
87 contextMenu
->addAction(copyAddressAction
);
88 contextMenu
->addAction(copyLabelAction
);
89 contextMenu
->addAction(editAction
);
91 contextMenu
->addAction(deleteAction
);
92 contextMenu
->addSeparator();
94 // Connect signals for context menu actions
95 connect(copyAddressAction
, SIGNAL(triggered()), this, SLOT(on_copyAddress_clicked()));
96 connect(copyLabelAction
, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
97 connect(editAction
, SIGNAL(triggered()), this, SLOT(onEditAction()));
98 connect(deleteAction
, SIGNAL(triggered()), this, SLOT(on_deleteAddress_clicked()));
100 connect(ui
->tableView
, SIGNAL(customContextMenuRequested(QPoint
)), this, SLOT(contextualMenu(QPoint
)));
102 connect(ui
->closeButton
, SIGNAL(clicked()), this, SLOT(accept()));
105 AddressBookPage::~AddressBookPage()
110 void AddressBookPage::setModel(AddressTableModel
*_model
)
112 this->model
= _model
;
116 proxyModel
= new QSortFilterProxyModel(this);
117 proxyModel
->setSourceModel(_model
);
118 proxyModel
->setDynamicSortFilter(true);
119 proxyModel
->setSortCaseSensitivity(Qt::CaseInsensitive
);
120 proxyModel
->setFilterCaseSensitivity(Qt::CaseInsensitive
);
125 proxyModel
->setFilterRole(AddressTableModel::TypeRole
);
126 proxyModel
->setFilterFixedString(AddressTableModel::Receive
);
130 proxyModel
->setFilterRole(AddressTableModel::TypeRole
);
131 proxyModel
->setFilterFixedString(AddressTableModel::Send
);
134 ui
->tableView
->setModel(proxyModel
);
135 ui
->tableView
->sortByColumn(0, Qt::AscendingOrder
);
138 #if QT_VERSION < 0x050000
139 ui
->tableView
->horizontalHeader()->setResizeMode(AddressTableModel::Label
, QHeaderView::Stretch
);
140 ui
->tableView
->horizontalHeader()->setResizeMode(AddressTableModel::Address
, QHeaderView::ResizeToContents
);
142 ui
->tableView
->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label
, QHeaderView::Stretch
);
143 ui
->tableView
->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address
, QHeaderView::ResizeToContents
);
146 connect(ui
->tableView
->selectionModel(), SIGNAL(selectionChanged(QItemSelection
,QItemSelection
)),
147 this, SLOT(selectionChanged()));
149 // Select row for newly created address
150 connect(_model
, SIGNAL(rowsInserted(QModelIndex
,int,int)), this, SLOT(selectNewAddress(QModelIndex
,int,int)));
155 void AddressBookPage::on_copyAddress_clicked()
157 GUIUtil::copyEntryData(ui
->tableView
, AddressTableModel::Address
);
160 void AddressBookPage::onCopyLabelAction()
162 GUIUtil::copyEntryData(ui
->tableView
, AddressTableModel::Label
);
165 void AddressBookPage::onEditAction()
170 if(!ui
->tableView
->selectionModel())
172 QModelIndexList indexes
= ui
->tableView
->selectionModel()->selectedRows();
173 if(indexes
.isEmpty())
176 EditAddressDialog
dlg(
178 EditAddressDialog::EditSendingAddress
:
179 EditAddressDialog::EditReceivingAddress
, this);
181 QModelIndex origIndex
= proxyModel
->mapToSource(indexes
.at(0));
182 dlg
.loadRow(origIndex
.row());
186 void AddressBookPage::on_newAddress_clicked()
191 EditAddressDialog
dlg(
193 EditAddressDialog::NewSendingAddress
:
194 EditAddressDialog::NewReceivingAddress
, this);
198 newAddressToSelect
= dlg
.getAddress();
202 void AddressBookPage::on_deleteAddress_clicked()
204 QTableView
*table
= ui
->tableView
;
205 if(!table
->selectionModel())
208 QModelIndexList indexes
= table
->selectionModel()->selectedRows();
209 if(!indexes
.isEmpty())
211 table
->model()->removeRow(indexes
.at(0).row());
215 void AddressBookPage::selectionChanged()
217 // Set button states based on selected tab and selection
218 QTableView
*table
= ui
->tableView
;
219 if(!table
->selectionModel())
222 if(table
->selectionModel()->hasSelection())
227 // In sending tab, allow deletion of selection
228 ui
->deleteAddress
->setEnabled(true);
229 ui
->deleteAddress
->setVisible(true);
230 deleteAction
->setEnabled(true);
233 // Deleting receiving addresses, however, is not allowed
234 ui
->deleteAddress
->setEnabled(false);
235 ui
->deleteAddress
->setVisible(false);
236 deleteAction
->setEnabled(false);
239 ui
->copyAddress
->setEnabled(true);
243 ui
->deleteAddress
->setEnabled(false);
244 ui
->copyAddress
->setEnabled(false);
248 void AddressBookPage::done(int retval
)
250 QTableView
*table
= ui
->tableView
;
251 if(!table
->selectionModel() || !table
->model())
254 // Figure out which address was selected, and return it
255 QModelIndexList indexes
= table
->selectionModel()->selectedRows(AddressTableModel::Address
);
257 Q_FOREACH (const QModelIndex
& index
, indexes
) {
258 QVariant address
= table
->model()->data(index
);
259 returnValue
= address
.toString();
262 if(returnValue
.isEmpty())
264 // If no address entry selected, return rejected
268 QDialog::done(retval
);
271 void AddressBookPage::on_exportButton_clicked()
273 // CSV is currently the only supported format
274 QString filename
= GUIUtil::getSaveFileName(this,
275 tr("Export Address List"), QString(),
276 tr("Comma separated file (*.csv)"), NULL
);
278 if (filename
.isNull())
281 CSVModelWriter
writer(filename
);
283 // name, column, role
284 writer
.setModel(proxyModel
);
285 writer
.addColumn("Label", AddressTableModel::Label
, Qt::EditRole
);
286 writer
.addColumn("Address", AddressTableModel::Address
, Qt::EditRole
);
288 if(!writer
.write()) {
289 QMessageBox::critical(this, tr("Exporting Failed"),
290 tr("There was an error trying to save the address list to %1. Please try again.").arg(filename
));
294 void AddressBookPage::contextualMenu(const QPoint
&point
)
296 QModelIndex index
= ui
->tableView
->indexAt(point
);
299 contextMenu
->exec(QCursor::pos());
303 void AddressBookPage::selectNewAddress(const QModelIndex
&parent
, int begin
, int /*end*/)
305 QModelIndex idx
= proxyModel
->mapFromSource(model
->index(begin
, AddressTableModel::Address
, parent
));
306 if(idx
.isValid() && (idx
.data(Qt::EditRole
).toString() == newAddressToSelect
))
308 // Select row of newly created address, once
309 ui
->tableView
->setFocus();
310 ui
->tableView
->selectRow(idx
.row());
311 newAddressToSelect
.clear();