this->enableWebsocket(checked);
});
-
-
- QComboBox *comboSyncInterval = new QComboBox(this);
- comboSyncInterval->setEditable(true);
-
- struct IntervalPreset {
- QString label;
- int seconds;
- };
-
- QList<IntervalPreset> presets = {
- {"30 seconds", 30},
- {"1 minute", 60},
- {"2 minutes", 120},
- {"5 minutes", 300},
- {"10 minutes", 600},
- {"15 minutes", 900},
- {"20 minutes", 1200},
- {"30 minutes", 1800},
- {"45 minutes", 2700},
- {"1 hour", 3600},
- {"1.5 hours", 5400},
- {"3 hours", 10800},
- {"5 hours", 18000},
- {"10 hours", 36000},
- {"1 day", 86400},
- {"1 week", 604800},
- {"1 month", 2592000}
- };
-
- for (const auto &preset : presets) {
- comboSyncInterval->addItem(preset.label, preset.seconds);
- }
-
- int currentInterval = conf()->get(Config::syncInterval).toInt();
- bool found = false;
- for (int i = 0; i < comboSyncInterval->count(); ++i) {
- if (comboSyncInterval->itemData(i).toInt() == currentInterval) {
- comboSyncInterval->setCurrentIndex(i);
- found = true;
- break;
- }
- }
- if (!found) {
- comboSyncInterval->setCurrentText(QString("%1 seconds").arg(currentInterval));
- }
-
- auto updateConfig = [comboSyncInterval](const QString &text){
- int seconds = 0;
- if (comboSyncInterval->currentIndex() != -1 && comboSyncInterval->currentText() == comboSyncInterval->itemText(comboSyncInterval->currentIndex())) {
- seconds = comboSyncInterval->currentData().toInt();
- } else {
- // Try to parse simple number as seconds
- bool ok;
- seconds = text.split(" ").first().toInt(&ok);
- if (!ok) return;
- }
- if (seconds < 30) {
- seconds = 30;
- }
- conf()->set(Config::syncInterval, seconds);
- };
-
- connect(comboSyncInterval, &QComboBox::currentTextChanged, updateConfig);
-
- QHBoxLayout *hLayoutSync = new QHBoxLayout();
- hLayoutSync->addWidget(new QLabel("Time between syncs:", this));
- hLayoutSync->addWidget(comboSyncInterval);
- hLayoutSync->addStretch();
-
// Add to Node tab
if (auto *layout = qobject_cast<QVBoxLayout*>(ui->Node->layout())) {
- layout->addLayout(hLayoutSync);
// Sync (Data Saving Mode)
QCheckBox *cbDataSaver = new QCheckBox("Data Saving Mode (Pause Sync on startup)", this);
conf()->set(Config::syncPaused, checked);
});
layout->addWidget(cbDataSaver);
-
- // Scan mempool when paused
- QCheckBox *cbScanMempool = new QCheckBox("Scan mempool and network info when paused", this);
- cbScanMempool->setChecked(conf()->get(Config::scanMempoolWhenPaused).toBool());
- cbScanMempool->setToolTip("Periodically updates the network status and mempool (pending transactions) even when synchronization is paused.");
-
- connect(cbScanMempool, &QCheckBox::toggled, [](bool checked){
- conf()->set(Config::scanMempoolWhenPaused, checked);
- });
- layout->addWidget(cbScanMempool);
}
}
#include <QSpinBox>
#include <QDateEdit>
#include <QLabel>
-#include <QTabWidget>
#include <QDialogButtonBox>
#include "utils/Utils.h"
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowFlags(windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
- auto *layout = new QVBoxLayout(this);
- m_tabWidget = new QTabWidget(this);
-
- // --- Date Tab ---
- m_dateTab = new QWidget;
- auto *formLayout = new QFormLayout(m_dateTab);
+ auto *layout = new QVBoxLayout(this);
+ auto *formLayout = new QFormLayout();
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
m_toDateEdit = new QDateEdit(QDate::currentDate());
formLayout->addRow(tr("Start date:"), m_fromDateEdit);
formLayout->addRow(tr("End date:"), m_toDateEdit);
- m_tabWidget->addTab(m_dateTab, tr("Date Range"));
-
- // --- Block Tab ---
- m_blockTab = new QWidget;
- auto *blockLayout = new QFormLayout(m_blockTab);
-
- quint64 currentHeight = m_wallet->blockChainHeight();
- quint64 daemonHeight = m_wallet->daemonBlockChainHeight();
- quint64 targetHeight = (daemonHeight > 0) ? daemonHeight : currentHeight;
-
- m_startHeightSpin = new QSpinBox;
- m_startHeightSpin->setRange(0, 9999999);
- m_startHeightSpin->setValue(std::max((quint64)0, targetHeight - 5040)); // Approx 7 days
-
- m_endHeightSpin = new QSpinBox;
- m_endHeightSpin->setRange(0, 9999999);
- m_endHeightSpin->setValue(targetHeight);
-
- blockLayout->addRow(tr("Start Height:"), m_startHeightSpin);
- blockLayout->addRow(tr("End Height:"), m_endHeightSpin);
-
- m_tabWidget->addTab(m_blockTab, tr("Block Height"));
+ layout->addLayout(formLayout);
m_infoLabel = new QLabel;
m_infoLabel->setWordWrap(true);
m_infoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; }");
- layout->addWidget(m_tabWidget);
layout->addWidget(m_infoLabel);
- connect(m_tabWidget, &QTabWidget::currentChanged, this, &SyncRangeDialog::updateInfo);
- connect(m_startHeightSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, &SyncRangeDialog::updateInfo);
- connect(m_endHeightSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, &SyncRangeDialog::updateInfo);
-
connect(m_fromDateEdit, &QDateEdit::dateChanged, this, &SyncRangeDialog::updateToDate);
connect(m_toDateEdit, &QDateEdit::dateChanged, this, &SyncRangeDialog::updateFromDate);
connect(m_daysSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &SyncRangeDialog::updateFromDate);
return m_estimatedSize;
}
-quint64 SyncRangeDialog::startHeight() const {
- return m_startHeightSpin->value();
-}
-
-quint64 SyncRangeDialog::endHeight() const {
- return m_endHeightSpin->value();
-}
-
-SyncRangeDialog::Mode SyncRangeDialog::mode() const {
- if (m_tabWidget->currentIndex() == 1) return Mode_Block;
- return Mode_Date;
-}
-
void SyncRangeDialog::updateInfo() {
- if (this->mode() == Mode_Block) {
- quint64 start = m_startHeightSpin->value();
- quint64 end = m_endHeightSpin->value();
-
- m_estimatedBlocks = (end > start) ? (end - start) : 0;
- m_estimatedSize = Utils::estimateSyncDataSize(m_estimatedBlocks);
- }
- else {
- NetworkType::Type nettype = m_wallet->nettype();
- QString filename = Utils::getRestoreHeightFilename(nettype);
- std::unique_ptr<RestoreHeightLookup> lookup(RestoreHeightLookup::fromFile(filename, nettype));
- if (!lookup || lookup->data.isEmpty()) {
- m_infoLabel->setText(tr("Unable to estimate - restore height data unavailable"));
- m_estimatedBlocks = 0;
- m_estimatedSize = 0;
- return;
- }
+ NetworkType::Type nettype = m_wallet->nettype();
+ QString filename = Utils::getRestoreHeightFilename(nettype);
+ std::unique_ptr<RestoreHeightLookup> lookup(RestoreHeightLookup::fromFile(filename, nettype));
+ if (!lookup || lookup->data.isEmpty()) {
+ m_infoLabel->setText(tr("Unable to estimate - restore height data unavailable"));
+ m_estimatedBlocks = 0;
+ m_estimatedSize = 0;
+ return;
+ }
- QDate start = m_fromDateEdit->date();
- QDate end = m_toDateEdit->date();
+ QDate start = m_fromDateEdit->date();
+ QDate end = m_toDateEdit->date();
- uint64_t startHeight = lookup->dateToHeight(start.startOfDay().toSecsSinceEpoch());
- uint64_t endHeight = lookup->dateToHeight(end.endOfDay().toSecsSinceEpoch());
+ uint64_t startHeight = lookup->dateToHeight(start.startOfDay().toSecsSinceEpoch());
+ uint64_t endHeight = lookup->dateToHeight(end.endOfDay().toSecsSinceEpoch());
- if (endHeight < startHeight) endHeight = startHeight;
- m_estimatedBlocks = endHeight - startHeight;
- m_estimatedSize = Utils::estimateSyncDataSize(m_estimatedBlocks);
- }
+ if (endHeight < startHeight) endHeight = startHeight;
+ m_estimatedBlocks = endHeight - startHeight;
+ m_estimatedSize = Utils::estimateSyncDataSize(m_estimatedBlocks);
m_infoLabel->setText(tr("Scanning ~%1 blocks\nEst. download size: %2")
.arg(m_estimatedBlocks)
class QSpinBox;
class QDateEdit;
class QLabel;
-class QTabWidget;
class SyncRangeDialog : public QDialog
{
explicit SyncRangeDialog(QWidget *parent, Wallet *wallet);
~SyncRangeDialog() override = default;
- enum Mode {
- Mode_Date,
- Mode_Block
- };
-
QDate fromDate() const;
QDate toDate() const;
- quint64 startHeight() const;
- quint64 endHeight() const;
quint64 estimatedBlocks() const;
quint64 estimatedSize() const;
- Mode mode() const;
private:
void updateInfo();
void updateToDate();
Wallet *m_wallet;
- QTabWidget *m_tabWidget;
- QWidget *m_dateTab;
- QWidget *m_blockTab;
// Date/Time
QComboBox *m_presetCombo;
QDateEdit *m_fromDateEdit;
QDateEdit *m_toDateEdit;
- // Blocks
- QSpinBox *m_startHeightSpin;
- QSpinBox *m_endHeightSpin;
-
QLabel *m_infoLabel;
quint64 m_estimatedBlocks = 0;
const auto elapsed = now - last;
if (elapsed >= std::chrono::seconds(m_refreshInterval) || m_refreshNow)
{
- if (m_syncPaused) {
+ if (m_syncPaused && !m_rangeSyncActive) {
bool shouldScanMempool = m_refreshNow || conf()->get(Config::scanMempoolWhenPaused).toBool();
if (shouldScanMempool) {
m_newWallet = false;
}
- quint64 walletHeight = m_walletImpl->blockChainHeight();
+ quint64 walletHeight = m_walletImpl->blockChainHeight();
+
+ if (m_rangeSyncActive) {
+ uint64_t max_blocks = (m_stopHeight > walletHeight) ? (m_stopHeight - walletHeight) : 1;
+ uint64_t blocks_fetched = 0;
+ bool received_money = false;
+
+ m_wallet2->refresh(m_wallet2->is_trusted_daemon(), 0, blocks_fetched, received_money, true, true, max_blocks);
+
+ if (m_walletImpl->blockChainHeight() >= m_stopHeight) {
+ m_rangeSyncActive = false;
+ if (m_syncPaused) {
+ setConnectionStatus(ConnectionStatus_Idle);
+ }
+ }
+ } else {
m_walletImpl->refresh();
}
}
+ }
}
std::this_thread::sleep_for(intervalResolution);
emit syncStatus(daemonHeight, targetHeight, false);
}
- if (walletHeight < targetHeight) {
+ if (m_syncPaused && !m_rangeSyncActive) {
+ setConnectionStatus(ConnectionStatus_Idle);
+ } else if (walletHeight < targetHeight) {
setConnectionStatus(ConnectionStatus_Synchronizing);
} else {
setConnectionStatus(ConnectionStatus_Synchronized);
}
QMutexLocker locker(&m_asyncMutex);
+ m_stopHeight = target;
+ m_rangeSyncActive = true;
m_wallet2->set_refresh_from_block_height(target);
m_lastSyncTime = QDateTime::currentDateTime();
startRefresh();
}
-void Wallet::scanBlockRange(quint64 start, quint64 end) {
- if (!m_wallet2) return;
-
- // Minimal sanity checks
- if (start >= end) return;
- {
- QMutexLocker locker(&m_asyncMutex);
- m_stopHeight = end;
- m_rangeSyncActive = true;
- m_wallet2->set_refresh_from_block_height(start);
- }
-
- setConnectionStatus(ConnectionStatus_Synchronizing);
- startRefresh();
-}
void Wallet::fullSync() {
if (!m_wallet2)
void setSyncPaused(bool paused);
Q_INVOKABLE void skipToTip();
Q_INVOKABLE void syncDateRange(const QDate &start, const QDate &end);
- Q_INVOKABLE void scanBlockRange(quint64 start, quint64 end);
+
void fullSync(); // Rescans from wallet creation height, not genesis block
bool importTransaction(const QString &txid);