mirror of
https://github.com/dashpay/dash.git
synced 2024-12-29 05:49:11 +01:00
91d99fcd3f
* Merge #8996: Network activity toggle19f46f1
Qt: New network_disabled icon (Luke Dashjr)54cf997
RPC/Net: Use boolean consistently for networkactive, and remove from getinfo (Luke Dashjr)b2b33d9
Overhaul network activity toggle (Jonas Schnelli)32efa79
Qt: Add GUI feedback and control of network activity state. (Jon Lund Steffensen)e38993b
RPC: Add "togglenetwork" method to toggle network activity temporarily (Jon Lund Steffensen)7c9a98a
Allow network activity to be temporarily suspended. (Jon Lund Steffensen) * Revert on-click behavior of network status icon to showing peers list Stay with the way Dash handled clicking on the status icon * Add theme support for network disabled icon * Merge #8874: Multiple Selection for peer and ban tables1077577
Fix auto-deselection of peers (Andrew Chow)addfdeb
Multiple Selection for peer and ban tables (Andrew Chow) * Merge #9190: qt: Plug many memory leaksed998ea
qt: Avoid OpenSSL certstore-related memory leak (Wladimir J. van der Laan)5204598
qt: Avoid shutdownwindow-related memory leak (Wladimir J. van der Laan)e4f126a
qt: Avoid splash-screen related memory leak (Wladimir J. van der Laan)693384e
qt: Prevent thread/memory leak on exiting RPCConsole (Wladimir J. van der Laan)47db075
qt: Plug many memory leaks (Wladimir J. van der Laan) * Merge #9218: qt: Show progress overlay when clicking spinner icon042f9fa
qt: Show progress overlay when clicking spinner icon (Wladimir J. van der Laan)827d9a3
qt: Replace NetworkToggleStatusBarControl with generic ClickableLabel (Wladimir J. van der Laan) * Merge #9266: Bugfix: Qt/RPCConsole: Put column enum in the right placesdf17fe0
Bugfix: Qt/RPCConsole: Put column enum in the right places (Luke Dashjr) * Merge #9255: qt: layoutAboutToChange signal is called layoutAboutToBeChangedf36349e
qt: Remove on_toggleNetworkActiveButton_clicked from RPCConsole (Wladimir J. van der Laan)297cc20
qt: layoutAboutToChange signal is called layoutAboutToBeChanged (Wladimir J. van der Laan) * Use UniValue until bitcoin PR #8788 is backported Network active toggle was already based on "[RPC] Give RPC commands more information about the RPC request" We need to use the old UniValue style until that one is backported * Merge #8906: [qt] sync-overlay: Don't show progress twicefafeec3
[qt] sync-overlay: Don't show progress twice (MarcoFalke) * Merge #8985: Use pindexBestHeader instead of setBlockIndexCandidates for NotifyHeaderTip()3154d6e
[Qt] use NotifyHeaderTip's height and date for the progress update (Jonas Schnelli)0a261b6
Use pindexBestHeader instead of setBlockIndexCandidates for NotifyHeaderTip() (Jonas Schnelli) * Merge #9280: [Qt] Show ModalOverlay by pressing the progress bar, allow hiding89a3723
[Qt] Show ModalOverlay by pressing the progress bar, disabled show() in sync mode (Jonas Schnelli) * Merge #9461: [Qt] Improve progress display during headers-sync and peer-finding40ec7c7
[Qt] Improve progress display during headers-sync and peer-finding (Jonas Schnelli) * Merge #9588: qt: Use nPowTargetSpacing constantfa4d478
qt: Use nPowTargetSpacing constant (MarcoFalke) * Hide modal overlay forever when syncing has catched up Don't allow to open it again by clicking on the progress bar and spinner icon. Currently the overlay does not show meaningful information about masternode sync and it gives the impression of being stuck after the block chain sync is done. * Don't include chainparams.h in sendcoinsdialog.cpp This was just a remainder of a backported PR which meant to change some calculation in this file which does not apply to Dash. * Also check for fNetworkActive in ConnectNode * Merge #9528: [qt] Rename formateNiceTimeOffset(qint64) to formatNiceTimeOffset(qint64)988d300
[qt] Rename formateNiceTimeOffset(qint64) to formatNiceTimeOffset(qint64) (practicalswift) * Merge #11237: qt: Fixing division by zero in time remainingc8d38abd6
Refactor tipUpdate as per style guide (MeshCollider)3b69a08c5
Fix division by zero in time remaining (MeshCollider) Pull request description: Fixes https://github.com/bitcoin/bitcoin/issues/10291, https://github.com/bitcoin/bitcoin/issues/11265 progressDelta may be 0 (or even negative according to 11265), this checks for that and prints unknown if it is, because we cannot calculate an estimate for the time remaining (would be infinite or negative). Tree-SHA512: bc5708e5ed6e4670d008219558c5fbb25709bd99a32c98ec39bb74f94a0b7fa058f3d03389ccdd39e6723e6b5b48e34b13ceee7c051c2db631e51d8ec3e1d68c
733 lines
24 KiB
C++
733 lines
24 KiB
C++
// Copyright (c) 2011-2015 The Bitcoin Core developers
|
|
// Copyright (c) 2014-2017 The Dash Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include "config/dash-config.h"
|
|
#endif
|
|
|
|
#include "bitcoingui.h"
|
|
|
|
#include "chainparams.h"
|
|
#include "clientmodel.h"
|
|
#include "guiconstants.h"
|
|
#include "guiutil.h"
|
|
#include "intro.h"
|
|
#include "net.h"
|
|
#include "networkstyle.h"
|
|
#include "optionsmodel.h"
|
|
#include "platformstyle.h"
|
|
#include "splashscreen.h"
|
|
#include "utilitydialog.h"
|
|
#include "winshutdownmonitor.h"
|
|
|
|
#ifdef ENABLE_WALLET
|
|
#include "paymentserver.h"
|
|
#include "walletmodel.h"
|
|
#endif
|
|
#include "masternodeconfig.h"
|
|
|
|
#include "init.h"
|
|
#include "rpc/server.h"
|
|
#include "scheduler.h"
|
|
#include "ui_interface.h"
|
|
#include "util.h"
|
|
|
|
#ifdef ENABLE_WALLET
|
|
#include "wallet/wallet.h"
|
|
#endif
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <boost/filesystem/operations.hpp>
|
|
#include <boost/thread.hpp>
|
|
|
|
#include <QApplication>
|
|
#include <QDebug>
|
|
#include <QLibraryInfo>
|
|
#include <QLocale>
|
|
#include <QMessageBox>
|
|
#include <QProcess>
|
|
#include <QSettings>
|
|
#include <QThread>
|
|
#include <QTimer>
|
|
#include <QTranslator>
|
|
#include <QSslConfiguration>
|
|
|
|
#if defined(QT_STATICPLUGIN)
|
|
#include <QtPlugin>
|
|
#if QT_VERSION < 0x050000
|
|
Q_IMPORT_PLUGIN(qcncodecs)
|
|
Q_IMPORT_PLUGIN(qjpcodecs)
|
|
Q_IMPORT_PLUGIN(qtwcodecs)
|
|
Q_IMPORT_PLUGIN(qkrcodecs)
|
|
Q_IMPORT_PLUGIN(qtaccessiblewidgets)
|
|
#else
|
|
#if QT_VERSION < 0x050400
|
|
Q_IMPORT_PLUGIN(AccessibleFactory)
|
|
#endif
|
|
#if defined(QT_QPA_PLATFORM_XCB)
|
|
Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
|
|
#elif defined(QT_QPA_PLATFORM_WINDOWS)
|
|
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
|
|
#elif defined(QT_QPA_PLATFORM_COCOA)
|
|
Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#if QT_VERSION < 0x050000
|
|
#include <QTextCodec>
|
|
#endif
|
|
|
|
// Declare meta types used for QMetaObject::invokeMethod
|
|
Q_DECLARE_METATYPE(bool*)
|
|
Q_DECLARE_METATYPE(CAmount)
|
|
|
|
static void InitMessage(const std::string &message)
|
|
{
|
|
LogPrintf("init message: %s\n", message);
|
|
}
|
|
|
|
/*
|
|
Translate string to current locale using Qt.
|
|
*/
|
|
static std::string Translate(const char* psz)
|
|
{
|
|
return QCoreApplication::translate("dash-core", psz).toStdString();
|
|
}
|
|
|
|
static QString GetLangTerritory()
|
|
{
|
|
QSettings settings;
|
|
// Get desired locale (e.g. "de_DE")
|
|
// 1) System default language
|
|
QString lang_territory = QLocale::system().name();
|
|
// 2) Language from QSettings
|
|
QString lang_territory_qsettings = settings.value("language", "").toString();
|
|
if(!lang_territory_qsettings.isEmpty())
|
|
lang_territory = lang_territory_qsettings;
|
|
// 3) -lang command line argument
|
|
lang_territory = QString::fromStdString(GetArg("-lang", lang_territory.toStdString()));
|
|
return lang_territory;
|
|
}
|
|
|
|
/** Set up translations */
|
|
static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
|
|
{
|
|
// Remove old translators
|
|
QApplication::removeTranslator(&qtTranslatorBase);
|
|
QApplication::removeTranslator(&qtTranslator);
|
|
QApplication::removeTranslator(&translatorBase);
|
|
QApplication::removeTranslator(&translator);
|
|
|
|
// Get desired locale (e.g. "de_DE")
|
|
// 1) System default language
|
|
QString lang_territory = GetLangTerritory();
|
|
|
|
// Convert to "de" only by truncating "_DE"
|
|
QString lang = lang_territory;
|
|
lang.truncate(lang_territory.lastIndexOf('_'));
|
|
|
|
// Load language files for configured locale:
|
|
// - First load the translator for the base language, without territory
|
|
// - Then load the more specific locale translator
|
|
|
|
// Load e.g. qt_de.qm
|
|
if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
|
QApplication::installTranslator(&qtTranslatorBase);
|
|
|
|
// Load e.g. qt_de_DE.qm
|
|
if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
|
QApplication::installTranslator(&qtTranslator);
|
|
|
|
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in dash.qrc)
|
|
if (translatorBase.load(lang, ":/translations/"))
|
|
QApplication::installTranslator(&translatorBase);
|
|
|
|
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in dash.qrc)
|
|
if (translator.load(lang_territory, ":/translations/"))
|
|
QApplication::installTranslator(&translator);
|
|
}
|
|
|
|
/* qDebug() message handler --> debug.log */
|
|
#if QT_VERSION < 0x050000
|
|
void DebugMessageHandler(QtMsgType type, const char *msg)
|
|
{
|
|
const char *category = (type == QtDebugMsg) ? "qt" : NULL;
|
|
LogPrint(category, "GUI: %s\n", msg);
|
|
}
|
|
#else
|
|
void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
|
|
{
|
|
Q_UNUSED(context);
|
|
const char *category = (type == QtDebugMsg) ? "qt" : NULL;
|
|
LogPrint(category, "GUI: %s\n", msg.toStdString());
|
|
}
|
|
#endif
|
|
|
|
/** Class encapsulating Dash Core startup and shutdown.
|
|
* Allows running startup and shutdown in a different thread from the UI thread.
|
|
*/
|
|
class BitcoinCore: public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit BitcoinCore();
|
|
|
|
public Q_SLOTS:
|
|
void initialize();
|
|
void shutdown();
|
|
void restart(QStringList args);
|
|
|
|
Q_SIGNALS:
|
|
void initializeResult(int retval);
|
|
void shutdownResult(int retval);
|
|
void runawayException(const QString &message);
|
|
|
|
private:
|
|
boost::thread_group threadGroup;
|
|
CScheduler scheduler;
|
|
|
|
/// Flag indicating a restart
|
|
bool execute_restart;
|
|
|
|
/// Pass fatal exception message to UI thread
|
|
void handleRunawayException(const std::exception *e);
|
|
};
|
|
|
|
/** Main Dash application object */
|
|
class BitcoinApplication: public QApplication
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
explicit BitcoinApplication(int &argc, char **argv);
|
|
~BitcoinApplication();
|
|
|
|
#ifdef ENABLE_WALLET
|
|
/// Create payment server
|
|
void createPaymentServer();
|
|
#endif
|
|
/// parameter interaction/setup based on rules
|
|
void parameterSetup();
|
|
/// Create options model
|
|
void createOptionsModel(bool resetSettings);
|
|
/// Create main window
|
|
void createWindow(const NetworkStyle *networkStyle);
|
|
/// Create splash screen
|
|
void createSplashScreen(const NetworkStyle *networkStyle);
|
|
|
|
/// Request core initialization
|
|
void requestInitialize();
|
|
/// Request core shutdown
|
|
void requestShutdown();
|
|
|
|
/// Get process return value
|
|
int getReturnValue() { return returnValue; }
|
|
|
|
/// Get window identifier of QMainWindow (BitcoinGUI)
|
|
WId getMainWinId() const;
|
|
|
|
public Q_SLOTS:
|
|
void initializeResult(int retval);
|
|
void shutdownResult(int retval);
|
|
/// Handle runaway exceptions. Shows a message box with the problem and quits the program.
|
|
void handleRunawayException(const QString &message);
|
|
|
|
Q_SIGNALS:
|
|
void requestedInitialize();
|
|
void requestedRestart(QStringList args);
|
|
void requestedShutdown();
|
|
void stopThread();
|
|
void splashFinished(QWidget *window);
|
|
|
|
private:
|
|
QThread *coreThread;
|
|
OptionsModel *optionsModel;
|
|
ClientModel *clientModel;
|
|
BitcoinGUI *window;
|
|
QTimer *pollShutdownTimer;
|
|
#ifdef ENABLE_WALLET
|
|
PaymentServer* paymentServer;
|
|
WalletModel *walletModel;
|
|
#endif
|
|
int returnValue;
|
|
const PlatformStyle *platformStyle;
|
|
std::unique_ptr<QWidget> shutdownWindow;
|
|
|
|
void startThread();
|
|
};
|
|
|
|
#include "dash.moc"
|
|
|
|
BitcoinCore::BitcoinCore():
|
|
QObject()
|
|
{
|
|
}
|
|
|
|
void BitcoinCore::handleRunawayException(const std::exception *e)
|
|
{
|
|
PrintExceptionContinue(e, "Runaway exception");
|
|
Q_EMIT runawayException(QString::fromStdString(strMiscWarning));
|
|
}
|
|
|
|
void BitcoinCore::initialize()
|
|
{
|
|
execute_restart = true;
|
|
|
|
try
|
|
{
|
|
qDebug() << __func__ << ": Running AppInit2 in thread";
|
|
int rv = AppInit2(threadGroup, scheduler);
|
|
Q_EMIT initializeResult(rv);
|
|
} catch (const std::exception& e) {
|
|
handleRunawayException(&e);
|
|
} catch (...) {
|
|
handleRunawayException(NULL);
|
|
}
|
|
}
|
|
|
|
void BitcoinCore::restart(QStringList args)
|
|
{
|
|
if(execute_restart) { // Only restart 1x, no matter how often a user clicks on a restart-button
|
|
execute_restart = false;
|
|
try
|
|
{
|
|
qDebug() << __func__ << ": Running Restart in thread";
|
|
threadGroup.interrupt_all();
|
|
threadGroup.join_all();
|
|
PrepareShutdown();
|
|
qDebug() << __func__ << ": Shutdown finished";
|
|
Q_EMIT shutdownResult(1);
|
|
CExplicitNetCleanup::callCleanup();
|
|
QProcess::startDetached(QApplication::applicationFilePath(), args);
|
|
qDebug() << __func__ << ": Restart initiated...";
|
|
QApplication::quit();
|
|
} catch (std::exception& e) {
|
|
handleRunawayException(&e);
|
|
} catch (...) {
|
|
handleRunawayException(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BitcoinCore::shutdown()
|
|
{
|
|
try
|
|
{
|
|
qDebug() << __func__ << ": Running Shutdown in thread";
|
|
Interrupt(threadGroup);
|
|
threadGroup.join_all();
|
|
Shutdown();
|
|
qDebug() << __func__ << ": Shutdown finished";
|
|
Q_EMIT shutdownResult(1);
|
|
} catch (const std::exception& e) {
|
|
handleRunawayException(&e);
|
|
} catch (...) {
|
|
handleRunawayException(NULL);
|
|
}
|
|
}
|
|
|
|
BitcoinApplication::BitcoinApplication(int &argc, char **argv):
|
|
QApplication(argc, argv),
|
|
coreThread(0),
|
|
optionsModel(0),
|
|
clientModel(0),
|
|
window(0),
|
|
pollShutdownTimer(0),
|
|
#ifdef ENABLE_WALLET
|
|
paymentServer(0),
|
|
walletModel(0),
|
|
#endif
|
|
returnValue(0)
|
|
{
|
|
setQuitOnLastWindowClosed(false);
|
|
|
|
// UI per-platform customization
|
|
// This must be done inside the BitcoinApplication constructor, or after it, because
|
|
// PlatformStyle::instantiate requires a QApplication
|
|
std::string platformName;
|
|
platformName = GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM);
|
|
platformStyle = PlatformStyle::instantiate(QString::fromStdString(platformName));
|
|
if (!platformStyle) // Fall back to "other" if specified name not found
|
|
platformStyle = PlatformStyle::instantiate("other");
|
|
assert(platformStyle);
|
|
}
|
|
|
|
BitcoinApplication::~BitcoinApplication()
|
|
{
|
|
if(coreThread)
|
|
{
|
|
qDebug() << __func__ << ": Stopping thread";
|
|
Q_EMIT stopThread();
|
|
coreThread->wait();
|
|
qDebug() << __func__ << ": Stopped thread";
|
|
}
|
|
|
|
delete window;
|
|
window = 0;
|
|
#ifdef ENABLE_WALLET
|
|
delete paymentServer;
|
|
paymentServer = 0;
|
|
#endif
|
|
// Delete Qt-settings if user clicked on "Reset Options"
|
|
QSettings settings;
|
|
if(optionsModel && optionsModel->resetSettings){
|
|
settings.clear();
|
|
settings.sync();
|
|
}
|
|
delete optionsModel;
|
|
optionsModel = 0;
|
|
delete platformStyle;
|
|
platformStyle = 0;
|
|
}
|
|
|
|
#ifdef ENABLE_WALLET
|
|
void BitcoinApplication::createPaymentServer()
|
|
{
|
|
paymentServer = new PaymentServer(this);
|
|
}
|
|
#endif
|
|
|
|
void BitcoinApplication::createOptionsModel(bool resetSettings)
|
|
{
|
|
optionsModel = new OptionsModel(NULL, resetSettings);
|
|
}
|
|
|
|
void BitcoinApplication::createWindow(const NetworkStyle *networkStyle)
|
|
{
|
|
window = new BitcoinGUI(platformStyle, networkStyle, 0);
|
|
|
|
pollShutdownTimer = new QTimer(window);
|
|
connect(pollShutdownTimer, SIGNAL(timeout()), window, SLOT(detectShutdown()));
|
|
pollShutdownTimer->start(200);
|
|
}
|
|
|
|
void BitcoinApplication::createSplashScreen(const NetworkStyle *networkStyle)
|
|
{
|
|
SplashScreen *splash = new SplashScreen(0, networkStyle);
|
|
// We don't hold a direct pointer to the splash screen after creation, but the splash
|
|
// screen will take care of deleting itself when slotFinish happens.
|
|
splash->show();
|
|
connect(this, SIGNAL(splashFinished(QWidget*)), splash, SLOT(slotFinish(QWidget*)));
|
|
connect(this, SIGNAL(requestedShutdown()), splash, SLOT(close()));
|
|
}
|
|
|
|
void BitcoinApplication::startThread()
|
|
{
|
|
if(coreThread)
|
|
return;
|
|
coreThread = new QThread(this);
|
|
BitcoinCore *executor = new BitcoinCore();
|
|
executor->moveToThread(coreThread);
|
|
|
|
/* communication to and from thread */
|
|
connect(executor, SIGNAL(initializeResult(int)), this, SLOT(initializeResult(int)));
|
|
connect(executor, SIGNAL(shutdownResult(int)), this, SLOT(shutdownResult(int)));
|
|
connect(executor, SIGNAL(runawayException(QString)), this, SLOT(handleRunawayException(QString)));
|
|
connect(this, SIGNAL(requestedInitialize()), executor, SLOT(initialize()));
|
|
connect(this, SIGNAL(requestedShutdown()), executor, SLOT(shutdown()));
|
|
connect(window, SIGNAL(requestedRestart(QStringList)), executor, SLOT(restart(QStringList)));
|
|
/* make sure executor object is deleted in its own thread */
|
|
connect(this, SIGNAL(stopThread()), executor, SLOT(deleteLater()));
|
|
connect(this, SIGNAL(stopThread()), coreThread, SLOT(quit()));
|
|
|
|
coreThread->start();
|
|
}
|
|
|
|
void BitcoinApplication::parameterSetup()
|
|
{
|
|
InitLogging();
|
|
InitParameterInteraction();
|
|
}
|
|
|
|
void BitcoinApplication::requestInitialize()
|
|
{
|
|
qDebug() << __func__ << ": Requesting initialize";
|
|
startThread();
|
|
Q_EMIT requestedInitialize();
|
|
}
|
|
|
|
void BitcoinApplication::requestShutdown()
|
|
{
|
|
// Show a simple window indicating shutdown status
|
|
// Do this first as some of the steps may take some time below,
|
|
// for example the RPC console may still be executing a command.
|
|
shutdownWindow.reset(ShutdownWindow::showShutdownWindow(window));
|
|
|
|
qDebug() << __func__ << ": Requesting shutdown";
|
|
startThread();
|
|
window->hide();
|
|
window->setClientModel(0);
|
|
pollShutdownTimer->stop();
|
|
|
|
#ifdef ENABLE_WALLET
|
|
window->removeAllWallets();
|
|
delete walletModel;
|
|
walletModel = 0;
|
|
#endif
|
|
delete clientModel;
|
|
clientModel = 0;
|
|
|
|
// Request shutdown from core thread
|
|
Q_EMIT requestedShutdown();
|
|
}
|
|
|
|
void BitcoinApplication::initializeResult(int retval)
|
|
{
|
|
qDebug() << __func__ << ": Initialization result: " << retval;
|
|
// Set exit result: 0 if successful, 1 if failure
|
|
returnValue = retval ? 0 : 1;
|
|
if(retval)
|
|
{
|
|
// Log this only after AppInit2 finishes, as then logging setup is guaranteed complete
|
|
qWarning() << "Platform customization:" << platformStyle->getName();
|
|
#ifdef ENABLE_WALLET
|
|
PaymentServer::LoadRootCAs();
|
|
paymentServer->setOptionsModel(optionsModel);
|
|
#endif
|
|
|
|
clientModel = new ClientModel(optionsModel);
|
|
window->setClientModel(clientModel);
|
|
|
|
#ifdef ENABLE_WALLET
|
|
if(pwalletMain)
|
|
{
|
|
walletModel = new WalletModel(platformStyle, pwalletMain, optionsModel);
|
|
|
|
window->addWallet(BitcoinGUI::DEFAULT_WALLET, walletModel);
|
|
window->setCurrentWallet(BitcoinGUI::DEFAULT_WALLET);
|
|
|
|
connect(walletModel, SIGNAL(coinsSent(CWallet*,SendCoinsRecipient,QByteArray)),
|
|
paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray)));
|
|
}
|
|
#endif
|
|
|
|
// If -min option passed, start window minimized.
|
|
if(GetBoolArg("-min", false))
|
|
{
|
|
window->showMinimized();
|
|
}
|
|
else
|
|
{
|
|
window->show();
|
|
}
|
|
Q_EMIT splashFinished(window);
|
|
|
|
#ifdef ENABLE_WALLET
|
|
// Now that initialization/startup is done, process any command-line
|
|
// dash: URIs or payment requests:
|
|
connect(paymentServer, SIGNAL(receivedPaymentRequest(SendCoinsRecipient)),
|
|
window, SLOT(handlePaymentRequest(SendCoinsRecipient)));
|
|
connect(window, SIGNAL(receivedURI(QString)),
|
|
paymentServer, SLOT(handleURIOrFile(QString)));
|
|
connect(paymentServer, SIGNAL(message(QString,QString,unsigned int)),
|
|
window, SLOT(message(QString,QString,unsigned int)));
|
|
QTimer::singleShot(100, paymentServer, SLOT(uiReady()));
|
|
#endif
|
|
} else {
|
|
quit(); // Exit main loop
|
|
}
|
|
}
|
|
|
|
void BitcoinApplication::shutdownResult(int retval)
|
|
{
|
|
qDebug() << __func__ << ": Shutdown result: " << retval;
|
|
quit(); // Exit main loop after shutdown finished
|
|
}
|
|
|
|
void BitcoinApplication::handleRunawayException(const QString &message)
|
|
{
|
|
QMessageBox::critical(0, "Runaway exception", BitcoinGUI::tr("A fatal error occurred. Dash Core can no longer continue safely and will quit.") + QString("\n\n") + message);
|
|
::exit(EXIT_FAILURE);
|
|
}
|
|
|
|
WId BitcoinApplication::getMainWinId() const
|
|
{
|
|
if (!window)
|
|
return 0;
|
|
|
|
return window->winId();
|
|
}
|
|
|
|
#ifndef BITCOIN_QT_TEST
|
|
int main(int argc, char *argv[])
|
|
{
|
|
SetupEnvironment();
|
|
|
|
/// 1. Parse command-line options. These take precedence over anything else.
|
|
// Command-line options take precedence:
|
|
ParseParameters(argc, argv);
|
|
|
|
// Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
|
|
|
|
/// 2. Basic Qt initialization (not dependent on parameters or configuration)
|
|
#if QT_VERSION < 0x050000
|
|
// Internal string conversion is all UTF-8
|
|
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
|
|
QTextCodec::setCodecForCStrings(QTextCodec::codecForTr());
|
|
#endif
|
|
|
|
Q_INIT_RESOURCE(dash);
|
|
Q_INIT_RESOURCE(dash_locale);
|
|
|
|
BitcoinApplication app(argc, argv);
|
|
#if QT_VERSION > 0x050100
|
|
// Generate high-dpi pixmaps
|
|
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
|
#endif
|
|
#ifdef Q_OS_MAC
|
|
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
|
|
#endif
|
|
#if QT_VERSION >= 0x050500
|
|
// Because of the POODLE attack it is recommended to disable SSLv3 (https://disablessl3.com/),
|
|
// so set SSL protocols to TLS1.0+.
|
|
QSslConfiguration sslconf = QSslConfiguration::defaultConfiguration();
|
|
sslconf.setProtocol(QSsl::TlsV1_0OrLater);
|
|
QSslConfiguration::setDefaultConfiguration(sslconf);
|
|
#endif
|
|
|
|
// Register meta types used for QMetaObject::invokeMethod
|
|
qRegisterMetaType< bool* >();
|
|
// Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
|
|
// IMPORTANT if it is no longer a typedef use the normal variant above
|
|
qRegisterMetaType< CAmount >("CAmount");
|
|
|
|
/// 3. Application identification
|
|
// must be set before OptionsModel is initialized or translations are loaded,
|
|
// as it is used to locate QSettings
|
|
QApplication::setOrganizationName(QAPP_ORG_NAME);
|
|
QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
|
|
QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
|
|
GUIUtil::SubstituteFonts(GetLangTerritory());
|
|
|
|
/// 4. Initialization of translations, so that intro dialog is in user's language
|
|
// Now that QSettings are accessible, initialize translations
|
|
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
|
|
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
|
|
translationInterface.Translate.connect(Translate);
|
|
|
|
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
|
|
// but before showing splash screen.
|
|
if (mapArgs.count("-?") || mapArgs.count("-h") || mapArgs.count("-help") || mapArgs.count("-version"))
|
|
{
|
|
HelpMessageDialog help(NULL, mapArgs.count("-version") ? HelpMessageDialog::about : HelpMessageDialog::cmdline);
|
|
help.showOrPrint();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/// 5. Now that settings and translations are available, ask user for data directory
|
|
// User language is set up: pick a data directory
|
|
Intro::pickDataDirectory();
|
|
|
|
/// 6. Determine availability of data directory and parse dash.conf
|
|
/// - Do not call GetDataDir(true) before this step finishes
|
|
if (!boost::filesystem::is_directory(GetDataDir(false)))
|
|
{
|
|
QMessageBox::critical(0, QObject::tr("Dash Core"),
|
|
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
|
|
return EXIT_FAILURE;
|
|
}
|
|
try {
|
|
ReadConfigFile(mapArgs, mapMultiArgs);
|
|
} catch (const std::exception& e) {
|
|
QMessageBox::critical(0, QObject::tr("Dash Core"),
|
|
QObject::tr("Error: Cannot parse configuration file: %1. Only use key=value syntax.").arg(e.what()));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
/// 7. Determine network (and switch to network specific options)
|
|
// - Do not call Params() before this step
|
|
// - Do this after parsing the configuration file, as the network can be switched there
|
|
// - QSettings() will use the new application name after this, resulting in network-specific settings
|
|
// - Needs to be done before createOptionsModel
|
|
|
|
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
|
|
try {
|
|
SelectParams(ChainNameFromCommandLine());
|
|
} catch(std::exception &e) {
|
|
QMessageBox::critical(0, QObject::tr("Dash Core"), QObject::tr("Error: %1").arg(e.what()));
|
|
return EXIT_FAILURE;
|
|
}
|
|
#ifdef ENABLE_WALLET
|
|
// Parse URIs on command line -- this can affect Params()
|
|
PaymentServer::ipcParseCommandLine(argc, argv);
|
|
#endif
|
|
|
|
QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(QString::fromStdString(Params().NetworkIDString())));
|
|
assert(!networkStyle.isNull());
|
|
// Allow for separate UI settings for testnets
|
|
// QApplication::setApplicationName(networkStyle->getAppName()); // moved to NetworkStyle::NetworkStyle
|
|
// Re-initialize translations after changing application name (language in network-specific settings can be different)
|
|
initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
|
|
|
|
#ifdef ENABLE_WALLET
|
|
/// 7a. parse masternode.conf
|
|
std::string strErr;
|
|
if(!masternodeConfig.read(strErr)) {
|
|
QMessageBox::critical(0, QObject::tr("Dash Core"),
|
|
QObject::tr("Error reading masternode configuration file: %1").arg(strErr.c_str()));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
/// 8. URI IPC sending
|
|
// - Do this early as we don't want to bother initializing if we are just calling IPC
|
|
// - Do this *after* setting up the data directory, as the data directory hash is used in the name
|
|
// of the server.
|
|
// - Do this after creating app and setting up translations, so errors are
|
|
// translated properly.
|
|
if (PaymentServer::ipcSendCommandLine())
|
|
exit(EXIT_SUCCESS);
|
|
|
|
// Start up the payment server early, too, so impatient users that click on
|
|
// dash: links repeatedly have their payment requests routed to this process:
|
|
app.createPaymentServer();
|
|
#endif
|
|
|
|
/// 9. Main GUI initialization
|
|
// Install global event filter that makes sure that long tooltips can be word-wrapped
|
|
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
|
|
#if QT_VERSION < 0x050000
|
|
// Install qDebug() message handler to route to debug.log
|
|
qInstallMsgHandler(DebugMessageHandler);
|
|
#else
|
|
#if defined(Q_OS_WIN)
|
|
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
|
|
qApp->installNativeEventFilter(new WinShutdownMonitor());
|
|
#endif
|
|
// Install qDebug() message handler to route to debug.log
|
|
qInstallMessageHandler(DebugMessageHandler);
|
|
#endif
|
|
// Allow parameter interaction before we create the options model
|
|
app.parameterSetup();
|
|
// Load GUI settings from QSettings
|
|
app.createOptionsModel(mapArgs.count("-resetguisettings") != 0);
|
|
|
|
// Subscribe to global signals from core
|
|
uiInterface.InitMessage.connect(InitMessage);
|
|
|
|
if (GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !GetBoolArg("-min", false))
|
|
app.createSplashScreen(networkStyle.data());
|
|
|
|
try
|
|
{
|
|
app.createWindow(networkStyle.data());
|
|
app.requestInitialize();
|
|
#if defined(Q_OS_WIN) && QT_VERSION >= 0x050000
|
|
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("Dash Core didn't yet exit safely..."), (HWND)app.getMainWinId());
|
|
#endif
|
|
app.exec();
|
|
app.requestShutdown();
|
|
app.exec();
|
|
} catch (const std::exception& e) {
|
|
PrintExceptionContinue(&e, "Runaway exception");
|
|
app.handleRunawayException(QString::fromStdString(strMiscWarning));
|
|
} catch (...) {
|
|
PrintExceptionContinue(NULL, "Runaway exception");
|
|
app.handleRunawayException(QString::fromStdString(strMiscWarning));
|
|
}
|
|
return app.getReturnValue();
|
|
}
|
|
#endif // BITCOIN_QT_TEST
|