@ -1,4 +1,4 @@
// Copyright 2019-2021 The Hush Developers
// Copyright 2019-2021 The Hush Developers
// Released under the GPLv3
# include "mainwindow.h"
# include "addressbook.h"
@ -8,11 +8,13 @@
# include "ui_mobileappconnector.h"
# include "ui_addressbook.h"
# include "ui_privkey.h"
# include "ui_qrcode.h"
# include "ui_viewkey.h"
# include "ui_about.h"
# include "ui_settings.h"
# include "ui_viewalladdresses.h"
# include "ui_validateaddress.h"
# include "ui_rescandialog.h"
# include "rpc.h"
# include "balancestablemodel.h"
# include "settings.h"
@ -33,7 +35,8 @@ MainWindow::MainWindow(QWidget *parent) :
theme_name = Settings : : getInstance ( ) - > get_theme_name ( ) ;
} catch ( . . . )
{
theme_name = " default " ;
qDebug ( ) < < __func__ < < " : exception! " ;
theme_name = " dark " ;
}
this - > slot_change_theme ( theme_name ) ;
@ -112,6 +115,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Initialize to the balances tab
ui - > tabWidget - > setCurrentIndex ( 0 ) ;
setupSendTab ( ) ;
setupTransactionsTab ( ) ;
setupReceiveTab ( ) ;
@ -185,6 +189,119 @@ void MainWindow::doClose() {
closeEvent ( nullptr ) ;
}
// Called every time, when a menu entry of the language menu is called
void MainWindow : : slotLanguageChanged ( QString lang )
{
qDebug ( ) < < __func__ < < " : lang= " < < lang ;
if ( lang ! = " " ) {
// load the language
loadLanguage ( lang ) ;
QDialog settingsDialog ( this ) ;
qDebug ( ) < < __func__ < < " : retranslating settingsDialog " ;
settings . retranslateUi ( & settingsDialog ) ;
}
}
void switchTranslator ( QTranslator & translator , const QString & filename ) {
qDebug ( ) < < __func__ < < " : filename= " < < filename ;
// remove the old translator
qApp - > removeTranslator ( & translator ) ;
// load the new translator
QString path = QApplication : : applicationDirPath ( ) ;
path . append ( " /res/ " ) ;
qDebug ( ) < < __func__ < < " : attempting to load " < < path + filename ;
if ( translator . load ( path + filename ) ) {
qApp - > installTranslator ( & translator ) ;
} else {
qDebug ( ) < < __func__ < < " : translation path does not exist! " < < path + filename ;
}
}
void MainWindow : : loadLanguage ( QString & rLanguage ) {
qDebug ( ) < < __func__ < < " : currLang= " < < m_currLang < < " rLanguage= " < < rLanguage ;
QString lang = rLanguage ;
// this allows us to call this function with just a locale such as "zh"
if ( lang . right ( 1 ) = = " ) " ) {
lang . chop ( 1 ) ; // remove trailing )
}
// remove everything up to and including the first (
lang = lang . remove ( 0 , lang . indexOf ( " ( " ) + 1 ) ;
// NOTE: language codes can be 2 or 3 letters
// https://www.loc.gov/standards/iso639-2/php/code_list.php
QString languageName ;
if ( m_currLang ! = lang ) {
qDebug ( ) < < __func__ < < " : changing language to lang= " < < lang ;
m_currLang = lang ;
QLocale locale = QLocale ( m_currLang ) ;
qDebug ( ) < < __func__ < < " : locale nativeLanguage= " < < locale . nativeLanguageName ( ) ;
// an invalid locale such as "zz" will give the C locale which has no native language name
if ( locale . nativeLanguageName ( ) = = " " ) {
qDebug ( ) < < __func__ < < " : detected invalid language in config file, defaulting to en " ;
locale = QLocale ( " en " ) ;
Settings : : getInstance ( ) - > set_language ( " en " ) ;
m_currLang = " en " ;
lang = " en " ;
}
qDebug ( ) < < __func__ < < " : locale= " < < locale ;
QLocale : : setDefault ( locale ) ;
qDebug ( ) < < __func__ < < " : setDefault locale= " < < locale ;
languageName = locale . nativeLanguageName ( ) ; //locale.language());
qDebug ( ) < < __func__ < < " : languageName= " < < languageName ;
switchTranslator ( m_translator , QString ( " silentdragon_%1.qm " ) . arg ( lang ) ) ;
switchTranslator ( m_translatorQt , QString ( " qt_%1.qm " ) . arg ( lang ) ) ;
// TODO: this likely wont work for RTL languages like Arabic
auto first = QString ( languageName . at ( 0 ) ) . toUpper ( ) ;
languageName = first + languageName . right ( languageName . size ( ) - 1 ) ;
if ( lang = = " en " ) {
languageName . replace ( " American " , " " ) ;
}
ui - > statusBar - > showMessage ( tr ( " Language changed to " ) + " " + languageName + " ( " + lang + " ) " ) ;
}
// write this language (the locale shortcode) out to config file
if ( lang ! = " " ) {
// only write valid languages to config file
Settings : : getInstance ( ) - > set_language ( lang ) ;
}
}
void MainWindow : : changeEvent ( QEvent * event ) {
if ( 0 ! = event ) {
switch ( event - > type ( ) ) {
// this event is sent if a translator is loaded
case QEvent : : LanguageChange :
qDebug ( ) < < __func__ < < " : QEvent::LanguageChange changeEvent " ;
ui - > retranslateUi ( this ) ;
break ;
// this event is sent, if the system, language changes
case QEvent : : LocaleChange :
{
QString locale = QLocale : : system ( ) . name ( ) ;
locale . truncate ( locale . lastIndexOf ( ' _ ' ) ) ;
qDebug ( ) < < __func__ < < " : QEvent::LocaleChange changeEvent locale= " < < locale ;
loadLanguage ( locale ) ;
}
break ;
default :
qDebug ( ) < < __func__ < < " : " < < event - > type ( ) ;
}
}
QMainWindow : : changeEvent ( event ) ;
}
void MainWindow : : closeEvent ( QCloseEvent * event ) {
QSettings s ;
@ -265,7 +382,7 @@ void MainWindow::setupSettingsModal() {
// Set up File -> Settings action
QObject : : connect ( ui - > actionSettings , & QAction : : triggered , [ = ] ( ) {
QDialog settingsDialog ( this ) ;
Ui_Settings settings ;
//Ui_Settings settings;
settings . setupUi ( & settingsDialog ) ;
Settings : : saveRestore ( & settingsDialog ) ;
@ -295,14 +412,22 @@ void MainWindow::setupSettingsModal() {
}
} ) ;
// Setup rescan button
QObject : : connect ( settings . rescanButton , & QPushButton : : clicked , [ = ] ( ) {
this - > rescanButtonClicked ( 1 ) ;
} ) ;
int theme_index = settings . comboBoxTheme - > findText ( Settings : : getInstance ( ) - > get_theme_name ( ) , Qt : : MatchExactly ) ;
settings . comboBoxTheme - > setCurrentIndex ( theme_index ) ;
QObject : : connect ( settings . comboBoxTheme , & QComboBox : : currentTextChanged , [ = ] ( QString theme_name ) {
this - > slot_change_theme ( theme_name ) ;
QMessageBox : : information ( this , tr ( " Theme Change " ) , tr ( " This change can take a few seconds. " ) , QMessageBox : : Ok ) ;
// QMessageBox::information(this, tr("Theme Change"), tr("This change can take a few seconds."), QMessageBox::Ok);
// For some reason, changing language also triggers this
//ui->statusBar->showMessage(tr("Theme changed to ") + theme_name);
} ) ;
// Set local currency
QString ticker = Settings : : getInstance ( ) - > get_currency_name ( ) ;
int currency_index = settings . comboBoxCurrency - > findText ( ticker , Qt : : MatchExactly ) ;
@ -310,7 +435,8 @@ void MainWindow::setupSettingsModal() {
QObject : : connect ( settings . comboBoxCurrency , & QComboBox : : currentTextChanged , [ = ] ( QString ticker ) {
this - > slot_change_currency ( ticker ) ;
rpc - > refresh ( true ) ;
QMessageBox : : information ( this , tr ( " Currency Change " ) , tr ( " This change can take a few seconds. " ) , QMessageBox : : Ok ) ;
ui - > statusBar - > showMessage ( tr ( " Currency changed to " ) + " " + ticker ) ;
// QMessageBox::information(this, tr("Currency Change"), tr("This change can take a few seconds."), QMessageBox::Ok);
} ) ;
// Save sent transactions
@ -342,18 +468,24 @@ void MainWindow::setupSettingsModal() {
settings . lblTor - > setToolTip ( tooltip ) ;
}
//Use Consolidation
// Wallet Size
if ( rpc - > getConnection ( ) ! = nullptr ) {
int size = 0 ;
qDebug ( ) < < __func__ < < " : settings hushDir= " < < rpc - > getConnection ( ) - > config - > hushDir ;
QDir hushdir ( rpc - > getConnection ( ) - > config - > hushDir ) ;
QFile WalletSize ( hushdir . filePath ( " wallet.dat " ) ) ;
if ( WalletSize . open ( QIODevice : : ReadOnly ) ) {
size = WalletSize . size ( ) / 1000000 ; //when file does open.
//QString size1 = QString::number(size) ;
settings . WalletSize - > setText ( QString : : number ( size ) ) ;
WalletSize . close ( ) ;
}
}
// Use Consolidation
bool isUsingConsolidation = false ;
int size = 0 ;
QDir hushdir ( rpc - > getConnection ( ) - > config - > hushDir ) ;
QFile WalletSize ( hushdir . filePath ( " wallet.dat " ) ) ;
if ( WalletSize . open ( QIODevice : : ReadOnly ) ) {
size = WalletSize . size ( ) / 1000000 ; //when file does open.
//QString size1 = QString::number(size) ;
settings . WalletSize - > setText ( QString : : number ( size ) ) ;
WalletSize . close ( ) ;
}
if ( rpc - > getConnection ( ) ! = nullptr ) {
isUsingConsolidation = ! rpc - > getConnection ( ) - > config - > consolidation . isEmpty ( ) = = true ;
}
@ -362,8 +494,7 @@ void MainWindow::setupSettingsModal() {
settings . chkConso - > setEnabled ( false ) ;
}
//Use Deletetx
// Use Deletetx
bool isUsingDeletetx = false ;
if ( rpc - > getConnection ( ) ! = nullptr ) {
isUsingDeletetx = ! rpc - > getConnection ( ) - > config - > deletetx . isEmpty ( ) = = true ;
@ -373,8 +504,7 @@ void MainWindow::setupSettingsModal() {
settings . chkDeletetx - > setEnabled ( false ) ;
}
//Use Zindex
// Use Zindex
bool isUsingZindex = false ;
if ( rpc - > getConnection ( ) ! = nullptr ) {
isUsingZindex = ! rpc - > getConnection ( ) - > config - > zindex . isEmpty ( ) = = true ;
@ -392,10 +522,10 @@ void MainWindow::setupSettingsModal() {
auto hushConfLocation = Settings : : getInstance ( ) - > getHushdConfLocation ( ) ;
if ( ! hushConfLocation . isEmpty ( ) ) {
settings . confMsg - > setText ( " Settings are being read from \n " + hushConfLocation ) ;
settings . hostname - > setEnabled ( fals e ) ;
settings . port - > setEnabled ( fals e ) ;
settings . rpcuser - > setEnabled ( fals e ) ;
settings . rpcpassword - > setEnabled ( fals e ) ;
settings . hostname - > setReadOnly ( tru e ) ;
settings . port - > setReadOnly ( tru e ) ;
settings . rpcuser - > setReadOnly ( tru e ) ;
settings . rpcpassword - > setReadOnly ( tru e ) ;
} else {
settings . confMsg - > setText ( " No local HUSH3.conf found. Please configure connection manually. " ) ;
settings . hostname - > setEnabled ( true ) ;
@ -418,13 +548,94 @@ void MainWindow::setupSettingsModal() {
settings . testnetTxExplorerUrl - > setText ( explorer . testnetTxExplorerUrl ) ;
settings . testnetAddressExplorerUrl - > setText ( explorer . testnetAddressExplorerUrl ) ;
// Connection tab by default
settings . tabWidget - > setCurrentIndex ( 0 ) ;
// format systems language
QString defaultLocale = QLocale : : system ( ) . name ( ) ; // e.g. "de_DE"
defaultLocale . truncate ( defaultLocale . lastIndexOf ( ' _ ' ) ) ; // e.g. "de"
// Set the current language to the default system language
// TODO: this will need to change when we read/write selected language to config on disk
//m_currLang = defaultLocale;
//qDebug() << __func__ << ": changed m_currLang to " << defaultLocale;
m_currLang = Settings : : getInstance ( ) - > get_language ( ) ;
qDebug ( ) < < __func__ < < " : got a currLang= " < < m_currLang < < " from config file " ;
//QString defaultLang = QLocale::languageToString(QLocale("en").language());
settings . comboBoxLanguage - > addItem ( " English (en) " ) ;
m_langPath = QApplication : : applicationDirPath ( ) ;
m_langPath . append ( " /res " ) ;
qDebug ( ) < < __func__ < < " : defaultLocale= " < < defaultLocale < < " m_langPath= " < < m_langPath ; ;
QDir dir ( m_langPath ) ;
QStringList fileNames = dir . entryList ( QStringList ( " silentdragon_*.qm " ) ) ;
qDebug ( ) < < __func__ < < " : found " < < fileNames . size ( ) < < " translations " ;
// create language drop down dynamically
for ( int i = 0 ; i < fileNames . size ( ) ; + + i ) {
// get locale extracted by filename
QString locale ;
locale = fileNames [ i ] ; // "silentdragon_de.qm"
locale . truncate ( locale . lastIndexOf ( ' . ' ) ) ; // "silentdragon_de"
locale . remove ( 0 , locale . lastIndexOf ( ' _ ' ) + 1 ) ; // "de"
QString lang = QLocale ( locale ) . nativeLanguageName ( ) ; //locale.language());
// TODO: this likely wont work for RTL languages like Arabic
// uppercase the first letter of all languages
auto first = QString ( lang . at ( 0 ) ) . toUpper ( ) ;
lang = first + lang . right ( lang . size ( ) - 1 ) ;
//settings.comboBoxLanguage->addItem(action);
settings . comboBoxLanguage - > addItem ( lang + " ( " + locale + " ) " ) ;
qDebug ( ) < < __func__ < < " : added lang= " < < lang < < " locale= " < < locale < < " defaultLocale= " < < defaultLocale < < " m_currLang= " < < m_currLang ;
qDebug ( ) < < __func__ < < " : m_currLang= " < < m_currLang < < " ?= locale= " < < locale ;
//if (defaultLocale == locale) {
if ( m_currLang = = locale ) {
settings . comboBoxLanguage - > setCurrentIndex ( i + 1 ) ;
qDebug ( ) < < " set defaultLocale= " < < locale < < " to checked!!! " ;
}
}
settings . comboBoxLanguage - > model ( ) - > sort ( 0 , Qt : : AscendingOrder ) ;
qDebug ( ) < < __func__ < < " : sorted translations " ;
//QString lang = QLocale::languageToString(QLocale(m_currLang).language());
QString lang = QLocale ( m_currLang ) . nativeLanguageName ( ) ; //locale.language());
auto first = QString ( lang . at ( 0 ) ) . toUpper ( ) ;
lang = first + lang . right ( lang . size ( ) - 1 ) ;
if ( m_currLang = = " en " ) {
// we have just 1 English translation
// en_US will render as "American English", so fix that
lang . replace ( " American " , " " ) ;
}
qDebug ( ) < < __func__ < < " : looking for " < < lang + " ( " + m_currLang + " ) " ;
//qDebug() << __func__ << ": looking for " << m_currLang;
int lang_index = settings . comboBoxLanguage - > findText ( lang + " ( " + m_currLang + " ) " , Qt : : MatchExactly ) ;
qDebug ( ) < < __func__ < < " : setting comboBoxLanguage index to " < < lang_index ;
settings . comboBoxLanguage - > setCurrentIndex ( lang_index ) ;
QObject : : connect ( settings . comboBoxLanguage , & QComboBox : : currentTextChanged , [ = ] ( QString lang ) {
qDebug ( ) < < " comboBoxLanguage.currentTextChanged lang= " < < lang ;
this - > slotLanguageChanged ( lang ) ;
//QMessageBox::information(this, tr("Language Changed"), tr("This change can take a few seconds."), QMessageBox::Ok);
} ) ;
// Options tab by default
settings . tabWidget - > setCurrentIndex ( 1 ) ;
// Enable the troubleshooting options only if using embedded hushd
if ( ! rpc - > isEmbedded ( ) ) {
settings . chkRescan - > setEnabled ( false ) ;
settings . chkRescan - > setToolTip ( tr ( " You're using an external hushd. Please restart hushd with -rescan " ) ) ;
//settings.chkRescan->setEnabled(false);
//settings.chkRescan->setToolTip(tr(" You're using an external hushd. Please restart hushd with -rescan"));
settings . chkReindex - > setEnabled ( false ) ;
settings . chkReindex - > setToolTip ( tr ( " You're using an external hushd. Please restart hushd with -reindex " ) ) ;
@ -490,10 +701,12 @@ void MainWindow::setupSettingsModal() {
// Check to see if rescan or reindex have been enabled
bool showRestartInfo = false ;
bool showReindexInfo = false ;
/*
if ( settings . chkRescan - > isChecked ( ) ) {
Settings : : addToHushConf ( hushConfLocation , " rescan=1 " ) ;
showRestartInfo = true ;
}
} */
if ( settings . chkReindex - > isChecked ( ) ) {
Settings : : addToHushConf ( hushConfLocation , " reindex=1 " ) ;
@ -580,7 +793,7 @@ void MainWindow::telegram() {
}
void MainWindow : : reportbug ( ) {
QString url = " https://git.hush.is/hush/SilentDragon/issues/new " ;
QString url = " https://hush.is/tg_support " ;
QDesktopServices : : openUrl ( QUrl ( url ) ) ;
}
@ -928,6 +1141,20 @@ void MainWindow::getViewKey(QString addr) {
* isDialogAlive = false ;
}
void MainWindow : : getQRCode ( QString addr ) {
QDialog d ( this ) ;
Ui_QRCode qrui ;
qrui . setupUi ( & d ) ;
// Display QR Code for address
qrui . qrcodeDisplayAddr - > setQrcodeString ( addr ) ;
auto isDialogAlive = std : : make_shared < bool > ( true ) ;
d . exec ( ) ;
* isDialogAlive = false ;
}
void MainWindow : : exportKeys ( QString addr ) {
bool allKeys = addr . isEmpty ( ) ? true : false ;
@ -1132,6 +1359,11 @@ void MainWindow::setupBalancesTab() {
menu . addAction ( tr ( " Get viewing key " ) , [ = ] ( ) {
this - > getViewKey ( addr ) ;
} ) ;
// QR Code for zaddrs only
menu . addAction ( tr ( " Get QR code " ) , [ = ] ( ) {
this - > getQRCode ( addr ) ;
} ) ;
}
menu . addAction ( " Send from " % addr . left ( 40 ) % ( addr . size ( ) > 40 ? " ... " : " " ) , [ = ] ( ) {
@ -1206,21 +1438,23 @@ QString peer2ip(QString peer) {
void MainWindow : : setupPeersTab ( ) {
qDebug ( ) < < __FUNCTION__ ;
// Set up context menu on transaction s tab
// Set up context menu on peer s tab
ui - > peersTable - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
ui - > bannedPeersTable - > setContextMenuPolicy ( Qt : : CustomContextMenu ) ;
// Table right click
QObject : : connect ( ui - > bannedPeersTable , & QTableView : : customContextMenuRequested , [ = ] ( QPoint pos ) {
QModelIndex index = ui - > p eersTable- > indexAt ( pos ) ;
QModelIndex index = ui - > bannedP eersTable- > indexAt ( pos ) ;
if ( index . row ( ) < 0 ) return ;
QMenu menu ( this ) ;
auto bannedPeerModel = dynamic_cast < BannedPeersTableModel * > ( ui - > bannedPeersTable - > model ( ) ) ;
QString addr = bannedPeerModel - > getAddress ( index . row ( ) ) ;
qint64 asn = bannedPeerModel - > getASN ( index . row ( ) ) ;
QString ip = peer2ip ( addr ) ;
QString subnet = bannedPeerModel - > getSubnet ( index . row ( ) ) ;
QString as = QString : : number ( asn ) ;
//qint64 banned_until = bannedPeerModel->getBannedUntil(index.row());
if ( ! ip . isEmpty ( ) ) {
@ -1240,6 +1474,46 @@ void MainWindow::setupPeersTab() {
} ) ;
}
if ( ! as . isEmpty ( ) ) {
menu . addAction ( tr ( " View ASN on bgpview.io (3rd party service) " ) , [ = ] ( ) {
QString url = " https://bgpview.io/asn/ " + as ;
qDebug ( ) < < " opening " < < url ;
QDesktopServices : : openUrl ( QUrl ( url ) ) ;
} ) ;
}
if ( ! ip . isEmpty ( ) ) {
menu . addAction ( tr ( " Unban this peer " ) , [ = ] ( ) {
ui - > statusBar - > showMessage ( tr ( " Unbanning peer... " ) ) ;
// Hide single banned peer
ui - > bannedPeersTable - > hideRow ( index . row ( ) ) ;
// Call setban
rpc - > setban ( ip , " remove " , [ = ] ( QJsonValue response ) {
qDebug ( ) < < " setban remove " < < response ;
ui - > statusBar - > showMessage ( tr ( " Peer unbanned " ) , 3 * 1000 ) ;
rpc - > refreshPeers ( ) ;
} ) ;
} ) ;
menu . addAction ( tr ( " Unban all peers " ) , [ = ] ( ) {
ui - > statusBar - > showMessage ( tr ( " Unbanning all peers... " ) ) ;
// Hide all banned peers
for ( int i = 0 ; i < bannedPeerModel - > rowCount ( index ) ; i + + ) {
ui - > bannedPeersTable - > hideRow ( i ) ;
}
// Call clearBanned
rpc - > clearBanned ( [ = ] ( QJsonValue response ) {
qDebug ( ) < < " clearBanned " < < response ;
ui - > statusBar - > showMessage ( tr ( " All peers unbanned " ) , 3 * 1000 ) ;
rpc - > refreshPeers ( ) ;
} ) ;
} ) ;
}
menu . exec ( ui - > bannedPeersTable - > viewport ( ) - > mapToGlobal ( pos ) ) ;
} ) ;
@ -1295,6 +1569,20 @@ void MainWindow::setupPeersTab() {
} ) ;
}
menu . addAction ( tr ( " Ban this peer " ) , [ = ] ( ) {
ui - > statusBar - > showMessage ( tr ( " Banning peer... " ) ) ;
// Hide single peer
ui - > peersTable - > hideRow ( index . row ( ) ) ;
// Call setban
rpc - > setban ( ip , " add " , [ = ] ( QJsonValue response ) {
qDebug ( ) < < " setban add " < < response ;
ui - > statusBar - > showMessage ( tr ( " Peer banned " ) , 3 * 1000 ) ;
rpc - > refreshPeers ( ) ;
} ) ;
} ) ;
menu . exec ( ui - > peersTable - > viewport ( ) - > mapToGlobal ( pos ) ) ;
} ) ;
@ -1383,10 +1671,52 @@ void MainWindow::setupTransactionsTab() {
QString memo = txModel - > getMemo ( index . row ( ) ) ;
if ( ! memo . isEmpty ( ) ) {
QMessageBox mb ( QMessageBox : : Information , tr ( " Memo " ) , memo , QMessageBox : : Ok , this ) ;
QMessageBox mb ;
mb . setText ( memo ) ;
mb . setWindowTitle ( tr ( " Memo " ) ) ;
mb . setIcon ( QMessageBox : : Information ) ;
QAbstractButton * buttonMemoReply = mb . addButton ( tr ( " Reply " ) , QMessageBox : : YesRole ) ; mb . addButton ( tr ( " OK " ) , QMessageBox : : NoRole ) ;
mb . setTextFormat ( Qt : : PlainText ) ;
mb . setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
mb . exec ( ) ;
if ( mb . clickedButton ( ) = = buttonMemoReply ) {
qDebug ( ) < < " Reply clicked " ;
int lastPost = memo . trimmed ( ) . lastIndexOf ( QRegExp ( " [ \r \n ]+ " ) ) ;
QString lastWord = memo . right ( memo . length ( ) - lastPost - 1 ) ;
if ( Settings : : getInstance ( ) - > isSaplingAddress ( lastWord ) ) {
// First, cancel any pending stuff in the send tab by pretending to click
// the cancel button
cancelButton ( ) ;
// Then set up the fields in the send tab
ui - > Address1 - > setText ( lastWord ) ;
ui - > Address1 - > setCursorPosition ( 0 ) ;
ui - > Amount1 - > setText ( " 0.0001 " ) ;
// And switch to the send tab.
ui - > tabWidget - > setCurrentIndex ( 1 ) ;
qApp - > processEvents ( ) ;
// Click the memo button
this - > memoButtonClicked ( 1 , true ) ;
} else {
// TODO: This memo has no reply to address. Show alert or don't show button to begin with.
QMessageBox mb ;
mb . setText ( tr ( " Sorry! This memo has no reply to address. " ) ) ;
mb . setWindowTitle ( tr ( " Error " ) ) ;
mb . setTextFormat ( Qt : : PlainText ) ;
mb . setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
mb . exec ( ) ;
}
}
}
} ) ;
@ -1440,6 +1770,14 @@ void MainWindow::setupTransactionsTab() {
QGuiApplication : : clipboard ( ) - > setText ( url ) ;
} ) ;
/* TODO: Decide whether to use this or not.
menu . addAction ( tr ( " Look for new transactions " ) , [ = ] ( ) {
QGuiApplication : : clipboard ( ) - > setText ( addr ) ;
ui - > statusBar - > showMessage ( tr ( " Looking for new transactions " ) , 3 * 1000 ) ;
rpc - > watchTxStatus ( ) ;
} ) ;
*/
// Payment Request
if ( ! memo . isEmpty ( ) & & memo . startsWith ( " hush: " ) ) {
menu . addAction ( tr ( " View Payment Request " ) , [ = ] ( ) {
@ -1450,10 +1788,57 @@ void MainWindow::setupTransactionsTab() {
// View Memo
if ( ! memo . isEmpty ( ) ) {
menu . addAction ( tr ( " View Memo " ) , [ = ] ( ) {
/*
QMessageBox mb ( QMessageBox : : Information , tr ( " Memo " ) , memo , QMessageBox : : Ok , this ) ;
mb . setTextFormat ( Qt : : PlainText ) ;
mb . setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
mb . exec ( ) ; */
QMessageBox mb ;
mb . setText ( memo ) ;
mb . setWindowTitle ( tr ( " Memo " ) ) ;
mb . setIcon ( QMessageBox : : Information ) ;
QAbstractButton * buttonMemoReply = mb . addButton ( tr ( " Reply " ) , QMessageBox : : YesRole ) ; mb . addButton ( tr ( " OK " ) , QMessageBox : : NoRole ) ;
mb . setTextFormat ( Qt : : PlainText ) ;
mb . setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
mb . exec ( ) ;
if ( mb . clickedButton ( ) = = buttonMemoReply ) {
qDebug ( ) < < " Reply clicked " ;
int lastPost = memo . trimmed ( ) . lastIndexOf ( QRegExp ( " [ \r \n ]+ " ) ) ;
QString lastWord = memo . right ( memo . length ( ) - lastPost - 1 ) ;
if ( Settings : : getInstance ( ) - > isSaplingAddress ( lastWord ) ) {
// First, cancel any pending stuff in the send tab by pretending to click
// the cancel button
cancelButton ( ) ;
// Then set up the fields in the send tab
ui - > Address1 - > setText ( lastWord ) ;
ui - > Address1 - > setCursorPosition ( 0 ) ;
ui - > Amount1 - > setText ( " 0.0001 " ) ;
// And switch to the send tab.
ui - > tabWidget - > setCurrentIndex ( 1 ) ;
qApp - > processEvents ( ) ;
// Click the memo button
this - > memoButtonClicked ( 1 , true ) ;
} else {
// TODO: This memo has no reply to address. Show alert or don't show button to begin with.
QMessageBox mb ;
mb . setText ( tr ( " Sorry! This memo has no reply to address. " ) ) ;
mb . setWindowTitle ( tr ( " Error " ) ) ;
mb . setTextFormat ( Qt : : PlainText ) ;
mb . setTextInteractionFlags ( Qt : : TextSelectableByMouse | Qt : : TextSelectableByKeyboard ) ;
mb . exec ( ) ;
}
}
} ) ;
}
@ -1658,6 +2043,7 @@ void MainWindow::setupReceiveTab() {
ui - > rcvBal - > setText ( Settings : : getHUSHUSDDisplayFormat ( rpc - > getAllBalances ( ) - > value ( addr ) ) ) ;
ui - > txtReceive - > setPlainText ( addr ) ;
ui - > qrcodeDisplay - > setQrcodeString ( addr ) ;
if ( rpc - > getUsedAddresses ( ) - > value ( addr , false ) ) {
ui - > rcvBal - > setToolTip ( tr ( " Address has been previously used " ) ) ;
} else {
@ -1747,7 +2133,7 @@ void MainWindow::updateLabels() {
void MainWindow : : slot_change_currency ( const QString & currency_name )
{
qDebug ( ) < < " slot_change_currency " ; //<< ": " << currency_name;
qDebug ( ) < < __func__ < < " : " < < currency_name ;
Settings : : getInstance ( ) - > set_currency_name ( currency_name ) ;
qDebug ( ) < < " Refreshing price stats after currency change " ;
rpc - > refreshPrice ( ) ;
@ -1762,9 +2148,17 @@ void MainWindow::slot_change_currency(const QString& currency_name)
}
}
void MainWindow : : slot_change_theme ( const QString & theme_name )
void MainWindow : : slot_change_theme ( QString & theme_name )
{
Settings : : getInstance ( ) - > set_theme_name ( theme_name ) ;
qDebug ( ) < < __func__ < < " : theme_name= " < < theme_name ;
if ( theme_name = = " dark " | | theme_name = = " default " | | theme_name = = " light " | |
theme_name = = " midnight " | | theme_name = = " blue " ) {
Settings : : getInstance ( ) - > set_theme_name ( theme_name ) ;
} else {
qDebug ( ) < < __func__ < < " : ignoring invalid theme_name= " < < theme_name ;
Settings : : getInstance ( ) - > set_theme_name ( " dark " ) ;
}
// Include css
QString saved_theme_name ;
@ -1772,10 +2166,12 @@ void MainWindow::slot_change_theme(const QString& theme_name)
saved_theme_name = Settings : : getInstance ( ) - > get_theme_name ( ) ;
} catch ( const std : : exception & e ) {
qDebug ( ) < < QString ( " Ignoring theme change Exception! : " ) ;
saved_theme_name = " default " ;
saved_theme_name = " dark " ;
}
QFile qFile ( " :/css/res/css/ " + saved_theme_name + " .css " ) ;
QString filename = " :/css/res/css/ " + saved_theme_name + " .css " ;
QFile qFile ( filename ) ;
qDebug ( ) < < __func__ < < " : attempting to open filename= " < < filename ;
if ( qFile . open ( QFile : : ReadOnly ) )
{
QString styleSheet = QLatin1String ( qFile . readAll ( ) ) ;
@ -1785,6 +2181,46 @@ void MainWindow::slot_change_theme(const QString& theme_name)
}
void MainWindow : : rescanButtonClicked ( int number ) {
qDebug ( ) < < " rescanButtonClicked " < < number ;
// Setup rescan dialog
Ui_RescanDialog rescanDialog ;
QDialog dialog ( this ) ;
rescanDialog . setupUi ( & dialog ) ;
// TODO: Maybe set to current blockheight by default
rescanDialog . rescanBlockheight - > setFocus ( ) ;
// Add validator for block height
QRegExpValidator * heightValidator = new QRegExpValidator ( QRegExp ( " \\ d* " ) , this ) ;
rescanDialog . rescanBlockheight - > setValidator ( heightValidator ) ;
// Check if OK clicked
if ( dialog . exec ( ) = = QDialog : : Accepted ) {
// Show message in status bar
ui - > statusBar - > showMessage ( tr ( " Rescanning... " ) ) ;
// Close settings
QWidget * modalWidget = QApplication : : activeModalWidget ( ) ;
if ( modalWidget )
modalWidget - > close ( ) ;
// Get submitted rescan height
int rescanHeight = rescanDialog . rescanBlockheight - > text ( ) . toInt ( ) ;
qDebug ( ) < < " rescan height = " < < rescanHeight ;
// Call rescan RPC
rpc - > rescan ( rescanHeight , [ = ] ( QJsonValue response ) {
qDebug ( ) < < " rescanning finished " < < response ;
ui - > statusBar - > showMessage ( tr ( " Rescanning finished " ) ) ;
} ) ;
}
}
MainWindow : : ~ MainWindow ( )
{
delete ui ;