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,188 @@ 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
+ boost::signals2::connection m_handler_message_box;
178
+ std::unique_ptr<interfaces::Init> m_init;
179
+ std::unique_ptr<interfaces::Node> m_node;
180
+ std::unique_ptr<interfaces::Chain> m_chain;
181
+ NodeModel* m_node_model{nullptr };
182
+ InitExecutor* m_executor{nullptr };
183
+ ChainModel* m_chain_model{nullptr };
184
+ OptionsQmlModel* m_options_model{nullptr };
185
+ int m_argc;
186
+ char ** m_argv;
187
+ NetworkTrafficTower* m_network_traffic_tower;
188
+ PeerTableModel* m_peer_model;
189
+ PeerListSortProxy* m_peer_model_sort_proxy;
190
+ bool m_isOnboarded;
191
+
192
+ bool createNode (QGuiApplication& app, QQmlApplicationEngine& engine, int & argc, char * argv[], ArgsManager& gArgs )
193
+ {
194
+ m_engine = &engine;
195
+
196
+ InitLogging (gArgs );
197
+ InitParameterInteraction (gArgs );
198
+
199
+ m_init = interfaces::MakeGuiInit (argc, argv);
200
+
201
+ m_node = m_init->makeNode ();
202
+ m_chain = m_init->makeChain ();
203
+
204
+ if (!m_node->baseInitialize ()) {
205
+ // A dialog with detailed error will have been shown by InitError().
206
+ return EXIT_FAILURE;
207
+ }
208
+
209
+ m_handler_message_box.disconnect ();
210
+
211
+ m_node_model = new NodeModel{*m_node};
212
+ m_executor = new InitExecutor{*m_node};
213
+ QObject::connect (m_node_model, &NodeModel::requestedInitialize, m_executor, &InitExecutor::initialize);
214
+ QObject::connect (m_node_model, &NodeModel::requestedShutdown, m_executor, &InitExecutor::shutdown);
215
+ QObject::connect (m_executor, &InitExecutor::initializeResult, m_node_model, &NodeModel::initializeResult);
216
+ QObject::connect (m_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
217
+
218
+ m_network_traffic_tower = new NetworkTrafficTower{*m_node_model};
219
+ #ifdef __ANDROID__
220
+ AndroidNotifier android_notifier{*m_node_model};
221
+ #endif
222
+
223
+ m_chain_model = new ChainModel{*m_chain};
224
+ m_chain_model->setCurrentNetworkName (QString::fromStdString (ChainTypeToString (gArgs .GetChainType ())));
225
+ setupChainQSettings (m_app, m_chain_model->currentNetworkName ());
226
+
227
+ QObject::connect (m_node_model, &NodeModel::setTimeRatioList, m_chain_model, &ChainModel::setTimeRatioList);
228
+ QObject::connect (m_node_model, &NodeModel::setTimeRatioListInitial, m_chain_model, &ChainModel::setTimeRatioListInitial);
229
+
230
+ qGuiApp->setQuitOnLastWindowClosed (false );
231
+ QObject::connect (qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
232
+ m_node->startShutdown ();
233
+ });
234
+
235
+ m_peer_model = new PeerTableModel{*m_node, nullptr };
236
+ m_peer_model_sort_proxy = new PeerListSortProxy{nullptr };
237
+ m_peer_model_sort_proxy->setSourceModel (m_peer_model);
238
+
239
+ m_engine->rootContext ()->setContextProperty (" networkTrafficTower" , m_network_traffic_tower);
240
+ m_engine->rootContext ()->setContextProperty (" nodeModel" , m_node_model);
241
+ m_engine->rootContext ()->setContextProperty (" chainModel" , m_chain_model);
242
+ m_engine->rootContext ()->setContextProperty (" peerTableModel" , m_peer_model);
243
+ m_engine->rootContext ()->setContextProperty (" peerListModelProxy" , m_peer_model_sort_proxy);
244
+
245
+ m_options_model->setNode (&(*m_node), m_isOnboarded);
246
+
247
+ QObject::connect (m_options_model, &OptionsQmlModel::requestedShutdown, m_executor, &InitExecutor::shutdown);
248
+
249
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
250
+
251
+ m_node_model->startShutdownPolling ();
252
+
253
+ return true ;
254
+ }
255
+
256
+ void startNodeAndTransitionSlot () { createNode (*m_app, *m_engine, m_argc, m_argv, gArgs ); }
257
+
258
+ // moved this function to a separate function for code reusability
259
+ int initializeAndRunApplication (QGuiApplication* app, QQmlApplicationEngine* m_engine) {
260
+ AppMode* app_mode = SetupAppMode ();
261
+
262
+ // Register the singleton instance for AppMode with the QML engine
263
+ qmlRegisterSingletonInstance<AppMode>(" org.bitcoincore.qt" , 1 , 0 , " AppMode" , app_mode);
264
+
265
+ // Register custom QML types
266
+ qmlRegisterType<BlockClockDial>(" org.bitcoincore.qt" , 1 , 0 , " BlockClockDial" );
267
+ qmlRegisterType<LineGraph>(" org.bitcoincore.qt" , 1 , 0 , " LineGraph" );
268
+
269
+ // Load the main QML file
270
+ m_engine->load (QUrl (QStringLiteral (" qrc:///qml/pages/main.qml" )));
271
+
272
+ // Check if the QML engine failed to load the main QML file
273
+ if (m_engine->rootObjects ().isEmpty ()) {
274
+ return EXIT_FAILURE;
275
+ }
276
+
277
+ // Get the first root object as a QQuickWindow
278
+ auto window = qobject_cast<QQuickWindow*>(m_engine->rootObjects ().first ());
279
+ if (!window) {
280
+ return EXIT_FAILURE;
281
+ }
282
+
283
+ // Install the custom message handler for qDebug()
284
+ qInstallMessageHandler (DebugMessageHandler);
285
+
286
+ // Log the graphics API in use
287
+ qInfo () << " Graphics API in use:" << QmlUtil::GraphicsApi (window);
288
+
289
+ // Execute the application
290
+ return qGuiApp->exec ();
291
+ }
292
+
293
+ bool startNode (QGuiApplication& app, QQmlApplicationEngine& engine, int & argc, char * argv[])
294
+ {
295
+ m_engine = &engine;
296
+ QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate (Params ().GetChainType ())};
297
+ assert (!network_style.isNull ());
298
+ m_engine->addImageProvider (QStringLiteral (" images" ), new ImageProvider{network_style.data ()});
299
+
300
+ m_isOnboarded = true ;
301
+
302
+ m_options_model = new OptionsQmlModel{nullptr , m_isOnboarded};
303
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
304
+
305
+ // moved this so that the settings.json file is read and parsed before creating the node
306
+ std::string error;
307
+ // / Read and parse settings.json file.
308
+ std::vector<std::string> errors;
309
+ if (!gArgs .ReadSettingsFile (&errors)) {
310
+ error = strprintf (" Failed loading settings file:\n %s\n " , MakeUnorderedList (errors));
311
+ InitError (Untranslated (error));
312
+ return EXIT_FAILURE;
313
+ }
314
+
315
+ createNode (*m_app, *m_engine, argc, argv, gArgs );
316
+
317
+ initializeAndRunApplication (&app, m_engine);
318
+ return true ;
319
+ }
320
+
321
+ bool startOnboarding (QGuiApplication& app, QQmlApplicationEngine& engine, ArgsManager& gArgs )
322
+ {
323
+ m_engine = &engine;
324
+ QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate (Params ().GetChainType ())};
325
+ assert (!network_style.isNull ());
326
+ m_engine->addImageProvider (QStringLiteral (" images" ), new ImageProvider{network_style.data ()});
327
+
328
+ m_isOnboarded = false ;
329
+
330
+ m_options_model = new OptionsQmlModel{nullptr , m_isOnboarded};
331
+
332
+ if (gArgs .IsArgSet (" -resetguisettings" )) {
333
+ m_options_model->defaultReset ();
334
+ }
335
+
336
+ m_engine->rootContext ()->setContextProperty (" optionsModel" , m_options_model);
337
+
338
+ QObject::connect (m_options_model, &OptionsQmlModel::onboardingFinished, startNodeAndTransitionSlot);
339
+
340
+ initializeAndRunApplication (&app, m_engine);
341
+
342
+ return true ;
343
+ }
161
344
} // namespace
162
345
163
346
@@ -175,9 +358,7 @@ int QmlGuiMain(int argc, char* argv[])
175
358
QGuiApplication::styleHints ()->setTabFocusBehavior (Qt::TabFocusAllControls);
176
359
QGuiApplication app (argc, argv);
177
360
178
- auto handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect (InitErrorMessageBox);
179
-
180
- std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit (argc, argv);
361
+ auto m_handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect (InitErrorMessageBox);
181
362
182
363
SetupEnvironment ();
183
364
util::ThreadSetInternalName (" main" );
@@ -189,6 +370,10 @@ int QmlGuiMain(int argc, char* argv[])
189
370
app.setOrganizationDomain (QAPP_ORG_DOMAIN);
190
371
app.setApplicationName (QAPP_APP_NAME_DEFAULT);
191
372
373
+ QSettings settings;
374
+ QString dataDir;
375
+ dataDir = settings.value (" strDataDir" , dataDir).toString ();
376
+
192
377
// / Parse command-line options. We do this after qt in order to show an error if there are problems parsing these.
193
378
SetupServerArgs (gArgs );
194
379
SetupUIArgs (gArgs );
@@ -218,16 +403,9 @@ int QmlGuiMain(int argc, char* argv[])
218
403
return EXIT_FAILURE;
219
404
}
220
405
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
406
QVariant need_onboarding (true );
230
- if (gArgs .IsArgSet (" -datadir" ) && !gArgs .GetPathArg (" -datadir" ).empty ()) {
407
+ if ((gArgs .IsArgSet (" -datadir" ) && !gArgs .GetPathArg (" -datadir" ).empty ()) || fs::exists (GUIUtil::QStringToPath (dataDir)) ) {
408
+ setCustomDataDir (dataDir);
231
409
need_onboarding.setValue (false );
232
410
} else if (ConfigurationFileExists (gArgs )) {
233
411
need_onboarding.setValue (false );
@@ -240,89 +418,22 @@ int QmlGuiMain(int argc, char* argv[])
240
418
// Default printtoconsole to false for the GUI. GUI programs should not
241
419
// print to the console unnecessarily.
242
420
gArgs .SoftSetBoolArg (" -printtoconsole" , false );
243
- InitLogging (gArgs );
244
- InitParameterInteraction (gArgs );
245
421
246
422
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
423
GUIUtil::LoadFont (" :/fonts/inter/regular" );
287
424
GUIUtil::LoadFont (" :/fonts/inter/semibold" );
288
425
289
- QQmlApplicationEngine engine;
290
-
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 ()});
426
+ m_app = &app;
294
427
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);
428
+ QQmlApplicationEngine engine;
300
429
301
- OptionsQmlModel options_model (*node, !need_onboarding.toBool ());
302
- engine.rootContext ()->setContextProperty (" optionsModel" , &options_model);
303
430
engine.rootContext ()->setContextProperty (" needOnboarding" , need_onboarding);
304
431
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;
432
+ if (need_onboarding.toBool ()) {
433
+ startOnboarding (*m_app, engine, gArgs );
434
+ } else {
435
+ startNode (*m_app, engine, argc, argv);
319
436
}
320
437
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 ();
438
+ return 0 ;
328
439
}
0 commit comments