45
45
#include < QQmlApplicationEngine>
46
46
#include < QQmlContext>
47
47
#include < QQuickWindow>
48
+ #include < QSettings>
48
49
#include < QString>
49
50
#include < QStyleHints>
50
51
#include < QUrl>
@@ -77,7 +78,7 @@ void SetupUIArgs(ArgsManager& argsman)
77
78
argsman.AddArg (" -resetguisettings" , " Reset all settings changed in the GUI" , ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
78
79
}
79
80
80
- AppMode SetupAppMode ()
81
+ AppMode* SetupAppMode ()
81
82
{
82
83
bool wallet_enabled;
83
84
AppMode::Mode mode;
@@ -93,7 +94,7 @@ AppMode SetupAppMode()
93
94
wallet_enabled = false ;
94
95
#endif // ENABLE_WALLET
95
96
96
- return AppMode (mode, wallet_enabled);
97
+ return new AppMode (mode, wallet_enabled);
97
98
}
98
99
99
100
bool InitErrorMessageBox (
@@ -103,9 +104,9 @@ bool InitErrorMessageBox(
103
104
{
104
105
QQmlApplicationEngine engine;
105
106
106
- AppMode app_mode = SetupAppMode ();
107
+ AppMode* app_mode = SetupAppMode ();
107
108
108
- qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , & app_mode);
109
+ qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , app_mode);
109
110
engine.rootContext ()->setContextProperty (" message" , QString::fromStdString (message.translated ));
110
111
engine.load (QUrl (QStringLiteral (" qrc:///qml/pages/initerrormessage.qml" )));
111
112
if (engine.rootObjects ().isEmpty ()) {
@@ -158,6 +159,193 @@ void setupChainQSettings(QGuiApplication* app, QString chain)
158
159
app->setApplicationName (QAPP_APP_NAME_REGTEST);
159
160
}
160
161
}
162
+
163
+ // added this function to set custom data directory when starting node
164
+ bool setCustomDataDir (QString strDataDir)
165
+ {
166
+ if (fs::exists (GUIUtil::QStringToPath (strDataDir))){
167
+ gArgs .SoftSetArg (" -datadir" , fs::PathToString (GUIUtil::QStringToPath (strDataDir)));
168
+ gArgs .ClearPathCache ();
169
+ return true ;
170
+ } else {
171
+ return false ;
172
+ }
173
+ }
174
+
175
+ QGuiApplication* m_app;
176
+ QQmlApplicationEngine* m_engine;
177
+ // ArgsManager* m_gArgs;
178
+ QQuickWindow* m_window;
179
+ boost::signals2::connection m_handler_message_box;
180
+ std::unique_ptr<interfaces::Init> m_init;
181
+ std::unique_ptr<interfaces::Node> m_node;
182
+ std::unique_ptr<interfaces::Chain> m_chain;
183
+ NodeModel* m_node_model{nullptr };
184
+ InitExecutor* m_executor{nullptr };
185
+ ChainModel* m_chain_model{nullptr };
186
+ OptionsQmlModel* m_options_model{nullptr };
187
+ // OnboardingModel* m_onboarding_model{nullptr};
188
+ int m_argc;
189
+ char ** m_argv;
190
+ bool m_prune;
191
+ int m_prune_size_gb;
192
+ NetworkTrafficTower* m_network_traffic_tower;
193
+ PeerTableModel* m_peer_model;
194
+ PeerListSortProxy* m_peer_model_sort_proxy;
195
+ QThread* m_introThread;
196
+ bool m_isOnboarded;
197
+
198
+ bool createNode (QGuiApplication& app, QQmlApplicationEngine& engine, int & argc, char * argv[], ArgsManager& gArgs )
199
+ {
200
+ m_engine = &engine;
201
+
202
+ InitLogging (gArgs );
203
+ InitParameterInteraction (gArgs );
204
+
205
+ m_init = interfaces::MakeGuiInit (argc, argv);
206
+
207
+ m_node = m_init->makeNode ();
208
+ m_chain = m_init->makeChain ();
209
+
210
+ if (!m_node->baseInitialize ()) {
211
+ // A dialog with detailed error will have been shown by InitError().
212
+ return EXIT_FAILURE;
213
+ }
214
+
215
+ m_handler_message_box.disconnect ();
216
+
217
+ m_node_model = new NodeModel{*m_node};
218
+ m_executor = new InitExecutor{*m_node};
219
+ QObject::connect (m_node_model, &NodeModel::requestedInitialize, m_executor, &InitExecutor::initialize);
220
+ QObject::connect (m_node_model, &NodeModel::requestedShutdown, m_executor, &InitExecutor::shutdown);
221
+ QObject::connect (m_executor, &InitExecutor::initializeResult, m_node_model, &NodeModel::initializeResult);
222
+ QObject::connect (m_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
223
+
224
+ m_network_traffic_tower = new NetworkTrafficTower{*m_node_model};
225
+ #ifdef __ANDROID__
226
+ AndroidNotifier android_notifier{*m_node_model};
227
+ #endif
228
+
229
+ m_chain_model = new ChainModel{*m_chain};
230
+ m_chain_model->setCurrentNetworkName (QString::fromStdString (ChainTypeToString (gArgs .GetChainType ())));
231
+ setupChainQSettings (m_app, m_chain_model->currentNetworkName ());
232
+
233
+ QObject::connect (m_node_model, &NodeModel::setTimeRatioList, m_chain_model, &ChainModel::setTimeRatioList);
234
+ QObject::connect (m_node_model, &NodeModel::setTimeRatioListInitial, m_chain_model, &ChainModel::setTimeRatioListInitial);
235
+
236
+ qGuiApp->setQuitOnLastWindowClosed (false );
237
+ QObject::connect (qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
238
+ m_node->startShutdown ();
239
+ });
240
+
241
+ m_peer_model = new PeerTableModel{*m_node, nullptr };
242
+ m_peer_model_sort_proxy = new PeerListSortProxy{nullptr };
243
+ m_peer_model_sort_proxy->setSourceModel (m_peer_model);
244
+
245
+ m_engine->rootContext ()->setContextProperty (" networkTrafficTower" , m_network_traffic_tower);
246
+ m_engine->rootContext ()->setContextProperty (" nodeModel" , m_node_model);
247
+ m_engine->rootContext ()->setContextProperty (" chainModel" , m_chain_model);
248
+ m_engine->rootContext ()->setContextProperty (" peerTableModel" , m_peer_model);
249
+ m_engine->rootContext ()->setContextProperty (" peerListModelProxy" , m_peer_model_sort_proxy);
250
+
251
+ m_options_model->setNode (&(*m_node), m_isOnboarded);
252
+
253
+ QObject::connect (m_options_model, &OptionsQmlModel::requestedShutdown, m_executor, &InitExecutor::shutdown);
254
+
255
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
256
+
257
+ m_node_model->startShutdownPolling ();
258
+
259
+ return true ;
260
+ }
261
+
262
+ void startNodeAndTransitionSlot () { createNode (*m_app, *m_engine, m_argc, m_argv, gArgs ); }
263
+
264
+ bool startNode (QGuiApplication& app, QQmlApplicationEngine& engine, int & argc, char * argv[])
265
+ {
266
+ m_engine = &engine;
267
+ QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate (Params ().GetChainType ())};
268
+ assert (!network_style.isNull ());
269
+ m_engine->addImageProvider (QStringLiteral (" images" ), new ImageProvider{network_style.data ()});
270
+
271
+ m_isOnboarded = true ;
272
+
273
+ m_options_model = new OptionsQmlModel{nullptr , m_isOnboarded};
274
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
275
+
276
+ // moved this so that the settings.json file is read and parsed before creating the node
277
+ std::string error;
278
+ // / Read and parse settings.json file.
279
+ std::vector<std::string> errors;
280
+ if (!gArgs .ReadSettingsFile (&errors)) {
281
+ error = strprintf (" Failed loading settings file:\n %s\n " , MakeUnorderedList (errors));
282
+ InitError (Untranslated (error));
283
+ return EXIT_FAILURE;
284
+ }
285
+
286
+ createNode (*m_app, *m_engine, argc, argv, gArgs );
287
+
288
+ AppMode* app_mode = SetupAppMode ();
289
+
290
+ qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , app_mode);
291
+ qmlRegisterType<BlockClockDial>(" org.bitcoincore.qt" , 1 , 0 , " BlockClockDial" );
292
+ qmlRegisterType<LineGraph>(" org.bitcoincore.qt" , 1 , 0 , " LineGraph" );
293
+
294
+ m_engine->load (QUrl (QStringLiteral (" qrc:///qml/pages/main.qml" )));
295
+ if (m_engine->rootObjects ().isEmpty ()) {
296
+ return EXIT_FAILURE;
297
+ }
298
+
299
+ auto window = qobject_cast<QQuickWindow*>(engine.rootObjects ().first ());
300
+ if (!window) {
301
+ return EXIT_FAILURE;
302
+ }
303
+
304
+ // Install qDebug() message handler to route to debug.log
305
+ qInstallMessageHandler (DebugMessageHandler);
306
+
307
+ qInfo () << " Graphics API in use:" << QmlUtil::GraphicsApi (window);
308
+
309
+ return qGuiApp->exec ();
310
+ }
311
+
312
+ bool startOnboarding (QGuiApplication& app, QQmlApplicationEngine& engine, ArgsManager& gArgs )
313
+ {
314
+ m_engine = &engine;
315
+ QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate (Params ().GetChainType ())};
316
+ assert (!network_style.isNull ());
317
+ m_engine->addImageProvider (QStringLiteral (" images" ), new ImageProvider{network_style.data ()});
318
+
319
+ m_isOnboarded = false ;
320
+
321
+ m_options_model = new OptionsQmlModel{nullptr , m_isOnboarded};
322
+
323
+ if (gArgs .IsArgSet (" -resetguisettings" )) {
324
+ m_options_model->defaultReset ();
325
+ }
326
+
327
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
328
+
329
+ QObject::connect (m_options_model, &OptionsQmlModel::onboardingFinished, startNodeAndTransitionSlot);
330
+
331
+ AppMode* app_mode = SetupAppMode ();
332
+
333
+ qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , app_mode);
334
+ qmlRegisterType<BlockClockDial>(" org.bitcoincore.qt" , 1 , 0 , " BlockClockDial" );
335
+ qmlRegisterType<LineGraph>(" org.bitcoincore.qt" , 1 , 0 , " LineGraph" );
336
+
337
+ m_engine->load (QUrl (QStringLiteral (" qrc:///qml/pages/main.qml" )));
338
+ if (m_engine->rootObjects ().isEmpty ()) {
339
+ return EXIT_FAILURE;
340
+ }
341
+
342
+ auto window = qobject_cast<QQuickWindow*>(m_engine->rootObjects ().first ());
343
+ if (!window) {
344
+ return EXIT_FAILURE;
345
+ }
346
+
347
+ return qGuiApp->exec ();
348
+ }
161
349
} // namespace
162
350
163
351
@@ -175,9 +363,7 @@ int QmlGuiMain(int argc, char* argv[])
175
363
QGuiApplication::styleHints ()->setTabFocusBehavior (Qt::TabFocusAllControls);
176
364
QGuiApplication app (argc, argv);
177
365
178
- auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect (InitErrorMessageBox);
179
-
180
- std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit (argc, argv);
366
+ auto m_handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect (InitErrorMessageBox);
181
367
182
368
SetupEnvironment ();
183
369
util::ThreadSetInternalName (" main" );
@@ -189,6 +375,10 @@ int QmlGuiMain(int argc, char* argv[])
189
375
app.setOrganizationDomain (QAPP_ORG_DOMAIN);
190
376
app.setApplicationName (QAPP_APP_NAME_DEFAULT);
191
377
378
+ QSettings settings;
379
+ QString dataDir;
380
+ dataDir = settings.value (" strDataDir" , dataDir).toString ();
381
+
192
382
// / Parse command-line options. We do this after qt in order to show an error if there are problems parsing these.
193
383
SetupServerArgs (gArgs );
194
384
SetupUIArgs (gArgs );
@@ -218,16 +408,9 @@ int QmlGuiMain(int argc, char* argv[])
218
408
return EXIT_FAILURE;
219
409
}
220
410
221
- // / Read and parse settings.json file.
222
- std::vector<std::string> errors;
223
- if (!gArgs .ReadSettingsFile (&errors)) {
224
- error = strprintf (" Failed loading settings file:\n %s\n " , MakeUnorderedList (errors));
225
- InitError (Untranslated (error));
226
- return EXIT_FAILURE;
227
- }
228
-
229
411
QVariant need_onboarding (true );
230
- if (gArgs .IsArgSet (" -datadir" ) && !gArgs .GetPathArg (" -datadir" ).empty ()) {
412
+ if ((gArgs .IsArgSet (" -datadir" ) && !gArgs .GetPathArg (" -datadir" ).empty ()) || fs::exists (GUIUtil::QStringToPath (dataDir)) ) {
413
+ setCustomDataDir (dataDir);
231
414
need_onboarding.setValue (false );
232
415
} else if (ConfigurationFileExists (gArgs )) {
233
416
need_onboarding.setValue (false );
@@ -240,89 +423,22 @@ int QmlGuiMain(int argc, char* argv[])
240
423
// Default printtoconsole to false for the GUI. GUI programs should not
241
424
// print to the console unnecessarily.
242
425
gArgs .SoftSetBoolArg (" -printtoconsole" , false );
243
- InitLogging (gArgs );
244
- InitParameterInteraction (gArgs );
245
426
246
427
GUIUtil::LogQtInfo ();
247
-
248
- std::unique_ptr<interfaces::Node> node = init->makeNode ();
249
- std::unique_ptr<interfaces::Chain> chain = init->makeChain ();
250
- if (!node->baseInitialize ()) {
251
- // A dialog with detailed error will have been shown by InitError().
252
- return EXIT_FAILURE;
253
- }
254
-
255
- handler_message_box.disconnect ();
256
-
257
- NodeModel node_model{*node};
258
- InitExecutor init_executor{*node};
259
- QObject::connect (&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize);
260
- QObject::connect (&node_model, &NodeModel::requestedShutdown, &init_executor, &InitExecutor::shutdown);
261
- QObject::connect (&init_executor, &InitExecutor::initializeResult, &node_model, &NodeModel::initializeResult);
262
- QObject::connect (&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
263
- // QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException);
264
-
265
- NetworkTrafficTower network_traffic_tower{node_model};
266
- #ifdef __ANDROID__
267
- AndroidNotifier android_notifier{node_model};
268
- #endif
269
-
270
- ChainModel chain_model{*chain};
271
- chain_model.setCurrentNetworkName (QString::fromStdString (ChainTypeToString (gArgs .GetChainType ())));
272
- setupChainQSettings (&app, chain_model.currentNetworkName ());
273
-
274
- QObject::connect (&node_model, &NodeModel::setTimeRatioList, &chain_model, &ChainModel::setTimeRatioList);
275
- QObject::connect (&node_model, &NodeModel::setTimeRatioListInitial, &chain_model, &ChainModel::setTimeRatioListInitial);
276
-
277
- qGuiApp->setQuitOnLastWindowClosed (false );
278
- QObject::connect (qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
279
- node->startShutdown ();
280
- });
281
-
282
- PeerTableModel peer_model{*node, nullptr };
283
- PeerListSortProxy peer_model_sort_proxy{nullptr };
284
- peer_model_sort_proxy.setSourceModel (&peer_model);
285
-
286
428
GUIUtil::LoadFont (" :/fonts/inter/regular" );
287
429
GUIUtil::LoadFont (" :/fonts/inter/semibold" );
288
430
289
- QQmlApplicationEngine engine ;
431
+ m_app = &app ;
290
432
291
- QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate (Params ().GetChainType ())};
292
- assert (!network_style.isNull ());
293
- engine.addImageProvider (QStringLiteral (" images" ), new ImageProvider{network_style.data ()});
294
-
295
- engine.rootContext ()->setContextProperty (" networkTrafficTower" , &network_traffic_tower);
296
- engine.rootContext ()->setContextProperty (" nodeModel" , &node_model);
297
- engine.rootContext ()->setContextProperty (" chainModel" , &chain_model);
298
- engine.rootContext ()->setContextProperty (" peerTableModel" , &peer_model);
299
- engine.rootContext ()->setContextProperty (" peerListModelProxy" , &peer_model_sort_proxy);
433
+ QQmlApplicationEngine engine;
300
434
301
- OptionsQmlModel options_model (*node, !need_onboarding.toBool ());
302
- engine.rootContext ()->setContextProperty (" optionsModel" , &options_model);
303
435
engine.rootContext ()->setContextProperty (" needOnboarding" , need_onboarding);
304
436
305
- AppMode app_mode = SetupAppMode ();
306
-
307
- qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , &app_mode);
308
- qmlRegisterType<BlockClockDial>(" org.bitcoincore.qt" , 1 , 0 , " BlockClockDial" );
309
- qmlRegisterType<LineGraph>(" org.bitcoincore.qt" , 1 , 0 , " LineGraph" );
310
-
311
- engine.load (QUrl (QStringLiteral (" qrc:///qml/pages/main.qml" )));
312
- if (engine.rootObjects ().isEmpty ()) {
313
- return EXIT_FAILURE;
314
- }
315
-
316
- auto window = qobject_cast<QQuickWindow*>(engine.rootObjects ().first ());
317
- if (!window) {
318
- return EXIT_FAILURE;
437
+ if (need_onboarding.toBool ()) {
438
+ startOnboarding (*m_app, engine, gArgs );
439
+ } else {
440
+ startNode (*m_app, engine, argc, argv);
319
441
}
320
442
321
- // Install qDebug() message handler to route to debug.log
322
- qInstallMessageHandler (DebugMessageHandler);
323
-
324
- qInfo () << " Graphics API in use:" << QmlUtil::GraphicsApi (window);
325
-
326
- node_model.startShutdownPolling ();
327
- return qGuiApp->exec ();
443
+ return 0 ;
328
444
}
0 commit comments