1 #include "addresstablemodel.h"
3 #include "walletmodel.h"
10 const QString AddressTableModel::Send = "S";
11 const QString AddressTableModel::Receive = "R";
13 struct AddressTableEntry
24 AddressTableEntry() {}
25 AddressTableEntry(Type type, const QString &label, const QString &address):
26 type(type), label(label), address(address) {}
29 // Private implementation
30 struct AddressTablePriv
33 QList<AddressTableEntry> cachedAddressTable;
35 AddressTablePriv(CWallet *wallet):
38 void refreshAddressTable()
40 cachedAddressTable.clear();
42 CRITICAL_BLOCK(cs_mapPubKeys)
43 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
45 BOOST_FOREACH(const PAIRTYPE(std::string, std::string)& item, wallet->mapAddressBook)
47 std::string strAddress = item.first;
48 std::string strName = item.second;
50 bool fMine = (AddressToHash160(strAddress, hash160) && mapPubKeys.count(hash160));
51 cachedAddressTable.append(AddressTableEntry(fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending,
52 QString::fromStdString(strName),
53 QString::fromStdString(strAddress)));
60 return cachedAddressTable.size();
63 AddressTableEntry *index(int idx)
65 if(idx >= 0 && idx < cachedAddressTable.size())
67 return &cachedAddressTable[idx];
76 AddressTableModel::AddressTableModel(CWallet *wallet, WalletModel *parent) :
77 QAbstractTableModel(parent),walletModel(parent),wallet(wallet),priv(0)
79 columns << tr("Label") << tr("Address");
80 priv = new AddressTablePriv(wallet);
81 priv->refreshAddressTable();
84 AddressTableModel::~AddressTableModel()
89 int AddressTableModel::rowCount(const QModelIndex &parent) const
95 int AddressTableModel::columnCount(const QModelIndex &parent) const
98 return columns.length();
101 QVariant AddressTableModel::data(const QModelIndex &index, int role) const
106 AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
108 if(role == Qt::DisplayRole || role == Qt::EditRole)
110 switch(index.column())
113 if(rec->label.isEmpty() && role == Qt::DisplayRole)
115 return tr("(no label)");
125 else if (role == Qt::FontRole)
128 if(index.column() == Address)
130 font = GUIUtil::bitcoinAddressFont();
134 else if (role == TypeRole)
138 case AddressTableEntry::Sending:
140 case AddressTableEntry::Receiving:
148 bool AddressTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
152 AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
156 if(role == Qt::EditRole)
158 switch(index.column())
161 wallet->SetAddressBookName(rec->address.toStdString(), value.toString().toStdString());
162 rec->label = value.toString();
165 // Refuse to set invalid address
166 if(!walletModel->validateAddress(value.toString()))
168 editStatus = INVALID_ADDRESS;
171 // Double-check that we're not overwriting receiving address
172 if(rec->type == AddressTableEntry::Sending)
174 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
177 wallet->DelAddressBookName(rec->address.toStdString());
178 // Add new entry with new address
179 wallet->SetAddressBookName(value.toString().toStdString(), rec->label.toStdString());
182 rec->address = value.toString();
186 emit dataChanged(index, index);
193 QVariant AddressTableModel::headerData(int section, Qt::Orientation orientation, int role) const
195 if(orientation == Qt::Horizontal)
197 if(role == Qt::DisplayRole)
199 return columns[section];
205 Qt::ItemFlags AddressTableModel::flags(const QModelIndex & index) const
209 AddressTableEntry *rec = static_cast<AddressTableEntry*>(index.internalPointer());
211 Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
212 // Can edit address and label for sending addresses,
213 // and only label for receiving addresses.
214 if(rec->type == AddressTableEntry::Sending ||
215 (rec->type == AddressTableEntry::Receiving && index.column()==Label))
217 retval |= Qt::ItemIsEditable;
222 QModelIndex AddressTableModel::index(int row, int column, const QModelIndex & parent) const
225 AddressTableEntry *data = priv->index(row);
228 return createIndex(row, column, priv->index(row));
232 return QModelIndex();
236 void AddressTableModel::updateList()
238 // Update internal model from Bitcoin core
240 priv->refreshAddressTable();
244 QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
246 std::string strLabel = label.toStdString();
247 std::string strAddress = address.toStdString();
254 if(!walletModel->validateAddress(address))
256 editStatus = INVALID_ADDRESS;
259 // Check for duplicate
260 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
262 if(wallet->mapAddressBook.count(strAddress))
264 editStatus = DUPLICATE_ADDRESS;
269 else if(type == Receive)
271 // Generate a new address to associate with given label, optionally
272 // set as default receiving address.
273 strAddress = PubKeyToAddress(wallet->GetOrReuseKeyFromPool());
279 // Add entry and update list
280 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
281 wallet->SetAddressBookName(strAddress, strLabel);
283 return QString::fromStdString(strAddress);
286 bool AddressTableModel::removeRows(int row, int count, const QModelIndex & parent)
289 AddressTableEntry *rec = priv->index(row);
290 if(count != 1 || !rec || rec->type == AddressTableEntry::Receiving)
292 // Can only remove one row at a time, and cannot remove rows not in model.
293 // Also refuse to remove receiving addresses.
296 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
298 wallet->DelAddressBookName(rec->address.toStdString());
304 void AddressTableModel::update()
309 /* Look up label for address in address book, if not found return empty string.
311 QString AddressTableModel::labelForAddress(const QString &address) const
313 CRITICAL_BLOCK(wallet->cs_mapAddressBook)
315 std::map<std::string, std::string>::iterator mi = wallet->mapAddressBook.find(address.toStdString());
316 if (mi != wallet->mapAddressBook.end())
318 return QString::fromStdString(mi->second);
324 int AddressTableModel::lookupAddress(const QString &address) const
326 QModelIndexList lst = match(index(0, Address, QModelIndex()),
327 Qt::EditRole, address, 1, Qt::MatchExactly);
334 return lst.at(0).row();