comparison libgui/src/resource-manager.cc @ 31619:ad014fc78bd6

use individual local gui_settings objects Previously, we created a single gui_settings object (derived from QSettings) and accessed it from the resource_manager object. That design is not necessary and is not the way QSettings was designed to be used. Instead of managing a single object, we should be using individual QSettings objects where needed. Each individual QSettings object manages thread-safe access to a single global collection of settings. The Qt docs say that operations on QSettings are not thread safe, but that means that you can't create a QSettings object in one thread and use it in another without some locking. I'm not sure whether we were doing that correctly, but with this change it no longer matters. Each QSettings object does perform locking when reading or writing the underlying global data. * resource-manager.h, resource-manager.cc (resource_manager::m_settings): Delete data member. (resource_manager::get_settings): Delete. * annotation-dialog.cc, QTerminal.cc, QTerminal.h, command-widget.cc, command-widget.h, community-news.cc, dialog.cc, documentation-bookmarks.cc, documentation-bookmarks.h, documentation-dock-widget.cc, documentation-dock-widget.h, documentation.cc, documentation.h, dw-main-window.cc, dw-main-window.h, external-editor-interface.cc, files-dock-widget.cc, files-dock-widget.h, find-files-dialog.cc, history-dock-widget.cc, history-dock-widget.h, file-editor-interface.h, file-editor-tab.cc, file-editor-tab.h, file-editor.cc, file-editor.h, find-dialog.cc, octave-qscintilla.cc, main-window.cc, main-window.h, news-reader.cc, octave-dock-widget.cc, octave-dock-widget.h, qt-interpreter-events.cc, qt-interpreter-events.h, release-notes.cc, resource-manager.cc, resource-manager.h, set-path-dialog.cc, settings-dialog.cc, settings-dialog.h, shortcut-manager.cc, shortcut-manager.h, terminal-dock-widget.cc, terminal-dock-widget.h, variable-editor.cc, variable-editor.h, welcome-wizard.cc, workspace-model.cc, workspace-model.h, workspace-view.cc: Use local gui_settings objects instead of accessing a pointer to a single gui_settings object owned by the resource_manager object.
author John W. Eaton <jwe@octave.org>
date Fri, 02 Dec 2022 14:23:53 -0500
parents 1f57ea5dfd4a
children 6dfaaf8ecf3b
comparison
equal deleted inserted replaced
31618:cd833a9baaa7 31619:ad014fc78bd6
62 #include "help.h" 62 #include "help.h"
63 63
64 namespace octave 64 namespace octave
65 { 65 {
66 resource_manager::resource_manager (void) 66 resource_manager::resource_manager (void)
67 : m_settings_directory (), m_settings_file (), m_settings (nullptr), 67 : m_settings_directory (), m_settings_file (),
68 m_temporary_files (), m_icon_fallbacks () 68 m_temporary_files (), m_icon_fallbacks ()
69 { 69 {
70 // Location, name, and format of settings file determined by 70 // Location, name, and format of settings file determined by
71 // settings in qt_application class construtor. 71 // settings in qt_application class construtor.
72 72
73 m_settings = new gui_settings ();
74
75 check_settings (); 73 check_settings ();
76 74
77 m_settings_file = m_settings->fileName (); 75 m_settings_file = settings.fileName ();
78 76
79 QFileInfo sfile (m_settings_file); 77 QFileInfo sfile (m_settings_file);
80 m_settings_directory = sfile.absolutePath (); 78 m_settings_directory = sfile.absolutePath ();
81 } 79 }
82 80
83 resource_manager::~resource_manager (void) 81 resource_manager::~resource_manager (void)
84 { 82 {
85 delete m_settings;
86
87 for (int i = m_temporary_files.count () - 1; i >=0; i--) 83 for (int i = m_temporary_files.count () - 1; i >=0; i--)
88 remove_tmp_file (m_temporary_files.at (i)); 84 remove_tmp_file (m_temporary_files.at (i));
89 } 85 }
90 86
91 QString resource_manager::get_gui_translation_dir (void) 87 QString resource_manager::get_gui_translation_dir (void)
109 QString language = "SYSTEM"; // take system language per default 105 QString language = "SYSTEM"; // take system language per default
110 106
111 // FIXME: can we somehow ensure that the settings object will always 107 // FIXME: can we somehow ensure that the settings object will always
112 // be initialize and valid? 108 // be initialize and valid?
113 109
114 if (m_settings) 110 gui_settings settings;
115 { 111
116 // get the locale from the settings if already available 112 // get the locale from the settings if already available
117 language = m_settings->value (global_language.key, 113 language = settings.value (global_language.key,
118 global_language.def).toString (); 114 global_language.def).toString ();
119 }
120 115
121 // load the translations depending on the settings 116 // load the translations depending on the settings
122 if (language == "SYSTEM") 117 if (language == "SYSTEM")
123 { 118 {
124 // get the system locale and pass it to the translators for loading 119 // get the system locale and pass it to the translators for loading
149 { 144 {
150 m_icon_fallbacks.clear (); 145 m_icon_fallbacks.clear ();
151 146
152 int theme = global_icon_theme_index.def.toInt (); 147 int theme = global_icon_theme_index.def.toInt ();
153 148
154 if (m_settings) 149 gui_settings settings;
155 { 150
156 // check for new and old setting and use old if required 151 // check for new and old setting and use old if required
157 if (! m_settings->contains (global_icon_theme_index.key)) 152 if (! settings.contains (global_icon_theme_index.key))
158 { 153 {
159 // new pref does not exist 154 // new pref does not exist
160 if (m_settings->value (global_icon_theme).toBool ()) 155 if (settings.value (global_icon_theme).toBool ())
161 theme = ICON_THEME_SYSTEM; 156 theme = ICON_THEME_SYSTEM;
162 else 157 else
163 theme = ICON_THEME_OCTAVE; 158 theme = ICON_THEME_OCTAVE;
164 m_settings->setValue (global_icon_theme_index.key, theme); // add new 159 settings.setValue (global_icon_theme_index.key, theme); // add new
165 m_settings->remove (global_icon_theme.key); // remove deprecated key 160 settings.remove (global_icon_theme.key); // remove deprecated key
166 }
167 else
168 {
169 // get new settings
170 theme = m_settings->value (global_icon_theme_index).toInt ();
171 }
172 } 161 }
173 162
174 QIcon::setThemeName (global_all_icon_themes.at (theme)); 163 QIcon::setThemeName (global_all_icon_themes.at (theme));
175 164
176 // set the required fallback search paths 165 // set the required fallback search paths
189 } 178 }
190 179
191 m_icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS); 180 m_icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS);
192 } 181 }
193 182
194 gui_settings * resource_manager::get_settings (void) const
195 {
196 if (! m_settings)
197 {
198 QString msg (QT_TR_NOOP ("Octave has lost its settings.\n"
199 "This should not happen.\n\n"
200 "Please report this bug.\n\n"
201 "Octave GUI must be closed now."));
202
203 QMessageBox::critical (nullptr,
204 QString (QT_TR_NOOP ("Octave Critical Error")),
205 msg);
206 exit (1);
207 }
208
209 return m_settings;
210 }
211
212 QString resource_manager::get_settings_directory (void) 183 QString resource_manager::get_settings_directory (void)
213 { 184 {
214 return m_settings_directory; 185 return m_settings_directory;
215 } 186 }
216 187
315 custom_editor = QString::fromStdString (env_default_editor); 286 custom_editor = QString::fromStdString (env_default_editor);
316 } 287 }
317 288
318 check_settings (); 289 check_settings ();
319 290
291 gui_settings settings;
292
320 // Write some settings that were dynamically determined at first startup 293 // Write some settings that were dynamically determined at first startup
321 if (m_settings) 294
322 { 295 // Custom editor
323 // Custom editor 296 if (! custom_editor.isEmpty ())
324 if (! custom_editor.isEmpty ()) 297 settings.setValue (global_custom_editor.key, custom_editor);
325 m_settings->setValue (global_custom_editor.key, custom_editor); 298
326 299 // Default monospace font for the terminal
327 // Default monospace font for the terminal 300 if (def_font.count () > 1)
328 if (def_font.count () > 1) 301 {
329 { 302 settings.setValue (cs_font.key, def_font[0]);
330 m_settings->setValue (cs_font.key, def_font[0]); 303 settings.setValue (cs_font_size.key, def_font[1].toInt ());
331 m_settings->setValue (cs_font_size.key, def_font[1].toInt ()); 304 }
332 } 305
333 306 // Write the default monospace font into the settings for later use by
334 // Write the default monospace font into the settings for later use by 307 // console and editor as fallbacks of their font preferences.
335 // console and editor as fallbacks of their font preferences. 308 settings.setValue (global_mono_font.key, get_default_font_family ());
336 m_settings->setValue (global_mono_font.key, get_default_font_family ());
337 }
338 } 309 }
339 310
340 #if defined (HAVE_QSCINTILLA) 311 #if defined (HAVE_QSCINTILLA)
341 int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles) 312 int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles)
342 { 313 {
364 return dest; 335 return dest;
365 } 336 }
366 337
367 #if defined (HAVE_QSCINTILLA) 338 #if defined (HAVE_QSCINTILLA)
368 void resource_manager::read_lexer_settings (QsciLexer *lexer, 339 void resource_manager::read_lexer_settings (QsciLexer *lexer,
369 gui_settings *settings,
370 int mode, int def) 340 int mode, int def)
371 { 341 {
342 gui_settings settings;
343
372 // Test whether the settings for lexer is already contained in the 344 // Test whether the settings for lexer is already contained in the
373 // given gui settings file. If yes, load them, if not copy them from the 345 // given gui settings file. If yes, load them, if not copy them from the
374 // default settings file. 346 // default settings file.
375 // This is useful when a new language support is implemented and the 347 // This is useful when a new language support is implemented and the
376 // existing settings file is used (which is of course the common case). 348 // existing settings file is used (which is of course the common case).
378 if (m > 1) 350 if (m > 1)
379 m = 1; 351 m = 1;
380 352
381 QString group ("Scintilla" + settings_color_modes_ext[m]); 353 QString group ("Scintilla" + settings_color_modes_ext[m]);
382 354
383 settings->beginGroup (group); 355 settings.beginGroup (group);
384 settings->beginGroup (lexer->language ()); 356 settings.beginGroup (lexer->language ());
385 357
386 QStringList lexer_keys = settings->allKeys (); 358 QStringList lexer_keys = settings.allKeys ();
387 359
388 settings->endGroup (); 360 settings.endGroup ();
389 settings->endGroup (); 361 settings.endGroup ();
390 362
391 if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0) 363 if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0)
392 { 364 {
393 // We have to reload the default values or no Lexer keys found: 365 // We have to reload the default values or no Lexer keys found:
394 // If mode == 0, take all settings except font from default lexer 366 // If mode == 0, take all settings except font from default lexer
406 int styles[ed_max_lexer_styles]; // array for saving valid styles 378 int styles[ed_max_lexer_styles]; // array for saving valid styles
407 int max_style = get_valid_lexer_styles (lexer, styles); 379 int max_style = get_valid_lexer_styles (lexer, styles);
408 380
409 for (int i = 0; i < max_style; i++) 381 for (int i = 0; i < max_style; i++)
410 { 382 {
411 c = settings->get_color_value (QVariant (lexer->color (styles[i])), m); 383 c = settings.get_color_value (QVariant (lexer->color (styles[i])), m);
412 lexer->setColor (c, styles[i]); 384 lexer->setColor (c, styles[i]);
413 p = settings->get_color_value (QVariant (lexer->paper (styles[i])), m); 385 p = settings.get_color_value (QVariant (lexer->paper (styles[i])), m);
414 lexer->setPaper (p, styles[i]); 386 lexer->setPaper (p, styles[i]);
415 dfa = copy_font_attributes (lexer->font (styles[i]), df); 387 dfa = copy_font_attributes (lexer->font (styles[i]), df);
416 lexer->setFont (dfa, styles[i]); 388 lexer->setFont (dfa, styles[i]);
417 } 389 }
418 // Set defaults last for not changing the defaults of the styles 390 // Set defaults last for not changing the defaults of the styles
421 393
422 // Write settings if not just reload the default values 394 // Write settings if not just reload the default values
423 if (def != settings_reload_default_colors_flag) 395 if (def != settings_reload_default_colors_flag)
424 { 396 {
425 const std::string group_str = group.toStdString (); 397 const std::string group_str = group.toStdString ();
426 lexer->writeSettings (*settings, group_str.c_str ()); 398 lexer->writeSettings (settings, group_str.c_str ());
427 settings->sync (); 399 settings.sync ();
428 } 400 }
429 } 401 }
430 else 402 else
431 { 403 {
432 // Found lexer keys, read the settings 404 // Found lexer keys, read the settings
433 const std::string group_str = group.toStdString (); 405 const std::string group_str = group.toStdString ();
434 lexer->readSettings (*settings, group_str.c_str ()); 406 lexer->readSettings (settings, group_str.c_str ());
435 } 407 }
436 } 408 }
437 #endif 409 #endif
438 410
439 void resource_manager::check_settings (void) 411 void resource_manager::check_settings (void)
440 { 412 {
441 if (m_settings->status () == QSettings::NoError) 413 gui_settings settings;
414
415 if (settings.status () == QSettings::NoError)
442 { 416 {
443 // Test usability (force file to be really created) 417 // Test usability (force file to be really created)
444 m_settings->setValue ("dummy", 0); 418 settings.setValue ("dummy", 0);
445 m_settings->sync (); 419 settings.sync ();
446 } 420 }
447 421
448 if (! (QFile::exists (m_settings->fileName ()) 422 if (! (QFile::exists (settings.fileName ())
449 && m_settings->isWritable () 423 && settings.isWritable ()
450 && m_settings->status () == QSettings::NoError)) 424 && settings.status () == QSettings::NoError))
451 { 425 {
452 QString msg 426 QString msg
453 = QString (QT_TR_NOOP ("The settings file\n%1\n" 427 = QString (QT_TR_NOOP ("The settings file\n%1\n"
454 "does not exist and can not be created.\n" 428 "does not exist and can not be created.\n"
455 "Make sure you have read and write permissions to\n%2\n\n" 429 "Make sure you have read and write permissions to\n%2\n\n"
460 msg.arg (get_settings_file ()).arg (get_settings_directory ())); 434 msg.arg (get_settings_file ()).arg (get_settings_directory ()));
461 435
462 exit (1); 436 exit (1);
463 } 437 }
464 else 438 else
465 m_settings->remove ("dummy"); // Remove test entry 439 settings.remove ("dummy"); // Remove test entry
466 } 440 }
467 441
468 bool resource_manager::update_settings_key (const QString& old_key, 442 bool resource_manager::update_settings_key (const QString& old_key,
469 const QString& new_key) 443 const QString& new_key)
470 { 444 {
471 if (m_settings->contains (old_key)) 445 gui_settings settings;
472 { 446
473 QVariant preference = m_settings->value (old_key); 447 if (settings.contains (old_key))
474 m_settings->setValue (new_key, preference); 448 {
475 m_settings->remove (old_key); 449 QVariant preference = settings.value (old_key);
450 settings.setValue (new_key, preference);
451 settings.remove (old_key);
476 return true; 452 return true;
477 } 453 }
478 454
479 return false; 455 return false;
480 } 456 }
484 return ! QFile::exists (m_settings_file); 460 return ! QFile::exists (m_settings_file);
485 } 461 }
486 462
487 void resource_manager::update_network_settings (void) 463 void resource_manager::update_network_settings (void)
488 { 464 {
489 if (! m_settings)
490 return;
491
492 QNetworkProxy proxy; 465 QNetworkProxy proxy;
493 466
494 // Assume no proxy and empty proxy data 467 // Assume no proxy and empty proxy data
495 QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy; 468 QNetworkProxy::ProxyType proxy_type = QNetworkProxy::NoProxy;
496 QString scheme; 469 QString scheme;
498 int port = 0; 471 int port = 0;
499 QString user; 472 QString user;
500 QString pass; 473 QString pass;
501 QUrl proxy_url = QUrl (); 474 QUrl proxy_url = QUrl ();
502 475
503 if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ()) 476 gui_settings settings;
477
478 if (settings.value (global_use_proxy.key, global_use_proxy.def).toBool ())
504 { 479 {
505 // Use a proxy, collect all required information 480 // Use a proxy, collect all required information
506 QString proxy_type_string 481 QString proxy_type_string
507 = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString (); 482 = settings.value (global_proxy_type.key, global_proxy_type.def).toString ();
508 483
509 // The proxy type for the Qt proxy settings 484 // The proxy type for the Qt proxy settings
510 if (proxy_type_string == "Socks5Proxy") 485 if (proxy_type_string == "Socks5Proxy")
511 proxy_type = QNetworkProxy::Socks5Proxy; 486 proxy_type = QNetworkProxy::Socks5Proxy;
512 else if (proxy_type_string == "HttpProxy") 487 else if (proxy_type_string == "HttpProxy")
514 489
515 // The proxy data from the settings 490 // The proxy data from the settings
516 if (proxy_type_string == "HttpProxy" 491 if (proxy_type_string == "HttpProxy"
517 || proxy_type_string == "Socks5Proxy") 492 || proxy_type_string == "Socks5Proxy")
518 { 493 {
519 host = m_settings->value (global_proxy_host.key, 494 host = settings.value (global_proxy_host.key,
520 global_proxy_host.def).toString (); 495 global_proxy_host.def).toString ();
521 port = m_settings->value (global_proxy_port.key, 496 port = settings.value (global_proxy_port.key,
522 global_proxy_port.def).toInt (); 497 global_proxy_port.def).toInt ();
523 user = m_settings->value (global_proxy_user.key, 498 user = settings.value (global_proxy_user.key,
524 global_proxy_user.def).toString (); 499 global_proxy_user.def).toString ();
525 pass = m_settings->value (global_proxy_pass.key, 500 pass = settings.value (global_proxy_pass.key,
526 global_proxy_pass.def).toString (); 501 global_proxy_pass.def).toString ();
527 if (proxy_type_string == "HttpProxy") 502 if (proxy_type_string == "HttpProxy")
528 scheme = "http"; 503 scheme = "http";
529 else if (proxy_type_string == "Socks5Proxy") 504 else if (proxy_type_string == "Socks5Proxy")
530 scheme = "socks5"; 505 scheme = "socks5";
531 506
660 QString ("SYSTEM (") + 635 QString ("SYSTEM (") +
661 QString (octave_locale_charset_wrapper ()).toUpper () + QString (")"); 636 QString (octave_locale_charset_wrapper ()).toUpper () + QString (")");
662 637
663 if (enc.isEmpty ()) 638 if (enc.isEmpty ())
664 { 639 {
665 enc = m_settings->value (ed_default_enc).toString (); 640 gui_settings settings;
641
642 enc = settings.value (ed_default_enc).toString ();
666 643
667 if (enc.isEmpty ()) // still empty? 644 if (enc.isEmpty ()) // still empty?
668 { 645 {
669 if (default_exists) 646 if (default_exists)
670 enc = ed_default_enc.def.toString (); 647 enc = ed_default_enc.def.toString ();