this->setEnabled(true);
// receive page
- m_wallet->subaddress()->refresh(m_wallet->currentSubaddressAccount());
+ m_wallet->subaddress()->refresh();
if (m_wallet->subaddress()->count() == 1) {
for (int i = 0; i < 10; i++) {
- m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), "");
+ m_wallet->subaddress()->addRow("");
}
}
- m_wallet->subaddressModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount());
// history page
m_wallet->history()->refresh();
}
void ReceiveWidget::generateSubaddress() {
- bool r = m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), "");
+ bool r = m_wallet->subaddress()->addRow("");
if (!r) {
Utils::showError(this, "Failed to generate subaddress", m_wallet->subaddress()->getError());
}
connect(ui->accounts, &QTreeView::customContextMenuRequested, this, &AccountSwitcherDialog::showContextMenu);
connect(ui->btn_newAccount, &QPushButton::clicked, [this]{
- m_wallet->addSubaddressAccount("New account");
- m_wallet->subaddressAccount()->refresh();
+ m_wallet->addSubaddressAccount("New account");
+ m_wallet->subaddressAccount()->refresh();
+ for (int i = 0; i < 10; i ++) {
+ m_wallet->subaddress()->addRow("");
+ }
});
connect(m_wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection);
m_hidden = hidden.split(",");
connect(this, &Subaddress::noUnusedSubaddresses, [this] {
- this->addRow(m_wallet->currentSubaddressAccount(), "");
+ this->addRow("");
});
}
-bool Subaddress::refresh(quint32 accountIndex)
+bool Subaddress::refresh()
{
emit refreshStarted();
m_rows.clear();
- bool haveUnused = false;
bool potentialWalletFileCorruption = false;
+ quint32 accountIndex = m_wallet->currentSubaddressAccount();
for (quint32 i = 0; i < m_wallet2->get_num_subaddresses(accountIndex); ++i)
{
- cryptonote::subaddress_index index = {accountIndex, i};
- cryptonote::account_public_address address = m_wallet2->get_subaddress(index);
-
- // Make sure we have previously generated Di
- auto idx = m_wallet2->get_subaddress_index(address);
- if (!idx) {
- potentialWalletFileCorruption = true;
- break;
- }
-
- // Verify mapping
- if (idx != index) {
+ bool r = emplaceRow(i);
+ if (!r) {
potentialWalletFileCorruption = true;
break;
}
-
- QString addressStr = QString::fromStdString(cryptonote::get_account_address_as_str(m_wallet2->nettype(), !index.is_zero(), address));
-
- bool used = m_wallet2->get_subaddress_used({accountIndex, (uint32_t)i});
- m_rows.emplace_back(
- addressStr,
- QString::fromStdString(m_wallet2->get_subaddress_label(index)),
- used,
- this->isHidden(addressStr),
- this->isPinned(addressStr)
- );
- if (!used && i > 0) {
- haveUnused = true;
- }
}
// Make sure keys are intact. We NEVER want to display incorrect addresses in case of memory corruption.
emit refreshFinished();
- if (!haveUnused) {
- emit noUnusedSubaddresses();
- }
-
return !potentialWalletFileCorruption;
}
return m_rows;
}
-bool Subaddress::addRow(quint32 accountIndex, const QString &label)
+bool Subaddress::emplaceRow(quint32 addressIndex)
+{
+ cryptonote::subaddress_index index = {m_wallet->currentSubaddressAccount(), addressIndex};
+ cryptonote::account_public_address address = m_wallet2->get_subaddress(index);
+
+ // Make sure we have previously generated Di
+ auto idx = m_wallet2->get_subaddress_index(address);
+ if (!idx) {
+ return false;
+ }
+
+ // Verify mapping
+ if (idx != index) {
+ return false;
+ }
+
+ if (m_rows.length() != addressIndex) {
+ return false;
+ }
+
+ QString addressStr = QString::fromStdString(cryptonote::get_account_address_as_str(m_wallet2->nettype(), !index.is_zero(), address));
+
+ bool used = m_wallet2->get_subaddress_used(index);
+ m_rows.emplace_back(
+ addressStr,
+ QString::fromStdString(m_wallet2->get_subaddress_label(index)),
+ used,
+ this->isHidden(addressStr),
+ this->isPinned(addressStr),
+ index.is_zero()
+ );
+ return true;
+}
+
+bool Subaddress::addRow(const QString &label)
{
// This can fail if hardware device is unplugged during operating, catch here to prevent crash
// Todo: Notify GUI that it was a device error
try
{
- m_wallet2->add_subaddress(accountIndex, label.toStdString());
- refresh(accountIndex);
+ quint32 addressIndex = m_wallet->numSubaddresses(m_wallet->currentSubaddressAccount());
+ m_wallet2->add_subaddress(m_wallet->currentSubaddressAccount(), label.toStdString());
+
+ emit beginAddRow(addressIndex);
+ emplaceRow(addressIndex);
+ emit endAddRow();
}
catch (const std::exception& e)
{
return true;
}
-bool Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label)
+bool Subaddress::setLabel(quint32 addressIndex, const QString &label)
{
try {
- m_wallet2->set_subaddress_label({accountIndex, addressIndex}, label.toStdString());
- refresh(accountIndex);
+ m_wallet2->set_subaddress_label({m_wallet->currentSubaddressAccount(), addressIndex}, label.toStdString());
+ SubaddressRow& row = m_rows[addressIndex];
+ row.label = label;
+ emit rowUpdated(addressIndex);
}
catch (const std::exception& e)
{
bool r = m_wallet->setCacheAttribute("feather.hiddenaddresses", m_hidden.join(","));
- refresh(m_wallet->currentSubaddressAccount());
+ refresh();
return r;
}
bool r = m_wallet->setCacheAttribute("feather.pinnedaddresses", m_pinned.join(","));
- refresh(m_wallet->currentSubaddressAccount());
+ refresh();
return r;
}
Q_OBJECT
public:
- bool refresh(quint32 accountIndex);
+ bool refresh();
void updateUsed(quint32 accountIndex);
[[nodiscard]] qsizetype count() const;
const SubaddressRow& getRow(qsizetype i);
const QList<SubaddressRow>& getRows();
- bool addRow(quint32 accountIndex, const QString &label);
- bool setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
+ bool addRow(const QString &label);
+ bool setLabel(quint32 addressIndex, const QString &label);
bool setHidden(const QString& address, bool hidden);
bool setPinned(const QString& address, bool pinned);
bool isHidden(const QString& address);
void rowUpdated(qsizetype index) const;
void corrupted() const;
void noUnusedSubaddresses() const;
+ void beginAddRow(qsizetype index) const;
+ void endAddRow() const;
private:
+ bool emplaceRow(quint32 addressIndex);
+
explicit Subaddress(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent);
friend class Wallet;
{
qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute";
}
- m_subaddress->refresh(m_currentSubaddressAccount);
+ m_subaddress->refresh();
m_history->refresh();
m_coins->refresh();
- this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount);
this->updateBalance();
this->setSelectedInputs({});
return m_wallet2->get_num_subaddresses(accountIndex);
}
-void Wallet::addSubaddress(const QString& label) {
- m_wallet2->add_subaddress(currentSubaddressAccount(), label.toStdString());
-}
-
QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const {
return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex));
}
-void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) {
- m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString());
-}
-
void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId) {
m_scheduler.run([this, accountIndex, addressIndex, paymentId] {
m_walletImpl->deviceShowAddress(accountIndex, addressIndex, paymentId.toStdString());
// #################### Synchronization (Refresh) ####################
void Wallet::startRefresh() {
+ m_refreshEnabled = true;
m_refreshEnabled = true;
m_refreshNow = true;
}
void Wallet::refreshModels() {
m_history->refresh();
m_coins->refresh();
- this->subaddress()->refresh(this->currentSubaddressAccount());
+ m_subaddress->refresh();
}
// #################### Hardware wallet ####################
this->history()->refresh();
this->coins()->refresh();
- this->subaddress()->refresh(this->currentSubaddressAccount());
+ this->subaddress()->refresh();
this->updateBalance();
void addSubaddressAccount(const QString& label);
quint32 numSubaddressAccounts() const;
quint32 numSubaddresses(quint32 accountIndex) const;
- void addSubaddress(const QString& label);
QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const;
- void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label);
void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId);
QString getSubaddressLookahead() const;
bool used = false;
bool hidden = false;
bool pinned = false;
+ bool primary = false;
- SubaddressRow(const QString& address, const QString &label, bool used, bool hidden, bool pinned)
+ SubaddressRow(const QString& address, const QString &label, bool used, bool hidden, bool pinned, bool primary)
: address(address)
, label(label)
, used(used)
, hidden(hidden)
- , pinned(pinned) {}
+ , pinned(pinned)
+ , primary(primary) {}
};
#endif //FEATHER_SUBADDRESSROW_H
{
connect(m_subaddress, &Subaddress::refreshStarted, this, &SubaddressModel::beginResetModel);
connect(m_subaddress, &Subaddress::refreshFinished, this, &SubaddressModel::endResetModel);
+ connect(m_subaddress, &Subaddress::beginAddRow, this, &SubaddressModel::beginRowAdded);
+ connect(m_subaddress, &Subaddress::endAddRow, this, &SubaddressModel::endInsertRows);
connect(m_subaddress, &Subaddress::rowUpdated, this, &SubaddressModel::rowUpdated);
}
switch (index.column()) {
case Label:
- m_subaddress->setLabel(m_currentSubaddressAccount, row, value.toString());
+ m_subaddress->setLabel(row, value.toString());
break;
default:
return false;
return QAbstractTableModel::flags(index);
}
-void SubaddressModel::setCurrentSubaddressAccount(quint32 accountIndex) {
- m_currentSubaddressAccount = accountIndex;
-}
-
const SubaddressRow& SubaddressModel::entryFromIndex(const QModelIndex &index) const {
Q_ASSERT(index.isValid() && index.row() < m_subaddress->count());
return m_subaddress->row(index.row());
{
emit dataChanged(this->index(index, 0), this->index(index, SubaddressModel::COUNT - 1), {Qt::DisplayRole, Qt::EditRole});
}
+
+void SubaddressModel::beginRowAdded(qsizetype index)
+{
+ this->beginInsertRows(this->index(index, 0), index, index);
+}
const SubaddressRow& entryFromIndex(const QModelIndex &index) const;
- void setCurrentSubaddressAccount(quint32 accountIndex);
-
void rowUpdated(qsizetype index);
+ void beginRowAdded(qsizetype index);
private:
Subaddress *m_subaddress;