Mercurial > octave
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 (); |