From: gg Date: Tue, 20 Jan 2026 03:03:12 +0000 (-0500) Subject: lint/warning fixes X-Git-Url: https://git.nutra.tk/v2?a=commitdiff_plain;h=cbb0c404a3f68991066161fbd223beabb9f5396e;p=gamesguru%2Ffeather.git lint/warning fixes --- diff --git a/src/HistoryWidget.cpp b/src/HistoryWidget.cpp index 09aa843b..1791fc8c 100644 --- a/src/HistoryWidget.cpp +++ b/src/HistoryWidget.cpp @@ -213,14 +213,14 @@ void HistoryWidget::copy(copyField field) { case copyField::JSON: { QJsonObject obj; obj.insert("txid", tx.hash); - obj.insert("amount", static_cast(tx.amount)); - obj.insert("fee", static_cast(tx.fee)); - obj.insert("height", static_cast(tx.blockHeight)); + obj.insert("amount", QString::number(tx.amount)); + obj.insert("fee", QString::number(tx.fee)); + obj.insert("height", static_cast(tx.blockHeight)); obj.insert("timestamp", tx.timestamp.toSecsSinceEpoch()); obj.insert("direction", tx.direction == TransactionRow::Direction_In ? "in" : "out"); obj.insert("payment_id", tx.paymentId); obj.insert("description", tx.description); - obj.insert("confirmations", static_cast(tx.confirmations)); + obj.insert("confirmations", static_cast(tx.confirmations)); obj.insert("failed", tx.failed); obj.insert("pending", tx.pending); obj.insert("coinbase", tx.coinbase); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index d7bf5dc1..df817018 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -444,7 +444,6 @@ void MainWindow::initWidgets() { connect(m_walletUnlockWidget, &WalletUnlockWidget::closeWallet, this, &MainWindow::close); connect(m_walletUnlockWidget, &WalletUnlockWidget::unlockWallet, this, &MainWindow::unlockWallet); - ui->tabWidget->setCurrentIndex(0); ui->tabWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0); diff --git a/src/SendWidget.cpp b/src/SendWidget.cpp index de34fae7..f869fb84 100644 --- a/src/SendWidget.cpp +++ b/src/SendWidget.cpp @@ -146,7 +146,9 @@ void SendWidget::scanClicked() { } void SendWidget::sendClicked() { - if (conf()->get(Config::syncPaused).toBool()) { + bool syncPaused = conf()->get(Config::syncPaused).toBool(); + + if (syncPaused) { QMessageBox msgBox(this); msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle("Are you sure? Create transaction?"); @@ -167,14 +169,14 @@ void SendWidget::sendClicked() { } } - if (!m_wallet->isConnected() && !conf()->get(Config::syncPaused).toBool()) { + if (!m_wallet->isConnected() && !syncPaused) { Utils::showError(this, "Unable to create transaction", "Wallet is not connected to a node.", {"Wait for the wallet to automatically connect to a node.", "Go to File -> Settings -> Network -> Node to manually connect to a node."}, "nodes"); return; } - if (!m_wallet->isSynchronized() && !conf()->get(Config::syncPaused).toBool()) { + if (!m_wallet->isSynchronized() && !syncPaused) { Utils::showError(this, "Unable to create transaction", "Wallet is not synchronized", {"Wait for wallet synchronization to complete"}, "synchronization"); return; } diff --git a/src/WindowManager.cpp b/src/WindowManager.cpp index 9fab17e5..07e0f36d 100644 --- a/src/WindowManager.cpp +++ b/src/WindowManager.cpp @@ -117,12 +117,12 @@ void WindowManager::close() { } m_closing = true; - - // Stop all threads before application shutdown to avoid QThreadStorage warnings - if (m_cleanupThread && m_cleanupThread->isRunning()) { - m_cleanupThread->quit(); - m_cleanupThread->wait(); - qDebug() << "WindowManager: cleanup thread stopped in close()"; + // Force save all wallets before attempting to close + // This ensures that even if the cleanup thread hangs and we _Exit(1), data is saved. + for (const auto &window : m_windows) { + if (window->m_wallet) { + window->m_wallet->store(); + } } // Close all windows first to ensure they cancel their tasks/connections @@ -132,6 +132,13 @@ void WindowManager::close() { window->close(); } + // Stop all threads before application shutdown to avoid QThreadStorage warnings + if (m_cleanupThread && m_cleanupThread->isRunning()) { + m_cleanupThread->quit(); + m_cleanupThread->wait(); + qDebug() << "WindowManager: cleanup thread stopped in close()"; + } + // Stop Tor manager threads torManager()->stop(); diff --git a/src/dialog/SyncRangeDialog.cpp b/src/dialog/SyncRangeDialog.cpp index 793d46c9..885f649f 100644 --- a/src/dialog/SyncRangeDialog.cpp +++ b/src/dialog/SyncRangeDialog.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "utils/Utils.h" #include "utils/RestoreHeightLookup.h" @@ -144,11 +145,13 @@ void SyncRangeDialog::updateInfo() { } void SyncRangeDialog::updateFromDate() { + const QSignalBlocker blocker(m_fromDateEdit); m_fromDateEdit->setDate(m_toDateEdit->date().addDays(-m_daysSpinBox->value())); updateInfo(); } void SyncRangeDialog::updateToDate() { + const QSignalBlocker blocker(m_toDateEdit); m_toDateEdit->setDate(m_fromDateEdit->date().addDays(m_daysSpinBox->value())); updateInfo(); } diff --git a/src/dialog/TxImportDialog.cpp b/src/dialog/TxImportDialog.cpp index 842337bf..d09dc738 100644 --- a/src/dialog/TxImportDialog.cpp +++ b/src/dialog/TxImportDialog.cpp @@ -46,6 +46,12 @@ void TxImportDialog::onImport() { QString txid = ui->line_txid->text().trimmed(); if (txid.isEmpty()) return; + static const QRegularExpression hexMatcher("^[0-9a-fA-F]{64}$"); + if (!hexMatcher.match(txid).hasMatch()) { + Utils::showError(this, "Invalid TXID", "Transaction ID must be a 64-character hexadecimal string."); + return; + } + if (m_wallet->haveTransaction(txid)) { Utils::showWarning(this, "Transaction already exists in wallet", "If you can't find it in your history, " "check if it belongs to a different account (Wallet -> Account)"); @@ -56,22 +62,22 @@ void TxImportDialog::onImport() { ui->btn_import->setEnabled(false); ui->btn_import->setText("Checking..."); - QNetworkAccessManager* nam = getNetwork(); // Use global network manager QString url = m_nodes->connection().toURL() + "/get_transactions"; - + QNetworkAccessManager* nam = getNetwork(url); // Use global network manager + QJsonObject req; req["txs_hashes"] = QJsonArray({txid}); - + QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QNetworkReply* reply = nam->post(request, QJsonDocument(req).toJson()); - + connect(reply, &QNetworkReply::finished, this, [this, reply, txid]() { reply->deleteLater(); ui->btn_import->setEnabled(true); ui->btn_import->setText("Import"); - + if (reply->error() != QNetworkReply::NoError) { Utils::showError(this, "Connection error", reply->errorString()); return; @@ -96,9 +102,22 @@ void TxImportDialog::onImport() { this->accept(); return; } - + quint64 height = tx.value("block_height").toVariant().toULongLong(); if (height > 0) { + if (height > std::numeric_limits::max() - 10) { + Utils::showError(this, "Invalid Block Height", "Block height is too large."); + return; + } + + // Validate against daemon height + quint64 daemonHeight = m_wallet->daemonBlockChainHeight(); + if (daemonHeight > 0 && height > daemonHeight + 100) { + Utils::showError(this, "Invalid Block Height", + QString("The node returned a block height significantly in the future (%1). Daemon height: %2.").arg(height).arg(daemonHeight)); + return; + } + // Check if wallet is far behind (fresh restore?) quint64 currentHeight = m_wallet->blockChainHeight(); diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index b4a517ef..a10d503a 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -61,6 +61,7 @@ Wallet::Wallet(Monero::Wallet *wallet, QObject *parent) , m_coins(new Coins(this, wallet->getWallet(), this)) , m_storeTimer(new QTimer(this)) , m_lastRefreshTime(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()) + , m_lastSyncTime(0) { m_walletListener = new WalletListenerImpl(this); m_walletImpl->setListener(m_walletListener); @@ -104,7 +105,7 @@ Wallet::Wallet(Monero::Wallet *wallet, QObject *parent) if (!lastSyncStr.isEmpty()) { qint64 lastSync = lastSyncStr.toLongLong(); if (lastSync > 0) { - m_lastSyncTime = QDateTime::fromSecsSinceEpoch(lastSync); + m_lastSyncTime = lastSync * 1000; } } } @@ -451,7 +452,7 @@ void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 safeAddress.prepend("http://"); } } - qCritical() << "Refresher: Initializing wallet with daemon address:" << safeAddress; + qInfo() << "Refresher: Initializing wallet with daemon address:" << safeAddress; qDebug() << "InitAsync: connecting to" << safeAddress; m_wallet2->set_offline(false); success = m_walletImpl->init(safeAddress.toStdString(), upperTransactionLimit, m_daemonUsername.toStdString(), m_daemonPassword.toStdString(), m_useSSL, false, proxyAddress.toStdString()); @@ -662,7 +663,7 @@ void Wallet::onHeightsRefreshed(bool success, quint64 daemonHeight, quint64 targ } if (success) { - m_lastSyncTime = QDateTime::currentDateTime(); + m_lastSyncTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); } } @@ -726,7 +727,9 @@ void Wallet::setScanMempoolWhenPaused(bool enabled) { } QDateTime Wallet::lastSyncTime() const { - return m_lastSyncTime; + if (m_lastSyncTime == 0) + return QDateTime(); + return QDateTime::fromMSecsSinceEpoch(m_lastSyncTime); } void Wallet::setRefreshInterval(int seconds) { @@ -746,7 +749,7 @@ void Wallet::skipToTip() { m_stopHeight = target; m_rangeSyncActive = true; m_wallet2->set_refresh_from_block_height(target); - m_lastSyncTime = QDateTime::currentDateTime(); + m_lastSyncTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); setConnectionStatus(ConnectionStatus_Synchronized); startRefresh(true); @@ -831,7 +834,7 @@ void Wallet::startSmartSync(quint64 requestedTarget) { m_stopHeight = target; m_rangeSyncActive = true; m_pauseAfterSync = true; - m_lastSyncTime = QDateTime::currentDateTime(); + m_lastSyncTime = QDateTime::currentDateTime().toMSecsSinceEpoch(); setConnectionStatus(ConnectionStatus_Synchronizing); startRefresh(true); @@ -1865,23 +1868,25 @@ void Wallet::getTxPoolStatsAsync() { } void Wallet::scanMempool() { - QMutexLocker locker(&m_asyncMutex); - try { - std::vector> process_txs; - m_wallet2->update_pool_state(process_txs, false, false); - // Refresh models so the UI picks up the new transaction(s) - // We invoke this on the main thread to ensure signals (beginResetModel) are processed synchronously - // with the data update, preventing race conditions or ignored updates in the view. - QMetaObject::invokeMethod(this, [this]{ - if (m_history) m_history->refresh(); - if (m_coins) m_coins->refresh(); - if (m_subaddress) m_subaddress->refresh(); - }, Qt::QueuedConnection); - - emit updated(); - } catch (const std::exception &e) { - qWarning() << "Failed to scan mempool:" << e.what(); + { + QMutexLocker locker(&m_asyncMutex); + try { + std::vector> process_txs; + m_wallet2->update_pool_state(process_txs, false, false); + // Refresh models so the UI picks up the new transaction(s) + // We invoke this on the main thread to ensure signals (beginResetModel) are processed synchronously + // with the data update, preventing race conditions or ignored updates in the view. + QMetaObject::invokeMethod(this, [this]{ + if (m_history) m_history->refresh(); + if (m_coins) m_coins->refresh(); + if (m_subaddress) m_subaddress->refresh(); + }, Qt::QueuedConnection); + + } catch (const std::exception &e) { + qWarning() << "Failed to scan mempool:" << e.what(); + } } + emit updated(); } Wallet::~Wallet() diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 1c85d9b3..d1beccf5 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -516,9 +516,9 @@ private: AddressBook *m_addressBook; AddressBookModel *m_addressBookModel; - quint64 m_daemonBlockChainHeight; - quint64 m_daemonBlockChainTargetHeight; - QDateTime m_lastSyncTime; + std::atomic m_daemonBlockChainHeight; + std::atomic m_daemonBlockChainTargetHeight; + std::atomic m_lastSyncTime; ConnectionStatus m_connectionStatus; @@ -553,7 +553,7 @@ private: std::atomic m_stopHeight{0}; std::atomic m_rangeSyncActive{false}; std::atomic m_syncPaused{false}; - std::atomic m_lastRefreshTime{0}; + std::atomic m_lastRefreshTime{0}; std::atomic m_pauseAfterSync{false}; std::atomic m_refreshThreadStarted{false}; std::atomic m_scanMempoolWhenPaused{false}; diff --git a/src/main.cpp b/src/main.cpp index 4b57478e..6d058396 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -212,7 +212,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) { conf()->set(Config::restartRequired, false); - if (!quiet && !conf()->get(Config::disableLogging).toBool()) { + if (!quiet && !conf()->get(Config::disableLoggingStdout).toBool()) { QList> info; info.emplace_back("Feather", FEATHER_VERSION); info.emplace_back("Monero", MONERO_VERSION); diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index d9e42776..c80ac2a4 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -761,11 +761,13 @@ QString formatSyncTimeEstimate(quint64 blocks) { quint64 minutes = blocks * 2; quint64 days = minutes / (60 * 24); + quint64 hours = minutes / 60; + QString timeStr; if (days > 0) { - timeStr = QObject::tr("~%1 days").arg(days); + timeStr = QObject::tr("~%1 day%2").arg(days).arg(days == 1 ? "" : "s"); } else if (minutes >= 60) { - timeStr = QObject::tr("~%1 hours").arg(minutes / 60); + timeStr = QObject::tr("~%1 hour%2").arg(hours).arg(hours == 1 ? "" : "s"); } else { timeStr = QObject::tr("< 1 hour"); }