Skip to content

Commit 3f976d4

Browse files
authored
Merge pull request #1978 from jamescowens/optionsModel_datadir
gui: Port Bitcoin Intro class (implement the ability to choose a data directory via the GUI)
2 parents bd1c9e2 + 04d0c77 commit 3f976d4

16 files changed

+982
-136
lines changed

src/Makefile.qt.include

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ QT_FORMS_UI = \
9595
qt/forms/sendcoinsdialog.ui \
9696
qt/forms/transactiondescdialog.ui \
9797
qt/forms/askpassphrasedialog.ui \
98-
qt/forms/sendcoinsentry.ui
98+
qt/forms/sendcoinsentry.ui \
99+
qt/forms/intro.ui
99100

100101
QT_MOC_CPP = \
101102
qt/moc_aboutdialog.cpp \
@@ -114,6 +115,7 @@ QT_MOC_CPP = \
114115
qt/moc_diagnosticsdialog.cpp \
115116
qt/moc_editaddressdialog.cpp \
116117
qt/moc_guiutil.cpp \
118+
qt/moc_intro.cpp \
117119
qt/moc_macdockiconhandler.cpp \
118120
qt/moc_macnotificationhandler.cpp \
119121
qt/moc_monitoreddatamapper.cpp \
@@ -155,6 +157,7 @@ GRIDCOIN_MM = \
155157
qt/macnotificationhandler.mm
156158

157159
QT_MOC = \
160+
qt/intro.moc \
158161
qt/overviewpage.moc \
159162
qt/rpcconsole.moc
160163

@@ -182,6 +185,7 @@ GRIDCOINRESEARCH_QT_H = \
182185
qt/editaddressdialog.h \
183186
qt/guiconstants.h \
184187
qt/guiutil.h \
188+
qt/intro.h \
185189
qt/macdockiconhandler.h \
186190
qt/macnotificationhandler.h \
187191
qt/monitoreddatamapper.h \
@@ -240,6 +244,7 @@ GRIDCOINRESEARCH_QT_CPP = \
240244
qt/diagnosticsdialog.cpp \
241245
qt/editaddressdialog.cpp \
242246
qt/guiutil.cpp \
247+
qt/intro.cpp \
243248
qt/monitoreddatamapper.cpp \
244249
qt/notificator.cpp \
245250
qt/optionsdialog.cpp \

src/qt/bitcoin.cpp

Lines changed: 125 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "researcher/researchermodel.h"
1515
#include "optionsmodel.h"
1616
#include "guiutil.h"
17+
#include "qt/intro.h"
1718
#include "guiconstants.h"
1819
#include "init.h"
1920
#include "ui_interface.h"
@@ -67,7 +68,7 @@ extern bool bGridcoinCoreInitComplete;
6768
static BitcoinGUI *guiref;
6869
static QSplashScreen *splashref;
6970

70-
int StartGridcoinQt(int argc, char *argv[]);
71+
int StartGridcoinQt(int argc, char *argv[], QApplication& app, OptionsModel& optionsModel);
7172

7273
static void ThreadSafeMessageBox(const std::string& message, const std::string& caption, int style)
7374
{
@@ -230,9 +231,116 @@ int main(int argc, char *argv[])
230231
// Before this would of been done in main then config file loaded.
231232
// We will load config file here as well.
232233
ParseParameters(argc, argv);
233-
234234
SelectParams(CBaseChainParams::MAIN);
235-
ReadConfigFile(mapArgs, mapMultiArgs);
235+
236+
// Generate high-dpi pixmaps
237+
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
238+
#if QT_VERSION >= 0x050600 && !defined(WIN32)
239+
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
240+
#endif
241+
242+
// Initiate the app here to support choosing the data directory.
243+
Q_INIT_RESOURCE(bitcoin);
244+
Q_INIT_RESOURCE(bitcoin_locale);
245+
246+
QApplication app(argc, argv);
247+
248+
#if defined(WIN32) && defined(QT_GUI)
249+
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
250+
#endif
251+
252+
// Application identification (must be set before OptionsModel is initialized,
253+
// as it is used to locate QSettings)
254+
app.setOrganizationName("Gridcoin");
255+
//XXX app.setOrganizationDomain("");
256+
if(GetBoolArg("-testnet")) // Separate UI settings for testnet
257+
app.setApplicationName("Gridcoin-Qt-testnet");
258+
else
259+
app.setApplicationName("Gridcoin-Qt");
260+
261+
// Install global event filter that makes sure that long tooltips can be word-wrapped
262+
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
263+
264+
// Install global event filter that suppresses help context question mark
265+
app.installEventFilter(new GUIUtil::WindowContextHelpButtonHintFilter(&app));
266+
267+
#if defined(WIN32) && QT_VERSION >= 0x050000
268+
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
269+
app.installNativeEventFilter(new WinShutdownMonitor());
270+
#endif
271+
272+
// Load the optionsModel. This has to be loaded before the translations, because the language selection is
273+
// a setting that can be stored in options.
274+
OptionsModel optionsModel;
275+
276+
// Get desired locale (e.g. "de_DE") from command line or use system locale
277+
QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
278+
QString lang = lang_territory;
279+
// Convert to "de" only by truncating "_DE"
280+
lang.truncate(lang_territory.lastIndexOf('_'));
281+
282+
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
283+
// Load language files for configured locale:
284+
// - First load the translator for the base language, without territory
285+
// - Then load the more specific locale translator
286+
287+
// Load e.g. qt_de.qm
288+
if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
289+
app.installTranslator(&qtTranslatorBase);
290+
291+
// Load e.g. qt_de_DE.qm
292+
if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
293+
app.installTranslator(&qtTranslator);
294+
295+
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
296+
if (translatorBase.load(lang, ":/translations/"))
297+
app.installTranslator(&translatorBase);
298+
299+
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
300+
if (translator.load(lang_territory, ":/translations/"))
301+
app.installTranslator(&translator);
302+
303+
// Now that settings and translations are available, ask user for data directory
304+
bool did_show_intro = false;
305+
// Gracefully exit if the user cancels
306+
if (!Intro::showIfNeeded(did_show_intro)) return EXIT_SUCCESS;
307+
308+
// Determine availability of data directory and parse gridcoinresearch.conf
309+
// Do not call GetDataDir(true) before this step finishes
310+
if (!CheckDataDirOption()) {
311+
ThreadSafeMessageBox(strprintf("Specified data directory \"%s\" does not exist.\n", GetArg("-datadir", "")),
312+
"", CClientUIInterface::ICON_ERROR | CClientUIInterface::OK | CClientUIInterface::MODAL);
313+
QMessageBox::critical(nullptr, PACKAGE_NAME,
314+
QObject::tr("Error: Specified data directory \"%1\" does not exist.")
315+
.arg(QString::fromStdString(GetArg("-datadir", ""))));
316+
return EXIT_FAILURE;
317+
}
318+
319+
// This check must be done before logging is initialized or the config file is read. We do not want another
320+
// instance writing into an already running Gridcoin instance's logs. This is checked in init too,
321+
// but that is too late.
322+
fs::path dataDir = GetDataDir();
323+
324+
if (!LockDirectory(dataDir, ".lock", false)) {
325+
std::string str = strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running "
326+
"and using that directory."),
327+
dataDir, PACKAGE_NAME);
328+
ThreadSafeMessageBox(str, _("Gridcoin"), CClientUIInterface::OK | CClientUIInterface::MODAL);
329+
QMessageBox::critical(nullptr, PACKAGE_NAME,
330+
QObject::tr("Error: Cannot obtain a lock on the specified data directory. "
331+
"An instance is probably already using that directory."));
332+
333+
return EXIT_FAILURE;
334+
}
335+
336+
if (!ReadConfigFile(mapArgs, mapMultiArgs)) {
337+
ThreadSafeMessageBox(strprintf("Error reading configuration file.\n"),
338+
"", CClientUIInterface::ICON_ERROR | CClientUIInterface::OK | CClientUIInterface::MODAL);
339+
QMessageBox::critical(nullptr, PACKAGE_NAME,
340+
QObject::tr("Error: Cannot parse configuration file."));
341+
return EXIT_FAILURE;
342+
}
343+
236344
SelectParams(mapArgs.count("-testnet") ? CBaseChainParams::TESTNET : CBaseChainParams::MAIN);
237345

238346
// Initialize logging as early as possible.
@@ -241,42 +349,31 @@ int main(int argc, char *argv[])
241349
// Do this early as we don't want to bother initializing if we are just calling IPC
242350
ipcScanRelay(argc, argv);
243351

244-
// Here we do it if it was started with the snapshot argument and we not TestNet
352+
// Run snapshot main if Gridcoin was started with the snapshot argument and we are not TestNet
245353
if (mapArgs.count("-snapshotdownload") && !mapArgs.count("-testnet"))
246354
{
247355
GRC::Upgrade snapshot;
248356

249-
// Let's check make sure gridcoin is not already running in the data directory.
250-
if (!LockDirectory(GetDataDir(), ".lock", false))
357+
try
251358
{
252-
fprintf(stderr, "Cannot obtain a lock on data directory %s. Gridcoin is probably already running.", GetDataDir().string().c_str());
253-
254-
exit(1);
359+
snapshot.SnapshotMain();
255360
}
256-
else
257-
{
258-
try
259-
{
260-
snapshot.SnapshotMain();
261-
}
262361

263-
catch (std::runtime_error& e)
264-
{
265-
LogPrintf("Snapshot Downloader: Runtime exception occurred in SnapshotMain() (%s)", e.what());
266-
267-
snapshot.DeleteSnapshot();
362+
catch (std::runtime_error& e)
363+
{
364+
LogPrintf("Snapshot Downloader: Runtime exception occurred in SnapshotMain() (%s)", e.what());
268365

269-
exit(1);
270-
}
366+
snapshot.DeleteSnapshot();
271367

368+
return EXIT_FAILURE;
272369
}
273370

274371
// Delete snapshot regardless of result.
275372
snapshot.DeleteSnapshot();
276373
}
277374

278375
/** Start Qt as normal before it was moved into this function **/
279-
StartGridcoinQt(argc, argv);
376+
StartGridcoinQt(argc, argv, app, optionsModel);
280377

281378
// We got a request to apply snapshot from GUI Menu selection
282379
// We got this request and everything should be shutdown now.
@@ -319,31 +416,16 @@ int main(int argc, char *argv[])
319416
Snapshot.DeleteSnapshot();
320417
}
321418

322-
return 0;
419+
return EXIT_SUCCESS;
323420
}
324421

325-
int StartGridcoinQt(int argc, char *argv[])
422+
int StartGridcoinQt(int argc, char *argv[], QApplication& app, OptionsModel& optionsModel)
326423
{
327424
// Set global boolean to indicate intended presence of GUI to core.
328425
fQtActive = true;
329426

330427
std::shared_ptr<ThreadHandler> threads = std::make_shared<ThreadHandler>();
331428

332-
Q_INIT_RESOURCE(bitcoin);
333-
Q_INIT_RESOURCE(bitcoin_locale);
334-
QApplication app(argc, argv);
335-
//uint SEM_FAILCRITICALERRORS= 0x0001;
336-
//uint SEM_NOGPFAULTERRORBOX = 0x0002;
337-
#if defined(WIN32) && defined(QT_GUI)
338-
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
339-
#endif
340-
341-
// Install global event filter that makes sure that long tooltips can be word-wrapped
342-
app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
343-
344-
// Install global event filter that suppresses help context question mark
345-
app.installEventFilter(new GUIUtil::WindowContextHelpButtonHintFilter(&app));
346-
347429
#if QT_VERSION < 0x050000
348430
// Install qDebug() message handler to route to debug.log
349431
qInstallMsgHandler(DebugMessageHandler);
@@ -352,57 +434,6 @@ int StartGridcoinQt(int argc, char *argv[])
352434
qInstallMessageHandler(DebugMessageHandler);
353435
#endif
354436

355-
#if defined(WIN32) && QT_VERSION >= 0x050000
356-
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
357-
app.installNativeEventFilter(new WinShutdownMonitor());
358-
#endif
359-
360-
if (!fs::is_directory(GetDataDir(false)))
361-
{
362-
QMessageBox::critical(0, "Gridcoin",
363-
QString("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(mapArgs["-datadir"])));
364-
return 1;
365-
}
366-
367-
// Application identification (must be set before OptionsModel is initialized,
368-
// as it is used to locate QSettings)
369-
app.setOrganizationName("Gridcoin");
370-
//XXX app.setOrganizationDomain("");
371-
if(GetBoolArg("-testnet")) // Separate UI settings for testnet
372-
app.setApplicationName("Gridcoin-Qt-testnet");
373-
else
374-
app.setApplicationName("Gridcoin-Qt");
375-
376-
// ... then GUI settings:
377-
OptionsModel optionsModel;
378-
379-
// Get desired locale (e.g. "de_DE") from command line or use system locale
380-
QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
381-
QString lang = lang_territory;
382-
// Convert to "de" only by truncating "_DE"
383-
lang.truncate(lang_territory.lastIndexOf('_'));
384-
385-
QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
386-
// Load language files for configured locale:
387-
// - First load the translator for the base language, without territory
388-
// - Then load the more specific locale translator
389-
390-
// Load e.g. qt_de.qm
391-
if (qtTranslatorBase.load("qt_" + lang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
392-
app.installTranslator(&qtTranslatorBase);
393-
394-
// Load e.g. qt_de_DE.qm
395-
if (qtTranslator.load("qt_" + lang_territory, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
396-
app.installTranslator(&qtTranslator);
397-
398-
// Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
399-
if (translatorBase.load(lang, ":/translations/"))
400-
app.installTranslator(&translatorBase);
401-
402-
// Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
403-
if (translator.load(lang_territory, ":/translations/"))
404-
app.installTranslator(&translator);
405-
406437
// Subscribe to global signals from core
407438
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
408439
uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
@@ -421,7 +452,7 @@ int StartGridcoinQt(int argc, char *argv[])
421452
{
422453
GUIUtil::HelpMessageBox help;
423454
help.showOrPrint();
424-
return 1;
455+
return EXIT_FAILURE;
425456
}
426457

427458
QSplashScreen splash(QPixmap(":/images/splash"), 0);
@@ -446,7 +477,7 @@ int StartGridcoinQt(int argc, char *argv[])
446477
if (!threads->createThread(ThreadAppInit2,threads,"AppInit2 Thread"))
447478
{
448479
LogPrintf("Error; NewThread(ThreadAppInit2) failed");
449-
return 1;
480+
return EXIT_FAILURE;
450481
}
451482
else
452483
{
@@ -526,7 +557,7 @@ int StartGridcoinQt(int argc, char *argv[])
526557
threads->removeAll();
527558
threads.reset();
528559

529-
return 0;
560+
return EXIT_SUCCESS;
530561
}
531562

532563
#endif // BITCOIN_QT_TEST

0 commit comments

Comments
 (0)