Audacity 3.2.0
Prefs.h
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 Prefs.h
6
7 Dominic Mazzoni
8 Markus Meyer
9
10 Audacity uses wxWidgets' wxFileConfig class to handle preferences.
11 In Audacity versions prior to 1.3.1, it used wxConfig, which would
12 store the prefs in a platform-dependent way (e.g. in the registry
13 on Windows). Now it always stores the settings in a configuration file
14 in the Audacity Data Directory.
15
16 Every time we read a preference, we need to specify the default
17 value for that preference, to be used if the preference hasn't
18 been set before.
19
20 So, to avoid code duplication, we provide functions in this file
21 to read and write preferences which have a nonobvious default
22 value, so that if we later want to change this value, we only
23 have to change it in one place.
24
25 See Prefs.cpp for a (complete?) list of preferences we keep
26 track of...
27
28**********************************************************************/
29#ifndef __AUDACITY_PREFS__
30#define __AUDACITY_PREFS__
31
32#include <functional>
33#include <set>
34#include <vector>
35
36// Increment this every time the prefs need to be reset
37// the first part (before the r) indicates the version the reset took place
38// the second part (after the r) indicates the number of times the prefs have been reset within the same version
39#define AUDACITY_PREFS_VERSION_STRING "1.1.1r1"
40
41#include <functional>
42
44#include "wxArrayStringEx.h"
45#include "FileConfig.h"
46
47#include <memory>
48
49class wxFileName;
50
51PREFERENCES_API void InitPreferences( std::unique_ptr<FileConfig> uPrefs );
53
57PREFERENCES_API void ResetPreferences();
58PREFERENCES_API void FinishPreferences();
59
60extern PREFERENCES_API FileConfig *gPrefs;
61extern int gMenusDirty;
62
63
64struct ByColumns_t{};
65extern PREFERENCES_API ByColumns_t ByColumns;
66
69 operator const RegistryPath &() const { return mPath; }
70};
71
73/* The constructors are non-explicit for convenience */
74class PREFERENCES_API SettingBase
75{
76public:
77 SettingBase( const char *path ) : mPath{ path } {}
78 SettingBase( const wxChar *path ) : mPath{ path } {}
79 SettingBase( const wxString &path ) : mPath{ path } {}
80
81 wxConfigBase *GetConfig() const;
82
83 const SettingPath &GetPath() const { return mPath; }
84
86 bool Delete();
87
88protected:
89 SettingBase( const SettingBase& ) = default;
91};
92
94{
95public:
97
98 virtual void Invalidate() = 0;
99
100protected:
101 // Methods below should only be callable
102 // from within a transaction.
103 friend class SettingTransaction;
104 friend class SettingScope;
105
106 virtual void EnterTransaction(size_t depth) = 0;
108 virtual bool Commit() = 0;
109 virtual void Rollback() noexcept = 0;
110};
111
113
114class PREFERENCES_API SettingScope /* not final */
115{
116public:
117 SettingScope();
118 ~SettingScope() noexcept;
119 SettingScope(const SettingScope&) = delete;
121
129 static AddResult Add( TransactionalSettingBase& setting );
130
131protected:
132 std::set< TransactionalSettingBase * > mPending;
133 bool mCommitted = false;
134};
135
137
143class PREFERENCES_API SettingTransaction final : public SettingScope
144{
145public:
147
149 bool Commit();
150};
151
155template< typename T >
157{
158public:
159 using TransactionalSettingBase::TransactionalSettingBase;
160 explicit CachingSettingBase( const SettingBase &path )
161 : TransactionalSettingBase{ path.GetPath() } {}
162
163protected:
165 mutable T mCurrentValue{};
166 mutable bool mValid{false};
167};
168
171template< typename T >
172class Setting : public CachingSettingBase< T >
173{
174public:
176
177 using DefaultValueFunction = std::function< T() >;
178
180 Setting( const SettingBase &path, const T &defaultValue )
181 : CachingSettingBase< T >{ path }
182 , mDefaultValue{ defaultValue }
183 {}
184
186 Setting( const SettingBase &path, DefaultValueFunction function )
187 : CachingSettingBase< T >{ path }
188 , mFunction{ function }
189 {}
190
191
192 const T& GetDefault() const
193 {
194 if ( mFunction )
195 mDefaultValue = mFunction();
196 return mDefaultValue;
197 }
198
200 bool Read( T *pVar ) const
201 {
202 return ReadWithDefault( pVar, GetDefault() );
203 }
204
206 bool ReadWithDefault( T *pVar, const T& defaultValue ) const
207 {
208 if ( pVar )
209 *pVar = defaultValue;
210 if ( pVar && this->mValid ) {
211 *pVar = this->mCurrentValue;
212 return true;
213 }
214 const auto config = this->GetConfig();
215 if ( pVar && config ) {
216 if ((this->mValid = config->Read( this->mPath, &this->mCurrentValue )))
217 *pVar = this->mCurrentValue;
218 return this->mValid;
219 }
220 return (this->mValid = false);
221 }
222
224
226 T Read() const
227 {
228 return ReadWithDefault( GetDefault() );
229 }
230
232
234 T ReadWithDefault( const T &defaultValue ) const
235 {
236 if (this->mValid)
237 return this->mCurrentValue;
238 const auto config = this->GetConfig();
239 if (config) {
240 this->mCurrentValue =
241 config->ReadObject(this->mPath, defaultValue);
242 // If config file contains a value that agrees with the default, we
243 // can't detect that, so assume invalidity still
244 this->mValid = (this->mCurrentValue != defaultValue);
245 return this->mCurrentValue;
246 }
247 else
248 return T{};
249 }
250
252 bool Write( const T &value )
253 {
254 const auto config = this->GetConfig();
255
256 if (config == nullptr)
257 return false;
258
259 switch ( SettingScope::Add( *this ) ) {
260 // Eager writes, but not flushed, when there is no transaction
261 default:
263 this->mCurrentValue = value;
264 return DoWrite();
265 }
266
267 // Deferred writes, with flush, if there is a commit later
270 this->mCurrentValue = value;
271 this->mValid = true;
272 return true;
273 }
274 }
275
277 bool Reset()
278 {
279 return Write( GetDefault() );
280 }
281
282 void Invalidate() override
283 {
284 this->mValid = false;
285 }
286
287private:
288 void EnterTransaction(size_t depth) override
289 {
290 const T value = Read();
291
292 for (size_t i = mPreviousValues.size(); i < depth; ++i)
293 this->mPreviousValues.emplace_back( value );
294 }
295
296 bool Commit() override
297 {
298 // This can be only called from within the transaction
299 assert(!this->mPreviousValues.empty());
300
301 if (this->mPreviousValues.empty())
302 return false;
303
304 const auto result = this->mPreviousValues.size() > 1 || DoWrite();
305 mPreviousValues.pop_back();
306
307 return result;
308 }
309
310 void Rollback() noexcept override
311 {
312 // This can be only called from within the transaction
313 assert(!this->mPreviousValues.empty());
314
315 if (!this->mPreviousValues.empty())
316 {
317 this->mCurrentValue = std::move(this->mPreviousValues.back());
318 this->mPreviousValues.pop_back();
319 }
320 }
321
322protected:
324
325 bool DoWrite( )
326 {
327 const auto config = this->GetConfig();
328 return this->mValid =
329 config ? config->Write( this->mPath, this->mCurrentValue ) : false;
330 }
331
333 mutable T mDefaultValue{};
334 std::vector<T> mPreviousValues;
335};
336
338class PREFERENCES_API BoolSetting final : public Setting< bool >
339{
340public:
341 using Setting::Setting;
342
344 bool Toggle();
345};
346
348class IntSetting final : public Setting< int >
349{
350public:
351 using Setting::Setting;
352};
353
355class DoubleSetting final : public Setting< double >
356{
357public:
358 using Setting::Setting;
359};
360
362class StringSetting final : public Setting< wxString >
363{
364public:
365 using Setting::Setting;
366};
367
369
373class PREFERENCES_API EnumValueSymbols : public std::vector< EnumValueSymbol >
374{
375public:
376 EnumValueSymbols() = default;
377 EnumValueSymbols( std::initializer_list<EnumValueSymbol> symbols )
378 : vector( symbols )
379 {}
380 EnumValueSymbols( std::vector< EnumValueSymbol > symbols )
381 : vector( symbols )
382 {}
383
384 // columnwise constructor; arguments must have same size
385 // (Implicit constructor takes initial tag argument to avoid unintended
386 // overload resolution to the inherited constructor taking
387 // initializer_list, in the case that each column has exactly two strings)
390 const TranslatableStrings &msgids,
391 wxArrayStringEx internals
392 );
393
394 const TranslatableStrings &GetMsgids() const;
395 const wxArrayStringEx &GetInternals() const;
396
397private:
400};
401
404class PREFERENCES_API ChoiceSetting
405{
406public:
409 ChoiceSetting(const SettingPath &, EnumValueSymbols, long = -1) = delete;
410
413 long defaultSymbol = -1)
414 : mKey{ key.GetPath() }
415 , mSymbols{ move(symbols) }
416 , mpOtherSettings{ &key }
417 , mDefaultSymbol{ defaultSymbol }
418 {
419 assert(defaultSymbol < static_cast<long>(mSymbols.size()));
420 }
421
424 long defaultSymbol = -1)
425 : mKey{ key.GetPath() }
426 , mSymbols{ move(symbols) }
427 , mDefaultSymbol{ defaultSymbol }
428 {
429 assert(defaultSymbol < static_cast<long>(mSymbols.size()));
430 }
431
432 const wxString &Key() const { return mKey; }
433 const EnumValueSymbol &Default() const;
434 const EnumValueSymbols &GetSymbols() const { return mSymbols; }
435
436 wxString Read() const;
437
438 // new direct use is discouraged but it may be needed in legacy code:
439 // use a default in case the preference is not defined, which may not be
440 // the default-default stored in this object.
441 wxString ReadWithDefault( const wxString & ) const;
442
443 bool Write( const wxString &value ); // you flush gPrefs afterward
444
446 void SetDefault( long value );
447
448protected:
449 size_t Find( const wxString &value ) const;
450 virtual void Migrate( wxString& );
451
452 const wxString mKey;
454 TransactionalSettingBase *const mpOtherSettings{};
455
456 // stores an internal value
457 mutable bool mMigrated { false };
458
460};
461
466class PREFERENCES_API EnumSettingBase : public ChoiceSetting {
467public:
469 template<typename Key>
471 Key &&key, // moved string, or lvalue reference to another Setting
472 EnumValueSymbols symbols,
473 long defaultSymbol,
474
475 std::vector<int> intValues, // must have same size as symbols
476 const wxString &oldKey = {}
477 ) : ChoiceSetting{ std::forward<Key>(key), move(symbols), defaultSymbol }
478 , mIntValues{ move(intValues) }
479 , mOldKey{ oldKey }
480 {
481 assert (mIntValues.size() == mSymbols.size());
482 }
483
484protected:
485
486 // Read and write the encoded values
487 int ReadInt() const;
488
489 // new direct use is discouraged but it may be needed in legacy code:
490 // use a default in case the preference is not defined, which may not be
491 // the default-default stored in this object.
492 int ReadIntWithDefault( int defaultValue ) const;
493
494 bool WriteInt( int code ); // you flush gPrefs afterward
495
496 size_t FindInt( int code ) const;
497 void Migrate( wxString& ) override;
498
499private:
500 std::vector<int> mIntValues;
501 const wxString mOldKey;
502};
503
505template< typename Enum >
507{
508public:
509
511 template<typename Key>
513 Key &&key, // moved string, or lvalue reference to another Setting
514 EnumValueSymbols symbols,
515 long defaultSymbol,
516
517 std::vector< Enum > values, // must have same size as symbols
518 const wxString &oldKey = {}
519 )
521 std::forward<Key>(key), move(symbols), defaultSymbol,
522 ConvertValues(values), oldKey
523 }
524 {}
525
526 // Wrap ReadInt() and ReadIntWithDefault() and WriteInt()
527 Enum ReadEnum() const
528 { return static_cast<Enum>( ReadInt() ); }
529
530 // new direct use is discouraged but it may be needed in legacy code:
531 // use a default in case the preference is not defined, which may not be
532 // the default-default stored in this object.
533 Enum ReadEnumWithDefault( Enum defaultValue ) const
534 {
535 auto integer = static_cast<int>(defaultValue);
536 return static_cast<Enum>( ReadIntWithDefault( integer ) );
537 }
538
539 bool WriteEnum( Enum value )
540 { return WriteInt( static_cast<int>( value ) ); }
541
542private:
543 std::vector<int> ConvertValues( const std::vector< Enum > &values)
544 {
545 // To convert scoped enums. This would be easier with std::ranges
546 std::vector<int> result;
547 result.reserve(values.size());
548 for (auto value : values)
549 result.push_back(static_cast<int>(value));
550 return result;
551 }
552};
553
555class PREFERENCES_API PrefsListener
556{
557public:
559
566 static void Broadcast(int id = 0);
567
569 virtual ~PrefsListener();
570
571 // Called when all preferences should be updated.
572 // PrefsListener::UpdatePrefs() is defined, and does nothing
573 virtual void UpdatePrefs() = 0;
574
575protected:
576 // Called when only selected preferences are to be updated.
577 // id is some value generated by wxNewId() that identifies the portion
578 // of preferences.
579 // Default function does nothing.
580 virtual void UpdateSelectedPrefs( int id );
581
582private:
583 struct Impl;
584 std::unique_ptr<Impl> mpImpl;
585};
586
590PREFERENCES_API
591wxString WarningDialogKey(const wxString &internalDialogName);
592
597struct PREFERENCES_API PreferenceInitializer {
599 virtual ~PreferenceInitializer();
600 virtual void operator () () = 0;
601
602 static void ReinitializeAll();
603};
604
605// Special extra-sticky settings
606extern PREFERENCES_API BoolSetting DefaultUpdatesCheckingFlag;
607
608#endif
static const AudacityProject::AttachedObjects::RegisteredFactory key
const wxChar * values
wxString RegistryPath
Definition: Identifier.h:218
gPrefs Read(wxT("/GUI/VerticalZooming"), &bVZoom, false)
PREFERENCES_API void InitPreferences(std::unique_ptr< FileConfig > uPrefs)
Definition: Prefs.cpp:200
PREFERENCES_API BoolSetting DefaultUpdatesCheckingFlag
Definition: Prefs.cpp:65
PREFERENCES_API FileConfig * gPrefs
Definition: Prefs.cpp:70
PREFERENCES_API wxString WarningDialogKey(const wxString &internalDialogName)
Definition: Prefs.cpp:469
PREFERENCES_API void FinishPreferences()
Definition: Prefs.cpp:227
PREFERENCES_API void ResetPreferences()
Call this to reset preferences to an (almost)-"new" default state.
Definition: Prefs.cpp:208
PREFERENCES_API ByColumns_t ByColumns
Definition: Prefs.cpp:474
int gMenusDirty
Definition: Prefs.cpp:71
std::vector< TranslatableString > TranslatableStrings
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:339
Class template adds an in-memory cache of a value to TransactionalSettingBase and support for Setting...
Definition: Prefs.h:157
CachingSettingBase(const CachingSettingBase &)=default
CachingSettingBase(const SettingBase &path)
Definition: Prefs.h:160
const wxString & Key() const
Definition: Prefs.h:432
const wxString mKey
Definition: Prefs.h:452
ChoiceSetting(const SettingBase &key, EnumValueSymbols symbols, long defaultSymbol=-1)
Definition: Prefs.h:423
const EnumValueSymbols mSymbols
Definition: Prefs.h:453
ChoiceSetting(const SettingPath &, EnumValueSymbols, long=-1)=delete
const EnumValueSymbols & GetSymbols() const
Definition: Prefs.h:434
long mDefaultSymbol
Definition: Prefs.h:459
ChoiceSetting(TransactionalSettingBase &key, EnumValueSymbols symbols, long defaultSymbol=-1)
Definition: Prefs.h:412
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Specialization of Setting for double.
Definition: Prefs.h:356
const wxString mOldKey
Definition: Prefs.h:501
std::vector< int > mIntValues
Definition: Prefs.h:500
EnumSettingBase(Key &&key, EnumValueSymbols symbols, long defaultSymbol, std::vector< int > intValues, const wxString &oldKey={})
Definition: Prefs.h:470
Adapts EnumSettingBase to a particular enumeration type.
Definition: Prefs.h:507
std::vector< int > ConvertValues(const std::vector< Enum > &values)
Definition: Prefs.h:543
bool WriteEnum(Enum value)
Definition: Prefs.h:539
EnumSetting(Key &&key, EnumValueSymbols symbols, long defaultSymbol, std::vector< Enum > values, const wxString &oldKey={})
Definition: Prefs.h:512
Enum ReadEnumWithDefault(Enum defaultValue) const
Definition: Prefs.h:533
Enum ReadEnum() const
Definition: Prefs.h:527
EnumValueSymbols()=default
wxArrayStringEx mInternals
Definition: Prefs.h:399
EnumValueSymbols(std::vector< EnumValueSymbol > symbols)
Definition: Prefs.h:380
EnumValueSymbols(std::initializer_list< EnumValueSymbol > symbols)
Definition: Prefs.h:377
TranslatableStrings mMsgids
Definition: Prefs.h:398
Specialization of Setting for int.
Definition: Prefs.h:349
A listener notified of changes in preferences.
Definition: Prefs.h:556
std::unique_ptr< Impl > mpImpl
Definition: Prefs.h:583
Base class for settings objects. It holds a configuration key path.
Definition: Prefs.h:75
SettingBase(const wxChar *path)
Definition: Prefs.h:78
SettingBase(const wxString &path)
Definition: Prefs.h:79
SettingBase(const char *path)
Definition: Prefs.h:77
SettingBase(const SettingBase &)=default
wxConfigBase * GetConfig() const
Definition: Prefs.cpp:503
const SettingPath & GetPath() const
Definition: Prefs.h:83
const SettingPath mPath
Definition: Prefs.h:90
Definition: Prefs.h:173
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:252
T Read() const
overload of Read, always returning a value
Definition: Prefs.h:226
Setting(const SettingBase &path, const T &defaultValue)
Usual overload supplies a default value.
Definition: Prefs.h:180
T ReadWithDefault(const T &defaultValue) const
new direct use is discouraged but it may be needed in legacy code
Definition: Prefs.h:234
void EnterTransaction(size_t depth) override
Definition: Prefs.h:288
void Invalidate() override
Definition: Prefs.h:282
bool ReadWithDefault(T *pVar, const T &defaultValue) const
overload of ReadWithDefault returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:206
void Rollback() noexcept override
Definition: Prefs.h:310
bool Reset()
Reset to the default value.
Definition: Prefs.h:277
bool DoWrite()
Write cached value to config and return true if successful.
Definition: Prefs.h:325
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:200
std::function< T() > DefaultValueFunction
Definition: Prefs.h:177
std::vector< T > mPreviousValues
Definition: Prefs.h:334
const T & GetDefault() const
Definition: Prefs.h:192
Setting(const SettingBase &path, DefaultValueFunction function)
This overload causes recomputation of the default each time it is needed.
Definition: Prefs.h:186
bool Commit() override
Definition: Prefs.h:296
const DefaultValueFunction mFunction
Definition: Prefs.h:332
Makes temporary changes to preferences, then rolls them back at destruction.
Definition: Prefs.h:115
bool mCommitted
Definition: Prefs.h:133
static AddResult Add(TransactionalSettingBase &setting)
Definition: Prefs.cpp:263
SettingScope(const SettingScope &)=delete
~SettingScope() noexcept
Definition: Prefs.cpp:246
SettingScope & operator=(const SettingScope &)=delete
@ NotAdded
Definition: Prefs.h:128
@ PreviouslyAdded
Definition: Prefs.h:128
std::set< TransactionalSettingBase * > mPending
Definition: Prefs.h:132
Extend SettingScope with Commit() which flushes updates in a batch.
Definition: Prefs.h:144
Specialization of Setting for strings.
Definition: Prefs.h:363
friend class SettingScope
Definition: Prefs.h:104
virtual void Rollback() noexcept=0
virtual void EnterTransaction(size_t depth)=0
virtual void Invalidate()=0
virtual bool Commit()=0
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
PROJECT_FILE_IO_API void Add(const FilePath &path)
PROJECT_FILE_IO_API wxString Find(const FilePath &path)
NumericFormatSymbol Default(const NumericConverterType &type)
Returns the default format for the type or empty symbol, if no default symbol is registered.
bool GetConfig(const EffectDefinitionInterface &ident, ConfigurationType type, const RegistryPath &group, const RegistryPath &key, Value &var, const Value &defval)
AUDACITY_DLL_API void UpdatePrefs(wxWindow *pParent)
RegistryPath mPath
Definition: Prefs.h:68