Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
addressbookpage.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2013 The Bitcoin developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #if defined(HAVE_CONFIG_H)
6 #include "bitcoin-config.h"
7 #endif
8 
9 #include "addressbookpage.h"
10 #include "ui_addressbookpage.h"
11 
12 #include "addresstablemodel.h"
13 #include "bitcoingui.h"
14 #include "csvmodelwriter.h"
15 #include "editaddressdialog.h"
16 #include "guiutil.h"
17 
18 #include <QIcon>
19 #include <QMenu>
20 #include <QMessageBox>
21 #include <QSortFilterProxyModel>
22 
24  QDialog(parent),
25  ui(new Ui::AddressBookPage),
26  model(0),
27  mode(mode),
28  tab(tab)
29 {
30  ui->setupUi(this);
31 
32 #ifdef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
33  ui->newAddress->setIcon(QIcon());
34  ui->copyAddress->setIcon(QIcon());
35  ui->deleteAddress->setIcon(QIcon());
36  ui->exportButton->setIcon(QIcon());
37 #endif
38 
39  switch(mode)
40  {
41  case ForSelection:
42  switch(tab)
43  {
44  case SendingTab: setWindowTitle(tr("Choose the address to send coins to")); break;
45  case ReceivingTab: setWindowTitle(tr("Choose the address to receive coins with")); break;
46  }
47  connect(ui->tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(accept()));
48  ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
49  ui->tableView->setFocus();
50  ui->closeButton->setText(tr("C&hoose"));
51  ui->exportButton->hide();
52  break;
53  case ForEditing:
54  switch(tab)
55  {
56  case SendingTab: setWindowTitle(tr("Sending addresses")); break;
57  case ReceivingTab: setWindowTitle(tr("Receiving addresses")); break;
58  }
59  break;
60  }
61  switch(tab)
62  {
63  case SendingTab:
64  ui->labelExplanation->setText(tr("These are your Bitcoin addresses for sending payments. Always check the amount and the receiving address before sending coins."));
65  ui->deleteAddress->setVisible(true);
66  break;
67  case ReceivingTab:
68  ui->labelExplanation->setText(tr("These are your Bitcoin addresses for receiving payments. It is recommended to use a new receiving address for each transaction."));
69  ui->deleteAddress->setVisible(false);
70  break;
71  }
72 
73  // Context menu actions
74  QAction *copyAddressAction = new QAction(tr("&Copy Address"), this);
75  QAction *copyLabelAction = new QAction(tr("Copy &Label"), this);
76  QAction *editAction = new QAction(tr("&Edit"), this);
77  deleteAction = new QAction(ui->deleteAddress->text(), this);
78 
79  // Build context menu
80  contextMenu = new QMenu();
81  contextMenu->addAction(copyAddressAction);
82  contextMenu->addAction(copyLabelAction);
83  contextMenu->addAction(editAction);
84  if(tab == SendingTab)
85  contextMenu->addAction(deleteAction);
86  contextMenu->addSeparator();
87 
88  // Connect signals for context menu actions
89  connect(copyAddressAction, SIGNAL(triggered()), this, SLOT(on_copyAddress_clicked()));
90  connect(copyLabelAction, SIGNAL(triggered()), this, SLOT(onCopyLabelAction()));
91  connect(editAction, SIGNAL(triggered()), this, SLOT(onEditAction()));
92  connect(deleteAction, SIGNAL(triggered()), this, SLOT(on_deleteAddress_clicked()));
93 
94  connect(ui->tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextualMenu(QPoint)));
95 
96  connect(ui->closeButton, SIGNAL(clicked()), this, SLOT(accept()));
97 }
98 
100 {
101  delete ui;
102 }
103 
105 {
106  this->model = model;
107  if(!model)
108  return;
109 
110  proxyModel = new QSortFilterProxyModel(this);
111  proxyModel->setSourceModel(model);
112  proxyModel->setDynamicSortFilter(true);
113  proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
114  proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
115  switch(tab)
116  {
117  case ReceivingTab:
118  // Receive filter
119  proxyModel->setFilterRole(AddressTableModel::TypeRole);
120  proxyModel->setFilterFixedString(AddressTableModel::Receive);
121  break;
122  case SendingTab:
123  // Send filter
124  proxyModel->setFilterRole(AddressTableModel::TypeRole);
125  proxyModel->setFilterFixedString(AddressTableModel::Send);
126  break;
127  }
128  ui->tableView->setModel(proxyModel);
129  ui->tableView->sortByColumn(0, Qt::AscendingOrder);
130 
131  // Set column widths
132 #if QT_VERSION < 0x050000
133  ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
134  ui->tableView->horizontalHeader()->setResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
135 #else
136  ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Label, QHeaderView::Stretch);
137  ui->tableView->horizontalHeader()->setSectionResizeMode(AddressTableModel::Address, QHeaderView::ResizeToContents);
138 #endif
139 
140  connect(ui->tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
141  this, SLOT(selectionChanged()));
142 
143  // Select row for newly created address
144  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(selectNewAddress(QModelIndex,int,int)));
145 
147 }
148 
150 {
152 }
153 
155 {
157 }
158 
160 {
161  if(!model)
162  return;
163 
164  if(!ui->tableView->selectionModel())
165  return;
166  QModelIndexList indexes = ui->tableView->selectionModel()->selectedRows();
167  if(indexes.isEmpty())
168  return;
169 
170  EditAddressDialog dlg(
171  tab == SendingTab ?
174  dlg.setModel(model);
175  QModelIndex origIndex = proxyModel->mapToSource(indexes.at(0));
176  dlg.loadRow(origIndex.row());
177  dlg.exec();
178 }
179 
181 {
182  if(!model)
183  return;
184 
185  EditAddressDialog dlg(
186  tab == SendingTab ?
189  dlg.setModel(model);
190  if(dlg.exec())
191  {
193  }
194 }
195 
197 {
198  QTableView *table = ui->tableView;
199  if(!table->selectionModel())
200  return;
201 
202  QModelIndexList indexes = table->selectionModel()->selectedRows();
203  if(!indexes.isEmpty())
204  {
205  table->model()->removeRow(indexes.at(0).row());
206  }
207 }
208 
210 {
211  // Set button states based on selected tab and selection
212  QTableView *table = ui->tableView;
213  if(!table->selectionModel())
214  return;
215 
216  if(table->selectionModel()->hasSelection())
217  {
218  switch(tab)
219  {
220  case SendingTab:
221  // In sending tab, allow deletion of selection
222  ui->deleteAddress->setEnabled(true);
223  ui->deleteAddress->setVisible(true);
224  deleteAction->setEnabled(true);
225  break;
226  case ReceivingTab:
227  // Deleting receiving addresses, however, is not allowed
228  ui->deleteAddress->setEnabled(false);
229  ui->deleteAddress->setVisible(false);
230  deleteAction->setEnabled(false);
231  break;
232  }
233  ui->copyAddress->setEnabled(true);
234  }
235  else
236  {
237  ui->deleteAddress->setEnabled(false);
238  ui->copyAddress->setEnabled(false);
239  }
240 }
241 
242 void AddressBookPage::done(int retval)
243 {
244  QTableView *table = ui->tableView;
245  if(!table->selectionModel() || !table->model())
246  return;
247 
248  // Figure out which address was selected, and return it
249  QModelIndexList indexes = table->selectionModel()->selectedRows(AddressTableModel::Address);
250 
251  foreach (QModelIndex index, indexes)
252  {
253  QVariant address = table->model()->data(index);
254  returnValue = address.toString();
255  }
256 
257  if(returnValue.isEmpty())
258  {
259  // If no address entry selected, return rejected
260  retval = Rejected;
261  }
262 
263  QDialog::done(retval);
264 }
265 
267 {
268  // CSV is currently the only supported format
269  QString filename = GUIUtil::getSaveFileName(this,
270  tr("Export Address List"), QString(),
271  tr("Comma separated file (*.csv)"), NULL);
272 
273  if (filename.isNull())
274  return;
275 
276  CSVModelWriter writer(filename);
277 
278  // name, column, role
279  writer.setModel(proxyModel);
280  writer.addColumn("Label", AddressTableModel::Label, Qt::EditRole);
281  writer.addColumn("Address", AddressTableModel::Address, Qt::EditRole);
282 
283  if(!writer.write()) {
284  QMessageBox::critical(this, tr("Exporting Failed"),
285  tr("There was an error trying to save the address list to %1.").arg(filename));
286  }
287 }
288 
289 void AddressBookPage::contextualMenu(const QPoint &point)
290 {
291  QModelIndex index = ui->tableView->indexAt(point);
292  if(index.isValid())
293  {
294  contextMenu->exec(QCursor::pos());
295  }
296 }
297 
298 void AddressBookPage::selectNewAddress(const QModelIndex &parent, int begin, int /*end*/)
299 {
300  QModelIndex idx = proxyModel->mapFromSource(model->index(begin, AddressTableModel::Address, parent));
301  if(idx.isValid() && (idx.data(Qt::EditRole).toString() == newAddressToSelect))
302  {
303  // Select row of newly created address, once
304  ui->tableView->setFocus();
305  ui->tableView->selectRow(idx.row());
306  newAddressToSelect.clear();
307  }
308 }
void on_newAddress_clicked()
Create a new address for receiving coins and / or add a new address book entry.
void onCopyLabelAction()
Copy label of currently selected address entry to clipboard (no button)
void addColumn(const QString &title, int column, int role=Qt::EditRole)
QModelIndex index(int row, int column, const QModelIndex &parent) const
QString getAddress() const
void setModel(AddressTableModel *model)
QPushButton * newAddress
void onEditAction()
Edit currently selected address entry (no button)
AddressTableModel * model
QPushButton * copyAddress
QSortFilterProxyModel * proxyModel
void on_exportButton_clicked()
Export button clicked.
Open address book for editing.
Open address book to pick address.
Export a Qt table model to a CSV file.
QString newAddressToSelect
AddressBookPage(Mode mode, Tabs tab, QWidget *parent)
Ui::AddressBookPage * ui
static const QString Send
Specifies send address.
void selectNewAddress(const QModelIndex &parent, int begin, int)
New entry/entries were added to address table.
QAction * deleteAction
QPushButton * closeButton
void setModel(AddressTableModel *model)
void done(int retval)
void setupUi(QWidget *AddressBookPage)
QPushButton * deleteAddress
void on_copyAddress_clicked()
Copy address of currently selected address entry to clipboard.
Widget that shows a list of sending or receiving addresses.
Qt model of the address book in the core.
void selectionChanged()
Set button states based on selected tab and selection.
QPushButton * exportButton
void setModel(const QAbstractItemModel *model)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:254
static const QString Receive
Specifies receive address.
Dialog for editing an address and associated information.
User specified label.
void copyEntryData(QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
Definition: guiutil.cpp:241
void contextualMenu(const QPoint &point)
Spawn contextual menu (right mouse menu) for address book entry.
void on_deleteAddress_clicked()
Delete currently selected address entry.
bool write()
Perform export of the model to CSV.
Type of address (Send or Receive)