Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
501const auto column = static_cast<ColumnIndex>(index.column());502switch (role) {503case RawDecorationRole:504switch (column) {505case Status:506return txStatusDecoration(rec);507case Date: return {};508case Type: return {};509case ToAddress:510return txAddressDecoration(rec);511case Amount: return {};512} // no default case, so the compiler can warn about missing cases513assert(false);514case Qt::DecorationRole:515{516QIcon icon = qvariant_cast<QIcon>(index.data(RawDecorationRole));517return platformStyle->TextColorIcon(icon);518}519case Qt::DisplayRole:520switch (column) {521case Status: return {};522case Date:523return formatTxDate(rec);524case Type:525return formatTxType(rec);526case ToAddress:527return formatTxToAddress(rec, false);528case Amount:529return formatTxAmount(rec, true, BitcoinUnits::SeparatorStyle::ALWAYS);530} // no default case, so the compiler can warn about missing cases531assert(false);532case Qt::EditRole:533// Edit role is used for sorting, so return the unformatted values534switch (column) {535case Status:536return QString::fromStdString(rec->status.sortKey);537case Date:538return QString::fromStdString(strprintf("%020s-%s", rec->time, rec->status.sortKey));539case Type:540return formatTxType(rec);541case ToAddress:542return formatTxToAddress(rec, true);543case Amount:544return qint64(rec->credit + rec->debit);545} // no default case, so the compiler can warn about missing cases546assert(false);547case Qt::ToolTipRole:548return formatTooltip(rec);549case Qt::TextAlignmentRole:550return column_alignments[index.column()];551case Qt::ForegroundRole:552// Use the "danger" color for abandoned transactions553if(rec->status.status == TransactionStatus::Abandoned)554{555return COLOR_TX_STATUS_DANGER;556}557// Non-confirmed (but not immature) as transactions are grey558if(!rec->status.countsForBalance && rec->status.status != TransactionStatus::Immature)559{560return COLOR_UNCONFIRMED;561}562if(index.column() == Amount && (rec->credit+rec->debit) < 0)563{564return COLOR_NEGATIVE;565}566if(index.column() == ToAddress)567{568return addressColor(rec);569}570break;571case TypeRole:572return rec->type;573case DateRole:574return QDateTime::fromSecsSinceEpoch(rec->time);575case LongDescriptionRole:576return priv->describe(walletModel->node(), walletModel->wallet(), rec, walletModel->getOptionsModel()->getDisplayUnit());577case AddressRole:578return QString::fromStdString(rec->address);579case LabelRole:580return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));581case AmountRole:582return qint64(rec->credit + rec->debit);583case TxHashRole:584return rec->getTxHash();585case TxHexRole:586return priv->getTxHex(walletModel->wallet(), rec);587case TxPlainTextRole:588{589QString details;590QDateTime date = QDateTime::fromSecsSinceEpoch(rec->time);591QString txLabel = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address));593details.append(date.toString("M/d/yy HH:mm"));594details.append(" ");595details.append(formatTxStatus(rec));596details.append(". ");597if(!formatTxType(rec).isEmpty()) {598details.append(formatTxType(rec));599details.append(" ");600}601if(!rec->address.empty()) {602if(txLabel.isEmpty())603details.append(tr("(no label)") + " ");604else {605details.append("(");606details.append(txLabel);607details.append(") ");608}609details.append(QString::fromStdString(rec->address));610details.append(" ");611}612details.append(formatTxAmount(rec, false, BitcoinUnits::SeparatorStyle::NEVER));613return details;614}615case ConfirmedRole:616return rec->status.status == TransactionStatus::Status::Confirming || rec->status.status == TransactionStatus::Status::Confirmed;617case FormattedAmountRole:618// Used for copy/export, so don't include separators619return formatTxAmount(rec, false, BitcoinUnits::SeparatorStyle::NEVER);620case StatusRole:621return rec->status.status;622}623return QVariant();624}626QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientation, int role) const627{628if(orientation == Qt::Horizontal)629{630if(role == Qt::DisplayRole)631{632return columns[section];633}634else if (role == Qt::TextAlignmentRole)635{636return column_alignments[section];637} else if (role == Qt::ToolTipRole)638{639switch(section)640{641case Status:642return tr("Transaction status. Hover over this field to show number of confirmations.");643case Date:644return tr("Date and time that the transaction was received.");645case Type:646return tr("Type of transaction.");647case ToAddress:648return tr("User-defined intent/purpose of the transaction.");649case Amount:650return tr("Amount removed from or added to balance.");651}652}653}654return QVariant();655}657QModelIndex TransactionTableModel::index(int row, int column, const QModelIndex &parent) const658{659Q_UNUSED(parent);660TransactionRecord* data = priv->index(walletModel->wallet(), walletModel->getLastBlockProcessed(), row);661if(data)662{663return createIndex(row, column, data);664}665return QModelIndex();666}668void TransactionTableModel::updateDisplayUnit()669{670// emit dataChanged to update Amount column with the current unit671updateAmountColumnTitle();672Q_EMIT dataChanged(index(0, Amount), index(priv->size()-1, Amount));673}675void TransactionTablePriv::NotifyTransactionChanged(const Txid& hash, ChangeType status)676{677// Find transaction in wallet678// Determine whether to show transaction or not (determine this here so that no relocking is needed in GUI thread)679bool showTransaction = TransactionRecord::showTransaction();681TransactionNotification notification(hash, status, showTransaction);683if (!m_loaded || m_loading)684{685vQueueNotifications.push_back(notification);686return;687}688notification.invoke(parent);689}691void TransactionTablePriv::DispatchNotifications()692{693if (!m_loaded || m_loading) return;695if (vQueueNotifications.size() > 10) { // prevent balloon spam, show maximum 10 balloons696bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, true));697assert(invoked);698}699for (unsigned int i = 0; i < vQueueNotifications.size(); ++i)700{701if (vQueueNotifications.size() - i <= 10) {702bool invoked = QMetaObject::invokeMethod(parent, "setProcessingQueuedTransactions", Qt::QueuedConnection, Q_ARG(bool, false));703assert(invoked);704}706vQueueNotifications[i].invoke(parent);707}708vQueueNotifications.clear();709}711void TransactionTableModel::subscribeToCoreSignals()712{713// Connect signals to wallet714m_handler_transaction_changed = walletModel->wallet().handleTransactionChanged([this](const Txid& hash, ChangeType status) {715priv->NotifyTransactionChanged(hash, status);716});717m_handler_show_progress = walletModel->wallet().handleShowProgress([this](const std::string&, int progress) {718priv->m_loading = progress < 100;719priv->DispatchNotifications();720});721}723void TransactionTableModel::unsubscribeFromCoreSignals()724{725// Disconnect signals from wallet726m_handler_transaction_changed->disconnect();727m_handler_show_progress->disconnect();728}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.