2022-12-24 23:49:50 +00:00
// Copyright (c) 2019-2022 The Bitcoin Core developers
2019-01-04 18:49:26 +00:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2019-11-19 13:45:32 +02:00
# include <qt/walletcontroller.h>
2019-05-24 17:14:16 -04:00
# include <qt/askpassphrasedialog.h>
2018-08-01 13:38:45 -04:00
# include <qt/clientmodel.h>
2019-05-24 17:14:16 -04:00
# include <qt/createwalletdialog.h>
# include <qt/guiconstants.h>
2019-06-21 15:13:15 +01:00
# include <qt/guiutil.h>
2019-11-19 13:45:32 +02:00
# include <qt/walletmodel.h>
2019-05-24 17:14:16 -04:00
2021-05-13 16:19:44 +02:00
# include <external_signer.h>
2019-01-04 18:49:26 +00:00
# include <interfaces/handler.h>
# include <interfaces/node.h>
2019-10-06 17:52:05 -04:00
# include <util/string.h>
2020-04-27 20:54:43 +03:00
# include <util/threadnames.h>
2019-08-19 18:12:35 -04:00
# include <util/translation.h>
2019-11-19 13:45:32 +02:00
# include <wallet/wallet.h>
2019-01-04 18:49:26 +00:00
# include <algorithm>
2022-01-06 18:35:53 +02:00
# include <chrono>
2019-01-04 18:49:26 +00:00
2019-03-17 17:54:35 +00:00
# include <QApplication>
2019-01-12 11:34:05 +00:00
# include <QMessageBox>
2022-04-16 19:18:25 +02:00
# include <QMetaObject>
2019-01-04 18:49:26 +00:00
# include <QMutexLocker>
# include <QThread>
2019-06-21 15:13:15 +01:00
# include <QTimer>
2019-03-17 17:54:35 +00:00
# include <QWindow>
2019-01-04 18:49:26 +00:00
2021-11-12 11:13:29 -05:00
using wallet : : WALLET_FLAG_BLANK_WALLET ;
using wallet : : WALLET_FLAG_DESCRIPTORS ;
using wallet : : WALLET_FLAG_DISABLE_PRIVATE_KEYS ;
using wallet : : WALLET_FLAG_EXTERNAL_SIGNER ;
2018-08-01 13:38:45 -04:00
WalletController : : WalletController ( ClientModel & client_model , const PlatformStyle * platform_style , QObject * parent )
2019-01-04 18:49:26 +00:00
: QObject ( parent )
2019-06-21 15:13:15 +01:00
, m_activity_thread ( new QThread ( this ) )
, m_activity_worker ( new QObject )
2018-08-01 13:38:45 -04:00
, m_client_model ( client_model )
, m_node ( client_model . node ( ) )
2019-01-04 18:49:26 +00:00
, m_platform_style ( platform_style )
2018-08-01 13:38:45 -04:00
, m_options_model ( client_model . getOptionsModel ( ) )
2019-01-04 18:49:26 +00:00
{
2021-12-22 13:44:55 -05:00
m_handler_load_wallet = m_node . walletLoader ( ) . handleLoadWallet ( [ this ] ( std : : unique_ptr < interfaces : : Wallet > wallet ) {
2019-01-04 18:49:26 +00:00
getOrCreateWallet ( std : : move ( wallet ) ) ;
} ) ;
2019-06-21 15:13:15 +01:00
m_activity_worker - > moveToThread ( m_activity_thread ) ;
m_activity_thread - > start ( ) ;
2020-04-27 20:54:43 +03:00
QTimer : : singleShot ( 0 , m_activity_worker , [ ] ( ) {
util : : ThreadRename ( " qt-walletctrl " ) ;
} ) ;
2019-01-04 18:49:26 +00:00
}
// Not using the default destructor because not all member types definitions are
// available in the header, just forward declared.
2019-01-21 16:57:22 +00:00
WalletController : : ~ WalletController ( )
{
2019-06-21 15:13:15 +01:00
m_activity_thread - > quit ( ) ;
m_activity_thread - > wait ( ) ;
delete m_activity_worker ;
2019-01-21 16:57:22 +00:00
}
2019-01-04 18:49:26 +00:00
2019-05-27 19:07:05 +01:00
std : : map < std : : string , bool > WalletController : : listWalletDir ( ) const
2019-01-12 11:34:05 +00:00
{
QMutexLocker locker ( & m_mutex ) ;
2019-05-27 19:07:05 +01:00
std : : map < std : : string , bool > wallets ;
2021-12-22 13:44:55 -05:00
for ( const std : : string & name : m_node . walletLoader ( ) . listWalletDir ( ) ) {
2019-05-27 19:07:05 +01:00
wallets [ name ] = false ;
}
2019-01-12 11:34:05 +00:00
for ( WalletModel * wallet_model : m_wallets ) {
2019-05-27 19:07:05 +01:00
auto it = wallets . find ( wallet_model - > wallet ( ) . getWalletName ( ) ) ;
if ( it ! = wallets . end ( ) ) it - > second = true ;
2019-01-12 11:34:05 +00:00
}
return wallets ;
}
2019-01-18 00:21:36 +00:00
void WalletController : : closeWallet ( WalletModel * wallet_model , QWidget * parent )
{
QMessageBox box ( parent ) ;
box . setWindowTitle ( tr ( " Close wallet " ) ) ;
2019-09-07 11:52:37 +02:00
box . setText ( tr ( " Are you sure you wish to close the wallet <i>%1</i>? " ) . arg ( GUIUtil : : HtmlEscape ( wallet_model - > getDisplayName ( ) ) ) ) ;
2019-01-18 00:21:36 +00:00
box . setInformativeText ( tr ( " Closing the wallet for too long can result in having to resync the entire chain if pruning is enabled. " ) ) ;
box . setStandardButtons ( QMessageBox : : Yes | QMessageBox : : Cancel ) ;
box . setDefaultButton ( QMessageBox : : Yes ) ;
if ( box . exec ( ) ! = QMessageBox : : Yes ) return ;
// First remove wallet from node.
wallet_model - > wallet ( ) . remove ( ) ;
// Now release the model.
removeAndDeleteWallet ( wallet_model ) ;
}
2019-01-18 01:05:25 +00:00
void WalletController : : closeAllWallets ( QWidget * parent )
{
QMessageBox : : StandardButton button = QMessageBox : : question ( parent , tr ( " Close all wallets " ) ,
tr ( " Are you sure you wish to close all wallets? " ) ,
QMessageBox : : Yes | QMessageBox : : Cancel ,
QMessageBox : : Yes ) ;
if ( button ! = QMessageBox : : Yes ) return ;
QMutexLocker locker ( & m_mutex ) ;
for ( WalletModel * wallet_model : m_wallets ) {
wallet_model - > wallet ( ) . remove ( ) ;
Q_EMIT walletRemoved ( wallet_model ) ;
delete wallet_model ;
}
m_wallets . clear ( ) ;
}
2019-01-04 18:49:26 +00:00
WalletModel * WalletController : : getOrCreateWallet ( std : : unique_ptr < interfaces : : Wallet > wallet )
{
QMutexLocker locker ( & m_mutex ) ;
// Return model instance if exists.
if ( ! m_wallets . empty ( ) ) {
std : : string name = wallet - > getWalletName ( ) ;
for ( WalletModel * wallet_model : m_wallets ) {
if ( wallet_model - > wallet ( ) . getWalletName ( ) = = name ) {
return wallet_model ;
}
}
}
// Instantiate model and register it.
2020-05-11 17:12:59 +03:00
WalletModel * wallet_model = new WalletModel ( std : : move ( wallet ) , m_client_model , m_platform_style ,
nullptr /* required for the following moveToThread() call */ ) ;
// Move WalletModel object to the thread that created the WalletController
// object (GUI main thread), instead of the current thread, which could be
// an outside wallet thread or RPC thread sending a LoadWallet notification.
// This ensures queued signals sent to the WalletModel object will be
// handled on the GUI event loop.
2019-07-09 16:25:55 +03:00
wallet_model - > moveToThread ( thread ( ) ) ;
2020-08-14 20:53:35 +03:00
// setParent(parent) must be called in the thread which created the parent object. More details in #18948.
2022-04-16 19:18:25 +02:00
QMetaObject : : invokeMethod ( this , [ wallet_model , this ] {
2020-08-14 20:53:35 +03:00
wallet_model - > setParent ( this ) ;
} , GUIUtil : : blockingGUIThreadConnection ( ) ) ;
2019-01-04 18:49:26 +00:00
m_wallets . push_back ( wallet_model ) ;
2019-10-12 22:26:47 +01:00
// WalletModel::startPollBalance needs to be called in a thread managed by
// Qt because of startTimer. Considering the current thread can be a RPC
// thread, better delegate the calling to Qt with Qt::AutoConnection.
const bool called = QMetaObject : : invokeMethod ( wallet_model , " startPollBalance " ) ;
assert ( called ) ;
2020-03-19 22:53:33 +00:00
connect ( wallet_model , & WalletModel : : unload , this , [ this , wallet_model ] {
2019-03-17 17:54:35 +00:00
// Defer removeAndDeleteWallet when no modal widget is active.
2020-12-24 22:37:17 +09:00
// TODO: remove this workaround by removing usage of QDialog::exec.
2019-03-17 17:54:35 +00:00
if ( QApplication : : activeModalWidget ( ) ) {
connect ( qApp , & QApplication : : focusWindowChanged , wallet_model , [ this , wallet_model ] ( ) {
if ( ! QApplication : : activeModalWidget ( ) ) {
removeAndDeleteWallet ( wallet_model ) ;
}
} , Qt : : QueuedConnection ) ;
} else {
removeAndDeleteWallet ( wallet_model ) ;
}
2020-03-19 22:53:33 +00:00
} , Qt : : QueuedConnection ) ;
2019-01-04 18:49:26 +00:00
// Re-emit coinsSent signal from wallet model.
connect ( wallet_model , & WalletModel : : coinsSent , this , & WalletController : : coinsSent ) ;
2019-07-09 16:25:55 +03:00
Q_EMIT walletAdded ( wallet_model ) ;
2019-01-04 18:49:26 +00:00
return wallet_model ;
}
void WalletController : : removeAndDeleteWallet ( WalletModel * wallet_model )
{
// Unregister wallet model.
{
QMutexLocker locker ( & m_mutex ) ;
m_wallets . erase ( std : : remove ( m_wallets . begin ( ) , m_wallets . end ( ) , wallet_model ) ) ;
}
Q_EMIT walletRemoved ( wallet_model ) ;
// Currently this can trigger the unload since the model can hold the last
// CWallet shared pointer.
delete wallet_model ;
}
2019-01-21 16:58:20 +00:00
2019-06-21 15:13:15 +01:00
WalletControllerActivity : : WalletControllerActivity ( WalletController * wallet_controller , QWidget * parent_widget )
: QObject ( wallet_controller )
, m_wallet_controller ( wallet_controller )
, m_parent_widget ( parent_widget )
{
2021-05-22 22:22:21 +03:00
connect ( this , & WalletControllerActivity : : finished , this , & QObject : : deleteLater ) ;
2019-06-21 15:13:15 +01:00
}
2019-01-21 16:58:20 +00:00
2021-08-24 19:46:13 +05:30
void WalletControllerActivity : : showProgressDialog ( const QString & title_text , const QString & label_text )
2019-01-21 16:58:20 +00:00
{
2021-05-22 22:08:59 +03:00
auto progress_dialog = new QProgressDialog ( m_parent_widget ) ;
progress_dialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
connect ( this , & WalletControllerActivity : : finished , progress_dialog , & QWidget : : close ) ;
2021-08-24 19:46:13 +05:30
progress_dialog - > setWindowTitle ( title_text ) ;
2021-05-22 22:08:59 +03:00
progress_dialog - > setLabelText ( label_text ) ;
progress_dialog - > setRange ( 0 , 0 ) ;
progress_dialog - > setCancelButton ( nullptr ) ;
progress_dialog - > setWindowModality ( Qt : : ApplicationModal ) ;
GUIUtil : : PolishProgressDialog ( progress_dialog ) ;
2021-05-22 21:32:51 +03:00
// The setValue call forces QProgressDialog to start the internal duration estimation.
// See details in https://bugreports.qt.io/browse/QTBUG-47042.
2021-05-22 22:08:59 +03:00
progress_dialog - > setValue ( 0 ) ;
2020-03-30 11:41:20 +01:00
}
2019-05-24 17:14:16 -04:00
CreateWalletActivity : : CreateWalletActivity ( WalletController * wallet_controller , QWidget * parent_widget )
: WalletControllerActivity ( wallet_controller , parent_widget )
{
m_passphrase . reserve ( MAX_PASSPHRASE_SIZE ) ;
}
CreateWalletActivity : : ~ CreateWalletActivity ( )
{
delete m_create_wallet_dialog ;
delete m_passphrase_dialog ;
}
2019-09-07 11:08:28 +02:00
void CreateWalletActivity : : askPassphrase ( )
2019-05-24 17:14:16 -04:00
{
m_passphrase_dialog = new AskPassphraseDialog ( AskPassphraseDialog : : Encrypt , m_parent_widget , & m_passphrase ) ;
2019-09-07 12:07:54 +02:00
m_passphrase_dialog - > setWindowModality ( Qt : : ApplicationModal ) ;
2019-05-24 17:14:16 -04:00
m_passphrase_dialog - > show ( ) ;
connect ( m_passphrase_dialog , & QObject : : destroyed , [ this ] {
m_passphrase_dialog = nullptr ;
} ) ;
connect ( m_passphrase_dialog , & QDialog : : accepted , [ this ] {
createWallet ( ) ;
} ) ;
connect ( m_passphrase_dialog , & QDialog : : rejected , [ this ] {
Q_EMIT finished ( ) ;
} ) ;
}
void CreateWalletActivity : : createWallet ( )
{
2021-08-24 19:46:13 +05:30
showProgressDialog (
//: Title of window indicating the progress of creation of a new wallet.
tr ( " Create Wallet " ) ,
/*: Descriptive text of the create wallet progress window which indicates
to the user which wallet is currently being created . */
tr ( " Creating Wallet <b>%1</b>… " ) . arg ( m_create_wallet_dialog - > walletName ( ) . toHtmlEscaped ( ) ) ) ;
2019-05-24 17:14:16 -04:00
std : : string name = m_create_wallet_dialog - > walletName ( ) . toStdString ( ) ;
uint64_t flags = 0 ;
2019-09-07 11:08:28 +02:00
if ( m_create_wallet_dialog - > isDisablePrivateKeysChecked ( ) ) {
2019-05-24 17:14:16 -04:00
flags | = WALLET_FLAG_DISABLE_PRIVATE_KEYS ;
}
2019-09-07 11:08:28 +02:00
if ( m_create_wallet_dialog - > isMakeBlankWalletChecked ( ) ) {
2019-05-24 17:14:16 -04:00
flags | = WALLET_FLAG_BLANK_WALLET ;
}
2019-07-11 18:21:21 -04:00
if ( m_create_wallet_dialog - > isDescriptorWalletChecked ( ) ) {
flags | = WALLET_FLAG_DESCRIPTORS ;
}
2020-02-21 21:13:43 +01:00
if ( m_create_wallet_dialog - > isExternalSignerChecked ( ) ) {
flags | = WALLET_FLAG_EXTERNAL_SIGNER ;
}
2019-05-24 17:14:16 -04:00
2022-01-06 18:35:53 +02:00
QTimer : : singleShot ( 500 ms , worker ( ) , [ this , name , flags ] {
2022-08-07 00:56:25 -03:00
auto wallet { node ( ) . walletLoader ( ) . createWallet ( name , m_passphrase , flags , m_warning_message ) } ;
2019-05-24 17:14:16 -04:00
2022-08-07 00:56:25 -03:00
if ( wallet ) {
m_wallet_model = m_wallet_controller - > getOrCreateWallet ( std : : move ( * wallet ) ) ;
} else {
m_error_message = util : : ErrorString ( wallet ) ;
}
2019-05-24 17:14:16 -04:00
2022-01-06 18:35:53 +02:00
QTimer : : singleShot ( 500 ms , this , & CreateWalletActivity : : finish ) ;
2019-05-24 17:14:16 -04:00
} ) ;
}
void CreateWalletActivity : : finish ( )
{
2020-05-10 11:42:11 +03:00
if ( ! m_error_message . empty ( ) ) {
2019-08-19 18:12:35 -04:00
QMessageBox : : critical ( m_parent_widget , tr ( " Create wallet failed " ) , QString : : fromStdString ( m_error_message . translated ) ) ;
2019-05-24 17:14:16 -04:00
} else if ( ! m_warning_message . empty ( ) ) {
2020-05-10 21:28:29 +03:00
QMessageBox : : warning ( m_parent_widget , tr ( " Create wallet warning " ) , QString : : fromStdString ( Join ( m_warning_message , Untranslated ( " \n " ) ) . translated ) ) ;
2019-05-24 17:14:16 -04:00
}
if ( m_wallet_model ) Q_EMIT created ( m_wallet_model ) ;
Q_EMIT finished ( ) ;
}
void CreateWalletActivity : : create ( )
{
m_create_wallet_dialog = new CreateWalletDialog ( m_parent_widget ) ;
2019-11-07 19:06:40 +01:00
2021-06-16 14:49:09 -04:00
std : : vector < std : : unique_ptr < interfaces : : ExternalSigner > > signers ;
2019-11-07 19:06:40 +01:00
try {
2021-06-16 14:49:09 -04:00
signers = node ( ) . listExternalSigners ( ) ;
2019-11-07 19:06:40 +01:00
} catch ( const std : : runtime_error & e ) {
QMessageBox : : critical ( nullptr , tr ( " Can't list signers " ) , e . what ( ) ) ;
}
2022-05-28 20:40:51 +02:00
if ( signers . size ( ) > 1 ) {
QMessageBox : : critical ( nullptr , tr ( " Too many external signers found " ) , QString : : fromStdString ( " More than one external signer found. Please connect only one at a time. " ) ) ;
signers . clear ( ) ;
}
2019-11-07 19:06:40 +01:00
m_create_wallet_dialog - > setSigners ( signers ) ;
2019-05-24 17:14:16 -04:00
m_create_wallet_dialog - > setWindowModality ( Qt : : ApplicationModal ) ;
m_create_wallet_dialog - > show ( ) ;
connect ( m_create_wallet_dialog , & QObject : : destroyed , [ this ] {
m_create_wallet_dialog = nullptr ;
} ) ;
connect ( m_create_wallet_dialog , & QDialog : : rejected , [ this ] {
Q_EMIT finished ( ) ;
} ) ;
connect ( m_create_wallet_dialog , & QDialog : : accepted , [ this ] {
2019-09-07 11:08:28 +02:00
if ( m_create_wallet_dialog - > isEncryptWalletChecked ( ) ) {
askPassphrase ( ) ;
2019-05-24 17:14:16 -04:00
} else {
createWallet ( ) ;
}
} ) ;
}
2019-06-21 15:13:15 +01:00
OpenWalletActivity : : OpenWalletActivity ( WalletController * wallet_controller , QWidget * parent_widget )
: WalletControllerActivity ( wallet_controller , parent_widget )
{
}
void OpenWalletActivity : : finish ( )
{
2020-05-10 11:42:11 +03:00
if ( ! m_error_message . empty ( ) ) {
2019-08-19 18:12:35 -04:00
QMessageBox : : critical ( m_parent_widget , tr ( " Open wallet failed " ) , QString : : fromStdString ( m_error_message . translated ) ) ;
2019-06-21 15:13:15 +01:00
} else if ( ! m_warning_message . empty ( ) ) {
2020-05-10 21:28:29 +03:00
QMessageBox : : warning ( m_parent_widget , tr ( " Open wallet warning " ) , QString : : fromStdString ( Join ( m_warning_message , Untranslated ( " \n " ) ) . translated ) ) ;
2019-01-21 16:58:20 +00:00
}
2019-06-21 15:13:15 +01:00
if ( m_wallet_model ) Q_EMIT opened ( m_wallet_model ) ;
2019-01-21 16:58:20 +00:00
Q_EMIT finished ( ) ;
}
2019-06-21 15:13:15 +01:00
void OpenWalletActivity : : open ( const std : : string & path )
{
QString name = path . empty ( ) ? QString ( " [ " + tr ( " default wallet " ) + " ] " ) : QString : : fromStdString ( path ) ;
2021-08-24 19:46:13 +05:30
showProgressDialog (
//: Title of window indicating the progress of opening of a wallet.
tr ( " Open Wallet " ) ,
/*: Descriptive text of the open wallet progress window which indicates
to the user which wallet is currently being opened . */
tr ( " Opening Wallet <b>%1</b>… " ) . arg ( name . toHtmlEscaped ( ) ) ) ;
2019-06-21 15:13:15 +01:00
QTimer : : singleShot ( 0 , worker ( ) , [ this , path ] {
2022-08-07 00:56:25 -03:00
auto wallet { node ( ) . walletLoader ( ) . loadWallet ( path , m_warning_message ) } ;
2019-06-21 15:13:15 +01:00
2022-08-07 00:56:25 -03:00
if ( wallet ) {
m_wallet_model = m_wallet_controller - > getOrCreateWallet ( std : : move ( * wallet ) ) ;
} else {
m_error_message = util : : ErrorString ( wallet ) ;
}
2019-06-21 15:13:15 +01:00
QTimer : : singleShot ( 0 , this , & OpenWalletActivity : : finish ) ;
} ) ;
}
2021-05-22 22:27:45 +03:00
LoadWalletsActivity : : LoadWalletsActivity ( WalletController * wallet_controller , QWidget * parent_widget )
: WalletControllerActivity ( wallet_controller , parent_widget )
{
}
void LoadWalletsActivity : : load ( )
{
2021-08-24 19:46:13 +05:30
showProgressDialog (
//: Title of progress window which is displayed when wallets are being loaded.
tr ( " Load Wallets " ) ,
/*: Descriptive text of the load wallets progress window which indicates to
the user that wallets are currently being loaded . */
tr ( " Loading wallets… " ) ) ;
2021-05-22 22:27:45 +03:00
QTimer : : singleShot ( 0 , worker ( ) , [ this ] {
2021-12-22 13:44:55 -05:00
for ( auto & wallet : node ( ) . walletLoader ( ) . getWallets ( ) ) {
2021-05-22 22:27:45 +03:00
m_wallet_controller - > getOrCreateWallet ( std : : move ( wallet ) ) ;
}
QTimer : : singleShot ( 0 , this , [ this ] { Q_EMIT finished ( ) ; } ) ;
} ) ;
}
2021-12-16 18:22:09 -03:00
RestoreWalletActivity : : RestoreWalletActivity ( WalletController * wallet_controller , QWidget * parent_widget )
: WalletControllerActivity ( wallet_controller , parent_widget )
{
}
void RestoreWalletActivity : : restore ( const fs : : path & backup_file , const std : : string & wallet_name )
{
QString name = QString : : fromStdString ( wallet_name ) ;
showProgressDialog (
//: Title of progress window which is displayed when wallets are being restored.
tr ( " Restore Wallet " ) ,
/*: Descriptive text of the restore wallets progress window which indicates to
the user that wallets are currently being restored . */
tr ( " Restoring Wallet <b>%1</b>… " ) . arg ( name . toHtmlEscaped ( ) ) ) ;
QTimer : : singleShot ( 0 , worker ( ) , [ this , backup_file , wallet_name ] {
2022-07-12 15:35:41 +02:00
auto wallet { node ( ) . walletLoader ( ) . restoreWallet ( backup_file , wallet_name , m_warning_message ) } ;
2021-12-16 18:22:09 -03:00
2022-08-07 00:56:25 -03:00
if ( wallet ) {
m_wallet_model = m_wallet_controller - > getOrCreateWallet ( std : : move ( * wallet ) ) ;
} else {
m_error_message = util : : ErrorString ( wallet ) ;
}
2021-12-16 18:22:09 -03:00
QTimer : : singleShot ( 0 , this , & RestoreWalletActivity : : finish ) ;
} ) ;
}
void RestoreWalletActivity : : finish ( )
{
if ( ! m_error_message . empty ( ) ) {
//: Title of message box which is displayed when the wallet could not be restored.
QMessageBox : : critical ( m_parent_widget , tr ( " Restore wallet failed " ) , QString : : fromStdString ( m_error_message . translated ) ) ;
} else if ( ! m_warning_message . empty ( ) ) {
//: Title of message box which is displayed when the wallet is restored with some warning.
QMessageBox : : warning ( m_parent_widget , tr ( " Restore wallet warning " ) , QString : : fromStdString ( Join ( m_warning_message , Untranslated ( " \n " ) ) . translated ) ) ;
} else {
//: Title of message box which is displayed when the wallet is successfully restored.
QMessageBox : : information ( m_parent_widget , tr ( " Restore wallet message " ) , QString : : fromStdString ( Untranslated ( " Wallet restored successfully \n " ) . translated ) ) ;
}
if ( m_wallet_model ) Q_EMIT restored ( m_wallet_model ) ;
Q_EMIT finished ( ) ;
}