mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-14 12:10:42 +02:00

bitcoin-config.h moved, but the old file is likely to still exist when reconfiguring or switching branches. This would've caused files to not rebuild correctly, and other strange problems. Make the path explicit so that the old one cannot be found. Core libs use config/bitcoin-config.h. Libs (like crypto) which don't want access to bitcoin's headers continue to use -Iconfig and #include bitcoin-config.h.
309 lines
9.4 KiB
C++
309 lines
9.4 KiB
C++
// Copyright (c) 2011-2013 The Bitcoin developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include "config/bitcoin-config.h"
|
|
#endif
|
|
|
|
#include "addressbookpage.h"
|
|
#include "ui_addressbookpage.h"
|
|
|
|
#include "addresstablemodel.h"
|
|
#include "bitcoingui.h"
|
|
#include "csvmodelwriter.h"
|
|
#include "editaddressdialog.h"
|
|
#include "guiutil.h"
|
|
|
|
#include <QIcon>
|
|
#include <QMenu>
|
|
#include <QMessageBox>
|
|
#include <QSortFilterProxyModel>
|
|
|
|
AddressBookPage::AddressBookPage(Mode mode, Tabs tab, QWidget *parent) :
|
|
QDialog(parent),
|
|
ui(new Ui::AddressBookPage),
|
|
model(0),
|
|
mode(mode),
|
|
tab(tab)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
#ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
|
|
ui->newAddress->setIcon(QIcon());
|
|
ui->copyAddress->setIcon(QIcon());
|
|
ui->deleteAddress->setIcon(QIcon());
|
|
ui->exportButton->setIcon(QIcon());
|
|
#endif
|
|
|
|
switch(mode)
|
|
{
|
|
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;
|
|
}
|
|
connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
|
|
ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
|
ui->tableView->setFocus();
|
|
ui->closeButton->setText(tr("C&hoose"));
|
|
ui->exportButton->hide();
|
|
break;
|
|
case ForEditing:
|
|
switch(tab)
|
|
{
|
|
case SendingTab: setWindowTitle(tr("Sending addresses")); break;
|
|
case ReceivingTab: setWindowTitle(tr("Receiving addresses")); break;
|
|
}
|
|
break;
|
|
}
|
|
switch(tab)
|
|
{
|
|
case SendingTab:
|
|
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);
|
|
break;
|
|
case ReceivingTab:
|
|
ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction."));
|
|
ui->deleteAddress->setVisible(false);
|
|
break;
|
|
}
|
|
|
|
// Context menu actions
|
|
QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
|
|
QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
|
|
QAction *editAction = new QAction(tr("&Edit"), this);
|
|
deleteAction = new QAction(ui->deleteAddress->text(), this);
|
|
|
|
// Build context menu
|
|
contextMenu = new QMenu();
|
|
contextMenu->addAction(copyAddressAction);
|
|
contextMenu->addAction(copyLabelAction);
|
|
contextMenu->addAction(editAction);
|
|
if(tab == SendingTab)
|
|
contextMenu->addAction(deleteAction);
|
|
contextMenu->addSeparator();
|
|
|
|
// Connect signals for context menu actions
|
|
connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyAddress_clicked()));
|
|
connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
|
|
connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
|
|
connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteAddress_clicked()));
|
|
|
|
connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
|
|
|
|
connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(accept()));
|
|
}
|
|
|
|
AddressBookPage::~AddressBookPage()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void AddressBookPage::setModel(AddressTableModel *model)
|
|
{
|
|
this->model = model;
|
|
if(!model)
|
|
return;
|
|
|
|
proxyModel = new QSortFilterProxyModel(this);
|
|
proxyModel->setSourceModel(model);
|
|
proxyModel->setDynamicSortFilter(true);
|
|
proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
|
|
proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
switch(tab)
|
|
{
|
|
case ReceivingTab:
|
|
// Receive filter
|
|
proxyModel->setFilterRole(AddressTableModel::TypeRole);
|
|
proxyModel->setFilterFixedString(AddressTableModel::Receive);
|
|
break;
|
|
case SendingTab:
|
|
// Send filter
|
|
proxyModel->setFilterRole(AddressTableModel::TypeRole);
|
|
proxyModel->setFilterFixedString(AddressTableModel::Send);
|
|
break;
|
|
}
|
|
ui->tableView->setModel(proxyModel);
|
|
ui->tableView->sortByColumn(0, Qt::AscendingOrder);
|
|
|
|
// Set column widths
|
|
#if QT_VERSION < 0x050000
|
|
ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
|
|
ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
|
|
#else
|
|
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
|
|
ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
|
|
#endif
|
|
|
|
connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
|
|
this, SLOT(selectionChanged()));
|
|
|
|
// Select row for newly created address
|
|
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int)));
|
|
|
|
selectionChanged();
|
|
}
|
|
|
|
void AddressBookPage::on_copyAddress_clicked()
|
|
{
|
|
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Address);
|
|
}
|
|
|
|
void AddressBookPage::onCopyLabelAction()
|
|
{
|
|
GUIUtil::copyEntryData(ui->tableView, AddressTableModel::Label);
|
|
}
|
|
|
|
void AddressBookPage::onEditAction()
|
|
{
|
|
if(!model)
|
|
return;
|
|
|
|
if(!ui->tableView->selectionModel())
|
|
return;
|
|
QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
|
|
if(indexes.isEmpty())
|
|
return;
|
|
|
|
EditAddressDialog dlg(
|
|
tab == SendingTab ?
|
|
EditAddressDialog::EditSendingAddress :
|
|
EditAddressDialog::EditReceivingAddress, this);
|
|
dlg.setModel(model);
|
|
QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
|
|
dlg.loadRow(origIndex.row());
|
|
dlg.exec();
|
|
}
|
|
|
|
void AddressBookPage::on_newAddress_clicked()
|
|
{
|
|
if(!model)
|
|
return;
|
|
|
|
EditAddressDialog dlg(
|
|
tab == SendingTab ?
|
|
EditAddressDialog::NewSendingAddress :
|
|
EditAddressDialog::NewReceivingAddress, this);
|
|
dlg.setModel(model);
|
|
if(dlg.exec())
|
|
{
|
|
newAddressToSelect = dlg.getAddress();
|
|
}
|
|
}
|
|
|
|
void AddressBookPage::on_deleteAddress_clicked()
|
|
{
|
|
QTableView *table = ui->tableView;
|
|
if(!table->selectionModel())
|
|
return;
|
|
|
|
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
|
|
QTableView *table = ui->tableView;
|
|
if(!table->selectionModel())
|
|
return;
|
|
|
|
if(table->selectionModel()->hasSelection())
|
|
{
|
|
switch(tab)
|
|
{
|
|
case SendingTab:
|
|
// In sending tab, allow deletion of selection
|
|
ui->deleteAddress->setEnabled(true);
|
|
ui->deleteAddress->setVisible(true);
|
|
deleteAction->setEnabled(true);
|
|
break;
|
|
case ReceivingTab:
|
|
// Deleting receiving addresses, however, is not allowed
|
|
ui->deleteAddress->setEnabled(false);
|
|
ui->deleteAddress->setVisible(false);
|
|
deleteAction->setEnabled(false);
|
|
break;
|
|
}
|
|
ui->copyAddress->setEnabled(true);
|
|
}
|
|
else
|
|
{
|
|
ui->deleteAddress->setEnabled(false);
|
|
ui->copyAddress->setEnabled(false);
|
|
}
|
|
}
|
|
|
|
void AddressBookPage::done(int retval)
|
|
{
|
|
QTableView *table = ui->tableView;
|
|
if(!table->selectionModel() || !table->model())
|
|
return;
|
|
|
|
// Figure out which address was selected, and return it
|
|
QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
|
|
|
|
foreach (QModelIndex index, indexes)
|
|
{
|
|
QVariant address = table->model()->data(index);
|
|
returnValue = address.toString();
|
|
}
|
|
|
|
if(returnValue.isEmpty())
|
|
{
|
|
// If no address entry selected, return rejected
|
|
retval = Rejected;
|
|
}
|
|
|
|
QDialog::done(retval);
|
|
}
|
|
|
|
void AddressBookPage::on_exportButton_clicked()
|
|
{
|
|
// CSV is currently the only supported format
|
|
QString filename = GUIUtil::getSaveFileName(this,
|
|
tr("Export Address List"), QString(),
|
|
tr("Comma separated file (*.csv)"), NULL);
|
|
|
|
if (filename.isNull())
|
|
return;
|
|
|
|
CSVModelWriter writer(filename);
|
|
|
|
// name, column, role
|
|
writer.setModel(proxyModel);
|
|
writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
|
|
writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);
|
|
|
|
if(!writer.write()) {
|
|
QMessageBox::critical(this, tr("Exporting Failed"),
|
|
tr("There was an error trying to save the address list to %1.").arg(filename));
|
|
}
|
|
}
|
|
|
|
void AddressBookPage::contextualMenu(const QPoint &point)
|
|
{
|
|
QModelIndex index = ui->tableView->indexAt(point);
|
|
if(index.isValid())
|
|
{
|
|
contextMenu->exec(QCursor::pos());
|
|
}
|
|
}
|
|
|
|
void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int /*end*/)
|
|
{
|
|
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();
|
|
}
|
|
}
|