2021-05-18 15:59:18 +00:00
// SPDX-License-Identifier: BSD-3-Clause
2022-02-10 10:26:41 +00:00
// SPDX-FileCopyrightText: 2020-2022 The Monero Project
2021-05-18 15:59:18 +00:00
# include "WindowManager.h"
2021-06-28 17:48:23 +00:00
2021-07-08 00:34:27 +00:00
# include <QInputDialog>
2021-06-28 17:48:23 +00:00
# include <QMessageBox>
2021-05-18 15:59:18 +00:00
# include "constants.h"
2021-06-27 11:46:32 +00:00
# include "dialog/PasswordDialog.h"
# include "dialog/SplashDialog.h"
2021-05-18 15:59:18 +00:00
# include "utils/Icons.h"
# include "utils/NetworkManager.h"
2021-06-28 17:48:23 +00:00
# include "utils/os/tails.h"
2021-05-18 15:59:18 +00:00
# include "utils/TorManager.h"
2021-06-28 17:48:23 +00:00
# include "utils/WebsocketNotifier.h"
2021-05-18 15:59:18 +00:00
2022-03-04 16:20:17 +00:00
WindowManager : : WindowManager ( EventFilter * eventFilter )
: eventFilter ( eventFilter )
{
2021-05-18 15:59:18 +00:00
m_walletManager = WalletManager : : instance ( ) ;
m_splashDialog = new SplashDialog ;
2021-07-03 01:29:13 +00:00
m_cleanupThread = new QThread ( ) ;
2021-05-18 15:59:18 +00:00
connect ( m_walletManager , & WalletManager : : walletOpened , this , & WindowManager : : onWalletOpened ) ;
connect ( m_walletManager , & WalletManager : : walletCreated , this , & WindowManager : : onWalletCreated ) ;
connect ( m_walletManager , & WalletManager : : deviceButtonRequest , this , & WindowManager : : onDeviceButtonRequest ) ;
2021-07-07 02:38:15 +00:00
connect ( m_walletManager , & WalletManager : : deviceButtonPressed , this , & WindowManager : : onDeviceButtonPressed ) ;
2021-05-18 15:59:18 +00:00
connect ( m_walletManager , & WalletManager : : deviceError , this , & WindowManager : : onDeviceError ) ;
2021-07-08 00:34:27 +00:00
connect ( m_walletManager , & WalletManager : : walletPassphraseNeeded , this , & WindowManager : : onWalletPassphraseNeeded ) ;
2021-05-18 15:59:18 +00:00
connect ( qApp , & QGuiApplication : : lastWindowClosed , this , & WindowManager : : quitAfterLastWindow ) ;
m_tray = new QSystemTrayIcon ( icons ( ) - > icon ( " appicons/64x64.png " ) ) ;
m_tray - > setToolTip ( " Feather Wallet " ) ;
this - > buildTrayMenu ( ) ;
m_tray - > show ( ) ;
this - > initSkins ( ) ;
2021-05-27 01:58:07 +00:00
if ( ! config ( ) - > get ( Config : : firstRun ) . toBool ( ) | | TailsOS : : detect ( ) | | WhonixOS : : detect ( ) ) {
2021-05-18 15:59:18 +00:00
this - > onInitialNetworkConfigured ( ) ;
}
2021-05-26 23:20:37 +00:00
this - > startupWarning ( ) ;
2021-05-18 15:59:18 +00:00
if ( ! this - > autoOpenWallet ( ) ) {
this - > initWizard ( ) ;
}
}
2021-07-11 15:55:42 +00:00
WindowManager : : ~ WindowManager ( ) {
qDebug ( ) < < " ~WindowManager " ;
m_cleanupThread - > quit ( ) ;
m_cleanupThread - > wait ( ) ;
}
2021-05-18 15:59:18 +00:00
// ######################## APPLICATION LIFECYCLE ########################
void WindowManager : : quitAfterLastWindow ( ) {
if ( m_windows . length ( ) > 0 | | m_openingWallet ) {
return ;
}
qDebug ( ) < < " No wizards in progress and no wallets open, quitting application. " ;
2021-05-24 19:56:23 +00:00
this - > close ( ) ;
2021-05-18 15:59:18 +00:00
}
void WindowManager : : close ( ) {
qDebug ( ) < < Q_FUNC_INFO ;
for ( const auto & window : m_windows ) {
window - > close ( ) ;
}
2021-05-25 13:15:19 +00:00
2021-05-18 15:59:18 +00:00
torManager ( ) - > stop ( ) ;
2021-05-25 13:15:19 +00:00
m_tray - > hide ( ) ;
2021-05-18 15:59:18 +00:00
QApplication : : quit ( ) ;
}
void WindowManager : : closeWindow ( MainWindow * window ) {
m_windows . removeOne ( window ) ;
2021-07-03 01:29:13 +00:00
// Move Wallet to a different thread for cleanup so it doesn't block GUI thread
window - > m_ctx - > wallet - > moveToThread ( m_cleanupThread ) ;
m_cleanupThread - > start ( ) ;
window - > m_ctx - > wallet - > deleteLater ( ) ;
2021-05-18 15:59:18 +00:00
}
void WindowManager : : restartApplication ( const QString & binaryFilename ) {
QProcess : : startDetached ( binaryFilename , qApp - > arguments ( ) ) ;
this - > close ( ) ;
}
2021-05-26 23:20:37 +00:00
void WindowManager : : startupWarning ( ) {
// Stagenet / Testnet
auto worthlessWarning = QString ( " Feather wallet is currently running in %1 mode. This is meant "
" for developers only. Your coins are WORTHLESS. " ) ;
if ( constants : : networkType = = NetworkType : : STAGENET & & config ( ) - > get ( Config : : warnOnStagenet ) . toBool ( ) ) {
this - > showWarningMessageBox ( " Warning " , worthlessWarning . arg ( " stagenet " ) ) ;
config ( ) - > set ( Config : : warnOnStagenet , false ) ;
}
else if ( constants : : networkType = = NetworkType : : TESTNET & & config ( ) - > get ( Config : : warnOnTestnet ) . toBool ( ) ) {
this - > showWarningMessageBox ( " Warning " , worthlessWarning . arg ( " testnet " ) ) ;
config ( ) - > set ( Config : : warnOnTestnet , false ) ;
}
}
void WindowManager : : showWarningMessageBox ( const QString & title , const QString & message ) {
QMessageBox msgBox ;
msgBox . setWindowIcon ( icons ( ) - > icon ( " appicons/64x64.png " ) ) ;
msgBox . setIcon ( QMessageBox : : Warning ) ;
msgBox . setText ( message ) ;
msgBox . setWindowTitle ( title ) ;
msgBox . setStandardButtons ( QMessageBox : : Ok ) ;
msgBox . setDefaultButton ( QMessageBox : : Ok ) ;
msgBox . exec ( ) ;
}
2022-03-03 22:27:54 +00:00
void WindowManager : : raise ( ) {
if ( ! m_windows . isEmpty ( ) ) {
m_windows . first ( ) - > bringToFront ( ) ;
}
else if ( m_wizard ) {
m_wizard - > show ( ) ;
m_wizard - > raise ( ) ;
m_wizard - > activateWindow ( ) ;
}
else {
// This shouldn't happen
this - > close ( ) ;
}
}
2021-05-18 15:59:18 +00:00
// ######################## WALLET OPEN ########################
void WindowManager : : tryOpenWallet ( const QString & path , const QString & password ) {
// Path : path to .keys file
QString absolutePath = path ;
if ( absolutePath . startsWith ( " ~ " ) ) {
absolutePath . replace ( 0 , 1 , QDir : : homePath ( ) ) ;
}
// If the wallet is already open, just bring window to front
for ( const auto & window : m_windows ) {
if ( absolutePath = = window - > walletKeysPath ( ) | | absolutePath = = window - > walletCachePath ( ) ) {
window - > bringToFront ( ) ;
return ;
}
}
if ( ! Utils : : fileExists ( path ) ) {
this - > handleWalletError ( QString ( " Wallet not found: %1 " ) . arg ( path ) ) ;
return ;
}
m_openingWallet = true ;
m_walletManager - > openWalletAsync ( path , password , constants : : networkType , 1 ) ;
}
void WindowManager : : onWalletOpened ( Wallet * wallet ) {
2022-03-04 12:30:26 +00:00
auto status = wallet - > status ( ) ;
if ( status ! = Wallet : : Status_Ok ) {
2021-05-18 15:59:18 +00:00
QString errMsg = wallet - > errorString ( ) ;
2022-03-04 12:30:26 +00:00
QString keysPath = wallet - > keysPath ( ) ;
QString cachePath = wallet - > cachePath ( ) ;
wallet - > deleteLater ( ) ;
if ( status = = Wallet : : Status_BadPassword ) {
2021-05-18 15:59:18 +00:00
// Don't show incorrect password when we try with empty password for the first time
bool showIncorrectPassword = m_openWalletTriedOnce ;
m_openWalletTriedOnce = true ;
2022-03-04 12:30:26 +00:00
this - > onWalletOpenPasswordRequired ( showIncorrectPassword , keysPath ) ;
2021-05-18 15:59:18 +00:00
}
else if ( errMsg = = QString ( " basic_string::_M_replace_aux " ) | | errMsg = = QString ( " std::bad_alloc " ) ) {
qCritical ( ) < < errMsg ;
2022-03-04 12:30:26 +00:00
WalletManager : : clearWalletCache ( cachePath ) ;
2021-05-18 15:59:18 +00:00
errMsg = QString ( " %1 \n \n Attempted to clean wallet cache. Please restart Feather. " ) . arg ( errMsg ) ;
this - > handleWalletError ( errMsg ) ;
} else {
this - > handleWalletError ( errMsg ) ;
}
return ;
}
2021-05-26 22:24:35 +00:00
this - > onInitialNetworkConfigured ( ) ;
2022-03-04 12:30:26 +00:00
if ( ! wallet - > cacheAttributeExists ( " feather.xmrig_password " ) & & ! wallet - > cacheAttributeExists ( " feather.created " ) ) {
auto result = QMessageBox : : question ( nullptr , " Foreign wallet " ,
" This wallet file was not created with Feather. This may cause unexpected behavior. Please restore your wallet from seed. \n \n Open this wallet anyway? " ) ;
if ( result = = QMessageBox : : No ) {
wallet - > deleteLater ( ) ;
this - > initWizard ( ) ;
return ;
}
}
2022-03-04 16:57:00 +00:00
if ( ! wallet - > viewOnly ( ) & & ! wallet - > isHwBacked ( ) ) {
if ( ! wallet - > isDeterministic ( ) ) {
auto result = QMessageBox : : question ( nullptr , " Non-deterministic wallet " ,
" This wallet is not deterministic. This may be caused by a corrupt keys file. "
" If you are unsure what this means, RESTORE YOUR WALLET FROM SEED. \n \n "
" USING THIS WALLET FILE MAY RESULT IN A LOSS OF FUNDS. \n \n "
" Open this wallet anyway? " ) ;
if ( result = = QMessageBox : : No ) {
wallet - > deleteLater ( ) ;
this - > initWizard ( ) ;
return ;
}
}
}
2021-05-18 15:59:18 +00:00
// Create new mainwindow with wallet
m_splashDialog - > hide ( ) ;
m_openWalletTriedOnce = false ;
auto * window = new MainWindow ( this , wallet ) ;
m_windows . append ( window ) ;
this - > buildTrayMenu ( ) ;
m_openingWallet = false ;
}
void WindowManager : : onWalletOpenPasswordRequired ( bool invalidPassword , const QString & path ) {
QFileInfo fileInfo ( path ) ;
PasswordDialog dialog { fileInfo . fileName ( ) , invalidPassword } ;
switch ( dialog . exec ( ) ) {
case QDialog : : Rejected :
{
m_openWalletTriedOnce = false ;
2021-08-14 17:43:50 +00:00
m_wizard - > show ( ) ;
2021-05-18 15:59:18 +00:00
return ;
}
}
this - > tryOpenWallet ( path , dialog . password ) ;
}
bool WindowManager : : autoOpenWallet ( ) {
QString autoPath = config ( ) - > get ( Config : : autoOpenWalletPath ) . toString ( ) ;
if ( ! autoPath . isEmpty ( ) & & autoPath . startsWith ( QString : : number ( constants : : networkType ) ) ) {
autoPath . remove ( 0 , 1 ) ;
}
if ( ! autoPath . isEmpty ( ) & & Utils : : fileExists ( autoPath ) ) {
this - > tryOpenWallet ( autoPath , " " ) ; // TODO: get password from --password
return true ;
}
return false ;
}
// ######################## WALLET CREATION ########################
2022-02-25 15:29:33 +00:00
void WindowManager : : tryCreateWallet ( Seed seed , const QString & path , const QString & password , const QString & seedLanguage ,
2021-05-18 15:59:18 +00:00
const QString & seedOffset ) {
if ( Utils : : fileExists ( path ) ) {
auto err = QString ( " Failed to write wallet to path: \" %1 \" ; file already exists. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
if ( seed . mnemonic . isEmpty ( ) ) {
this - > handleWalletError ( " Mnemonic seed error. Failed to write wallet. " ) ;
return ;
}
Wallet * wallet = nullptr ;
2022-05-23 21:43:33 +00:00
if ( seed . type = = Seed : : Type : : POLYSEED | | seed . type = = Seed : : Type : : TEVADOR ) {
2021-05-18 15:59:18 +00:00
wallet = m_walletManager - > createDeterministicWalletFromSpendKey ( path , password , seed . language , constants : : networkType , seed . spendKey , seed . restoreHeight , constants : : kdfRounds , seedOffset ) ;
}
2022-05-23 21:43:33 +00:00
else if ( seed . type = = Seed : : Type : : MONERO ) {
2021-05-18 15:59:18 +00:00
wallet = m_walletManager - > recoveryWallet ( path , password , seed . mnemonic . join ( " " ) , seedOffset , constants : : networkType , seed . restoreHeight , constants : : kdfRounds ) ;
}
if ( ! wallet ) {
this - > handleWalletError ( " Failed to write wallet " ) ;
return ;
}
2022-05-26 18:30:39 +00:00
wallet - > setCacheAttribute ( " feather.seed " , seed . mnemonic . join ( " " ) ) ;
wallet - > setCacheAttribute ( " feather.seedoffset " , seedOffset ) ;
2021-05-18 15:59:18 +00:00
this - > onWalletOpened ( wallet ) ;
}
2021-07-01 21:00:47 +00:00
void WindowManager : : tryCreateWalletFromDevice ( const QString & path , const QString & password , const QString & deviceName , int restoreHeight )
2021-05-18 15:59:18 +00:00
{
if ( Utils : : fileExists ( path ) ) {
auto err = QString ( " Failed to write wallet to path: \" %1 \" ; file already exists. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
m_openingWallet = true ;
2021-07-01 21:00:47 +00:00
m_walletManager - > createWalletFromDeviceAsync ( path , password , constants : : networkType , deviceName , restoreHeight ) ;
2021-05-18 15:59:18 +00:00
}
void WindowManager : : tryCreateWalletFromKeys ( const QString & path , const QString & password , const QString & address ,
const QString & viewkey , const QString & spendkey , quint64 restoreHeight ) {
if ( Utils : : fileExists ( path ) ) {
auto err = QString ( " Failed to write wallet to path: \" %1 \" ; file already exists. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
if ( ! WalletManager : : addressValid ( address , constants : : networkType ) ) {
auto err = QString ( " Failed to create wallet. Invalid address provided. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
if ( ! WalletManager : : keyValid ( viewkey , address , true , constants : : networkType ) ) {
auto err = QString ( " Failed to create wallet. Invalid viewkey provided. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
if ( ! spendkey . isEmpty ( ) & & ! WalletManager : : keyValid ( spendkey , address , false , constants : : networkType ) ) {
auto err = QString ( " Failed to create wallet. Invalid spendkey provided. " ) . arg ( path ) ;
this - > handleWalletError ( err ) ;
return ;
}
Wallet * wallet = m_walletManager - > createWalletFromKeys ( path , password , constants : : seedLanguage , constants : : networkType , address , viewkey , spendkey , restoreHeight ) ;
m_openingWallet = true ;
m_walletManager - > walletOpened ( wallet ) ;
}
void WindowManager : : onWalletCreated ( Wallet * wallet ) {
// Currently only called when a wallet is created from device.
auto state = wallet - > status ( ) ;
if ( state ! = Wallet : : Status_Ok ) {
qDebug ( ) < < Q_FUNC_INFO < < QString ( " Wallet open error: %1 " ) . arg ( wallet - > errorString ( ) ) ;
this - > displayWalletErrorMessage ( wallet - > errorString ( ) ) ;
m_splashDialog - > hide ( ) ;
this - > showWizard ( WalletWizard : : Page_Menu ) ;
return ;
}
this - > onWalletOpened ( wallet ) ;
}
// ######################## ERROR HANDLING ########################
void WindowManager : : handleWalletError ( const QString & message ) {
qCritical ( ) < < message ;
this - > displayWalletErrorMessage ( message ) ;
this - > initWizard ( ) ;
}
void WindowManager : : displayWalletErrorMessage ( const QString & message ) {
2021-07-01 21:00:47 +00:00
QString errMsg = QString ( " Error: %1 " ) . arg ( message ) ;
2021-07-07 17:04:31 +00:00
QString link ;
2021-07-01 21:00:47 +00:00
// Ledger
2021-05-18 15:59:18 +00:00
if ( message . contains ( " No device found " ) ) {
2021-07-01 21:00:47 +00:00
errMsg + = " \n \n This wallet is backed by a Ledger hardware device. Make sure the Monero app is opened on the device. \n "
2021-05-18 15:59:18 +00:00
" You may need to restart Feather before the device can get detected. " ;
}
if ( message . contains ( " Unable to open device " ) ) {
errMsg + = " \n \n The device might be in use by a different application. " ;
2021-05-25 18:00:02 +00:00
# if defined(Q_OS_LINUX)
errMsg + = " \n \n Note: On Linux you may need to follow the instructions in the link below before the device can be opened: \n "
2021-07-01 21:00:47 +00:00
" https://support.ledger.com/hc/en-us/articles/115005165269-Fix-connection-issues " ;
2021-07-07 17:04:31 +00:00
link = " https://support.ledger.com/hc/en-us/articles/115005165269-Fix-connection-issues " ;
2021-07-01 21:00:47 +00:00
# endif
}
// TREZOR
if ( message . contains ( " Unable to claim libusb device " ) ) {
errMsg + = " \n \n This wallet is backed by a Trezor hardware device. Feather was unable to access the device. "
" Please make sure it is not opened by another program and try again. " ;
}
if ( message . contains ( " Cannot get a device address " ) ) {
errMsg + = " \n \n Restart the Trezor hardware device and try again. " ;
}
if ( message . contains ( " Could not connect to the device Trezor " ) | | message . contains ( " Device connect failed " ) ) {
2021-07-07 17:04:31 +00:00
errMsg + = " \n \n This wallet is backed by a Trezor hardware device. Make sure the device is connected to your computer and unlocked. " ;
2021-07-01 21:00:47 +00:00
# if defined(Q_OS_LINUX)
errMsg + = " \n \n Note: On Linux you may need to follow the instructions in the link below before the device can be opened: \n "
" https://wiki.trezor.io/Udev_rules " ;
2021-07-07 17:04:31 +00:00
link = " https://wiki.trezor.io/Udev_rules " ;
2021-05-25 18:00:02 +00:00
# endif
2021-05-18 15:59:18 +00:00
}
if ( message . contains ( " SW_CLIENT_NOT_SUPPORTED " ) ) {
errMsg + = " \n \n Incompatible version: you may need to upgrade the Monero app on the Ledger device to the latest version. " ;
}
else if ( message . contains ( " Wrong Device Status " ) ) {
errMsg + = " \n \n The device may need to be unlocked. " ;
}
else if ( message . contains ( " Wrong Channel " ) ) {
errMsg + = " \n \n Restart the hardware device and try again. " ;
}
QMessageBox msgBox ;
msgBox . setWindowIcon ( icons ( ) - > icon ( " appicons/64x64.png " ) ) ;
msgBox . setIcon ( QMessageBox : : Warning ) ;
msgBox . setText ( errMsg ) ;
msgBox . setWindowTitle ( " Wallet error " ) ;
msgBox . setStandardButtons ( QMessageBox : : Ok ) ;
msgBox . setDefaultButton ( QMessageBox : : Ok ) ;
2021-07-07 17:04:31 +00:00
QPushButton * openLinkButton = nullptr ;
if ( ! link . isEmpty ( ) ) {
openLinkButton = msgBox . addButton ( " Open link " , QMessageBox : : ActionRole ) ;
}
2021-05-18 15:59:18 +00:00
msgBox . exec ( ) ;
2021-07-07 17:04:31 +00:00
if ( openLinkButton & & msgBox . clickedButton ( ) = = openLinkButton ) {
Utils : : externalLinkWarning ( nullptr , link ) ;
}
2021-05-18 15:59:18 +00:00
}
// ######################## DEVICE ########################
void WindowManager : : onDeviceButtonRequest ( quint64 code ) {
2021-07-01 21:00:47 +00:00
QString message ;
switch ( code ) {
case 1 : // Trezor
message = " Action required on device: enter your PIN to continue. " ;
break ;
case 8 : // Trezor
message = " Action required on device: Export watch-only credentials to open the wallet. " ;
break ;
2021-07-08 11:21:09 +00:00
case 19 : // Trezor
message = " Action required on device: Enter passphrase to open the wallet. " ;
break ;
2021-07-01 21:00:47 +00:00
default :
message = " Action required on device: Export the view key to open the wallet. " ;
}
m_splashDialog - > setMessage ( message ) ;
2021-05-18 15:59:18 +00:00
m_splashDialog - > setIcon ( QPixmap ( " :/assets/images/key.png " ) ) ;
m_splashDialog - > show ( ) ;
m_splashDialog - > setEnabled ( true ) ;
}
2021-07-07 02:38:15 +00:00
void WindowManager : : onDeviceButtonPressed ( ) {
m_splashDialog - > hide ( ) ;
}
2021-05-18 15:59:18 +00:00
void WindowManager : : onDeviceError ( const QString & errorMessage ) {
// TODO: when does this get called?
qCritical ( ) < < Q_FUNC_INFO < < errorMessage ;
}
2021-07-08 00:34:27 +00:00
void WindowManager : : onWalletPassphraseNeeded ( bool on_device ) {
auto button = QMessageBox : : question ( nullptr , " Wallet Passphrase Needed " , " Enter passphrase on hardware wallet? \n \n "
" It is recommended to enter passphrase on "
" the hardware wallet for better security. " ,
QMessageBox : : Yes | QMessageBox : : No , QMessageBox : : Yes ) ;
if ( button = = QMessageBox : : Yes ) {
m_walletManager - > onPassphraseEntered ( " " , true , false ) ;
return ;
}
bool ok ;
QString passphrase = QInputDialog : : getText ( nullptr , " Wallet Passphrase Needed " , " Enter passphrase: " , QLineEdit : : EchoMode : : Password , " " , & ok ) ;
if ( ok ) {
m_walletManager - > onPassphraseEntered ( passphrase , false , false ) ;
} else {
m_walletManager - > onPassphraseEntered ( passphrase , false , true ) ;
}
}
2021-05-18 15:59:18 +00:00
// ######################## TRAY ########################
void WindowManager : : buildTrayMenu ( ) {
QMenu * menu ;
if ( ! m_tray - > contextMenu ( ) ) {
menu = new QMenu ( ) ;
m_tray - > setContextMenu ( menu ) ;
} else {
menu = m_tray - > contextMenu ( ) ;
menu - > clear ( ) ;
}
for ( const auto & window : m_windows ) {
QString name = window - > walletName ( ) ;
QMenu * submenu = menu - > addMenu ( name ) ;
submenu - > addAction ( " Show/Hide " , window , & MainWindow : : showOrHide ) ;
submenu - > addAction ( " Close " , window , & MainWindow : : close ) ;
}
menu - > addSeparator ( ) ;
menu - > addAction ( " Exit Feather " , this , & WindowManager : : close ) ;
}
// ######################## NETWORKING ########################
void WindowManager : : onInitialNetworkConfigured ( ) {
2021-05-26 22:24:35 +00:00
if ( ! m_initialNetworkConfigured ) {
m_initialNetworkConfigured = true ;
2021-05-27 02:50:58 +00:00
appData ( ) ;
2022-03-14 21:36:58 +00:00
2021-05-26 22:24:35 +00:00
this - > initTor ( ) ;
this - > initWS ( ) ;
}
2021-05-18 15:59:18 +00:00
}
void WindowManager : : initTor ( ) {
torManager ( ) - > init ( ) ;
torManager ( ) - > start ( ) ;
this - > onTorSettingsChanged ( ) ;
}
void WindowManager : : onTorSettingsChanged ( ) {
if ( Utils : : isTorsocks ( ) ) {
return ;
}
// use local tor -> bundled tor
QString host = config ( ) - > get ( Config : : socks5Host ) . toString ( ) ;
quint16 port = config ( ) - > get ( Config : : socks5Port ) . toString ( ) . toUShort ( ) ;
if ( ! torManager ( ) - > isLocalTor ( ) ) {
host = torManager ( ) - > featherTorHost ;
port = torManager ( ) - > featherTorPort ;
}
QNetworkProxy proxy { QNetworkProxy : : Socks5Proxy , host , port } ;
getNetworkTor ( ) - > setProxy ( proxy ) ;
websocketNotifier ( ) - > websocketClient . webSocket . setProxy ( proxy ) ;
emit torSettingsChanged ( ) ;
}
2022-03-15 12:36:20 +00:00
void WindowManager : : onWebsocketStatusChanged ( bool enabled ) {
emit websocketStatusChanged ( enabled ) ;
}
2021-05-18 15:59:18 +00:00
void WindowManager : : initWS ( ) {
2022-03-14 21:36:58 +00:00
if ( config ( ) - > get ( Config : : offlineMode ) . toBool ( ) ) {
return ;
}
2022-03-04 21:55:29 +00:00
if ( config ( ) - > get ( Config : : disableWebsocket ) . toBool ( ) ) {
return ;
}
2021-05-18 15:59:18 +00:00
websocketNotifier ( ) - > websocketClient . start ( ) ;
}
// ######################## WIZARD ########################
WalletWizard * WindowManager : : createWizard ( WalletWizard : : Page startPage ) const {
auto * wizard = new WalletWizard ;
connect ( wizard , & WalletWizard : : initialNetworkConfigured , this , & WindowManager : : onInitialNetworkConfigured ) ;
connect ( wizard , & WalletWizard : : skinChanged , this , & WindowManager : : changeSkin ) ;
connect ( wizard , & WalletWizard : : openWallet , this , & WindowManager : : tryOpenWallet ) ;
connect ( wizard , & WalletWizard : : createWallet , this , & WindowManager : : tryCreateWallet ) ;
connect ( wizard , & WalletWizard : : createWalletFromKeys , this , & WindowManager : : tryCreateWalletFromKeys ) ;
connect ( wizard , & WalletWizard : : createWalletFromDevice , this , & WindowManager : : tryCreateWalletFromDevice ) ;
return wizard ;
}
void WindowManager : : initWizard ( ) {
auto startPage = WalletWizard : : Page_Menu ;
if ( config ( ) - > get ( Config : : firstRun ) . toBool ( ) & & ! ( TailsOS : : detect ( ) | | WhonixOS : : detect ( ) ) ) {
startPage = WalletWizard : : Page_Network ;
}
this - > showWizard ( startPage ) ;
}
void WindowManager : : showWizard ( WalletWizard : : Page startPage ) {
if ( ! m_wizard ) {
m_wizard = this - > createWizard ( startPage ) ;
}
2022-05-25 10:59:28 +00:00
m_wizard - > resetFields ( ) ;
2021-05-18 15:59:18 +00:00
m_wizard - > setStartId ( startPage ) ;
m_wizard - > restart ( ) ;
m_wizard - > setEnabled ( true ) ;
m_wizard - > show ( ) ;
}
void WindowManager : : wizardOpenWallet ( ) {
this - > showWizard ( WalletWizard : : Page_OpenWallet ) ;
}
// ######################## SKINS ########################
void WindowManager : : initSkins ( ) {
m_skins . insert ( " Native " , " " ) ;
QString qdarkstyle = this - > loadStylesheet ( " :qdarkstyle/style.qss " ) ;
if ( ! qdarkstyle . isEmpty ( ) )
m_skins . insert ( " QDarkStyle " , qdarkstyle ) ;
QString breeze_dark = this - > loadStylesheet ( " :/dark.qss " ) ;
if ( ! breeze_dark . isEmpty ( ) )
m_skins . insert ( " Breeze/Dark " , breeze_dark ) ;
QString breeze_light = this - > loadStylesheet ( " :/light.qss " ) ;
if ( ! breeze_light . isEmpty ( ) )
m_skins . insert ( " Breeze/Light " , breeze_light ) ;
QString skin = config ( ) - > get ( Config : : skin ) . toString ( ) ;
qApp - > setStyleSheet ( m_skins [ skin ] ) ;
}
QString WindowManager : : loadStylesheet ( const QString & resource ) {
QFile f ( resource ) ;
if ( ! f . exists ( ) ) {
printf ( " Unable to set stylesheet, file not found \n " ) ;
f . close ( ) ;
return " " ;
}
f . open ( QFile : : ReadOnly | QFile : : Text ) ;
QTextStream ts ( & f ) ;
QString data = ts . readAll ( ) ;
f . close ( ) ;
return data ;
}
void WindowManager : : changeSkin ( const QString & skinName ) {
if ( ! m_skins . contains ( skinName ) ) {
qWarning ( ) < < QString ( " No such skin %1 " ) . arg ( skinName ) ;
return ;
}
config ( ) - > set ( Config : : skin , skinName ) ;
qApp - > setStyleSheet ( m_skins [ skinName ] ) ;
qDebug ( ) < < QString ( " Skin changed to %1 " ) . arg ( skinName ) ;
}