diff --git a/doc/release-notes.md b/doc/release-notes.md index 81e79dd3a9f..5501bae252c 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -129,7 +129,11 @@ GUI changes ----------- - UTXOs which are locked via the GUI are now stored persistently in the - wallet database, so are not lost on node shutdown or crash. (#23065) + wallet database, so are not lost on node shutdown or crash. (bitcoin-core/gui#23065) + +- Toggle chain from mainnet to testnet, signet or regtest. The GUI now always sets `-chain`, + so any occurrences of `-testnet`, `-signet` or `-regtest` in `bitcoin.conf` should + be replace with `chain=test`, `chain=signet` or `chain=regtest` respectively. (bitcoin-core/gui#414) Low-level changes ================= diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 00c9fd30598..076f59b8039 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -562,6 +562,10 @@ int GuiMain(int argc, char* argv[]) // - QSettings() will use the new application name after this, resulting in network-specific settings // - Needs to be done before createOptionsModel + QSettings settings; + std::string chain = settings.value("chain", "main").toString().toStdString(); + gArgs.SoftSetArg("-chain", chain); + // Check for chain settings (Params() calls are only valid after this clause) try { SelectParams(gArgs.GetChainName()); diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index 610637360bd..a713232070e 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -454,6 +454,46 @@ void BitcoinGUI::createMenuBar() appMenuBar = menuBar(); #endif + // Add chain selection submenu + QAction* chain_selection_action{nullptr}; + QMenu* chain_selection_menu{nullptr}; + chain_selection_action = new QAction(tr("&Switch chain"), this); + chain_selection_action->setStatusTip(tr("Restart application using a different (test) network")); + chain_selection_menu = new QMenu(this); + + connect(chain_selection_menu, &QMenu::aboutToShow, [this, chain_selection_menu] { + chain_selection_menu->clear(); + const std::vector> chains = {{"main", "&Bitcoin"}, {"test", "&Testnet"}, {"regtest", "&Regtest"}, {"signet", "&Signet"}}; + for (auto chain : chains) { + const bool is_current = gArgs.GetChainName() == chain.first.toStdString(); + QAction* action = chain_selection_menu->addAction(chain.second); + action->setCheckable(true); + action->setChecked(is_current); + action->setEnabled(!is_current); + + connect(action, &QAction::triggered, [this, chain] { + //: Switch to the mainnet, testnet, signet or regtest chain. + QMessageBox::StandardButton btn_ret_val = QMessageBox::question(this, tr("Switch chain"), + //: Switching between mainnet, testnet, signet or regtest chain requires a restart. + tr("Client restart required to switch chain.\n\nClientClient will be shut down. Do you want to proceed?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); + + if (btn_ret_val == QMessageBox::Cancel) return; + + // QSettings are stored seperately for each network. Switch application name + // to mainnet before storing the selected chain. + QScopedPointer networkStyle(NetworkStyle::instantiate("main")); + assert(!networkStyle.isNull()); + QApplication::setApplicationName(networkStyle->getAppName()); + + QSettings settings; + settings.setValue("chain", chain.first); + QApplication::quit(); + }); + } + }); + chain_selection_action->setMenu(chain_selection_menu); + // Configure the menus QMenu *file = appMenuBar->addMenu(tr("&File")); if(walletFrame) @@ -471,6 +511,8 @@ void BitcoinGUI::createMenuBar() file->addAction(m_load_psbt_clipboard_action); file->addSeparator(); } + file->addAction(chain_selection_action); + file->addSeparator(); file->addAction(quitAction); QMenu *settings = appMenuBar->addMenu(tr("&Settings"));