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
46#include <wx/filename.h>
47#include <wx/textfile.h>
48
49#include "GlobalVariable.h"
50
51#include "BasicSettings.h"
52
53
54PREFERENCES_API void InitPreferences( std::unique_ptr<audacity::BasicSettings> uPrefs );
55PREFERENCES_API void GetPreferencesVersion(int& vMajor, int& vMinor, int& vMicro);
56PREFERENCES_API void SetPreferencesVersion(int vMajor, int vMinor, int vMicor);
58
62PREFERENCES_API void ResetPreferences();
63PREFERENCES_API void FinishPreferences();
64
65extern PREFERENCES_API audacity::BasicSettings *gPrefs;
66extern int gMenusDirty;
67
68
69struct ByColumns_t{};
70extern PREFERENCES_API ByColumns_t ByColumns;
71
74 operator const RegistryPath &() const { return mPath; }
75};
76
78/* The constructors are non-explicit for convenience */
79class PREFERENCES_API SettingBase
80{
81public:
82 SettingBase( const char *path ) : mPath{ path } {}
83 SettingBase( const wxChar *path ) : mPath{ path } {}
84 SettingBase( const wxString &path ) : mPath{ path } {}
85
87
88 const SettingPath &GetPath() const { return mPath; }
89
91 bool Delete();
92
93protected:
94 SettingBase( const SettingBase& ) = default;
96};
97
99{
100public:
102
103 virtual void Invalidate() = 0;
104
105protected:
106 // Methods below should only be callable
107 // from within a transaction.
108 friend class SettingTransaction;
109 friend class SettingScope;
110
111 virtual void EnterTransaction(size_t depth) = 0;
113 virtual bool Commit() = 0;
114 virtual void Rollback() noexcept = 0;
115};
116
118
119class PREFERENCES_API SettingScope /* not final */
120{
121public:
122 SettingScope();
123 ~SettingScope() noexcept;
124 SettingScope(const SettingScope&) = delete;
126
134 static AddResult Add( TransactionalSettingBase& setting );
135
136protected:
137 std::set< TransactionalSettingBase * > mPending;
138 bool mCommitted = false;
139};
140
142
148class PREFERENCES_API SettingTransaction final : public SettingScope
149{
150public:
152
154 bool Commit();
155};
156
160template< typename T >
162{
163public:
164 using TransactionalSettingBase::TransactionalSettingBase;
165 explicit CachingSettingBase( const SettingBase &path )
166 : TransactionalSettingBase{ path.GetPath() } {}
167
168protected:
170 mutable T mCurrentValue{};
171 mutable bool mValid{false};
172};
173
176template< typename T >
177class Setting : public CachingSettingBase< T >
178{
179public:
181
182 using DefaultValueFunction = std::function< T() >;
183
185 Setting( const SettingBase &path, const T &defaultValue )
186 : CachingSettingBase< T >{ path }
187 , mDefaultValue{ defaultValue }
188 {}
189
191 Setting( const SettingBase &path, DefaultValueFunction function )
192 : CachingSettingBase< T >{ path }
193 , mFunction{ function }
194 {}
195
196
197 const T& GetDefault() const
198 {
199 if ( mFunction )
200 mDefaultValue = mFunction();
201 return mDefaultValue;
202 }
203
205 bool Read( T *pVar ) const
206 {
207 return ReadWithDefault( pVar, GetDefault() );
208 }
209
211 bool ReadWithDefault( T *pVar, const T& defaultValue ) const
212 {
213 if ( pVar )
214 *pVar = defaultValue;
215 if ( pVar && this->mValid ) {
216 *pVar = this->mCurrentValue;
217 return true;
218 }
219 const auto config = this->GetConfig();
220 if ( pVar && config ) {
221 if ((this->mValid = config->Read( this->mPath, &this->mCurrentValue )))
222 *pVar = this->mCurrentValue;
223 return this->mValid;
224 }
225 return (this->mValid = false);
226 }
227
229
231 T Read() const
232 {
233 return ReadWithDefault( GetDefault() );
234 }
235
237
239 T ReadWithDefault( const T &defaultValue ) const
240 {
241 if (this->mValid)
242 return this->mCurrentValue;
243 const auto config = this->GetConfig();
244 if (config) {
245 this->mCurrentValue =
246 config->ReadObject(this->mPath, defaultValue);
247 // If config file contains a value that agrees with the default, we
248 // can't detect that, so assume invalidity still
249 this->mValid = (this->mCurrentValue != defaultValue);
250 return this->mCurrentValue;
251 }
252 else
253 return T{};
254 }
255
257 bool Write( const T &value )
258 {
259 const auto config = this->GetConfig();
260
261 if (config == nullptr)
262 return false;
263
264 switch ( SettingScope::Add( *this ) ) {
265 // Eager writes, but not flushed, when there is no transaction
266 default:
268 this->mCurrentValue = value;
269 return DoWrite();
270 }
271
272 // Deferred writes, with flush, if there is a commit later
275 this->mCurrentValue = value;
276 this->mValid = true;
277 return true;
278 }
279 }
280
282 bool Reset()
283 {
284 return Write( GetDefault() );
285 }
286
287 void Invalidate() override
288 {
289 this->mValid = false;
290 }
291
292private:
293 void EnterTransaction(size_t depth) override
294 {
295 const T value = Read();
296
297 for (size_t i = mPreviousValues.size(); i < depth; ++i)
298 this->mPreviousValues.emplace_back( value );
299 }
300
301 bool Commit() override
302 {
303 // This can be only called from within the transaction
304 assert(!this->mPreviousValues.empty());
305
306 if (this->mPreviousValues.empty())
307 return false;
308
309 const auto result = this->mPreviousValues.size() > 1 || DoWrite();
310 mPreviousValues.pop_back();
311
312 return result;
313 }
314
315 void Rollback() noexcept override
316 {
317 // This can be only called from within the transaction
318 assert(!this->mPreviousValues.empty());
319
320 if (!this->mPreviousValues.empty())
321 {
322 this->mCurrentValue = std::move(this->mPreviousValues.back());
323 this->mPreviousValues.pop_back();
324 }
325 }
326
327protected:
329
330 bool DoWrite( )
331 {
332 const auto config = this->GetConfig();
333 return this->mValid =
334 config ? config->Write( this->mPath, this->mCurrentValue ) : false;
335 }
336
338 mutable T mDefaultValue{};
339 std::vector<T> mPreviousValues;
340};
341
343class PREFERENCES_API BoolSetting final : public Setting< bool >
344{
345public:
346 using Setting::Setting;
347
349 bool Toggle();
350};
351
353class IntSetting final : public Setting< int >
354{
355public:
356 using Setting::Setting;
357};
358
360class DoubleSetting final : public Setting< double >
361{
362public:
363 using Setting::Setting;
364};
365
367class StringSetting final : public Setting< wxString >
368{
369public:
370 using Setting::Setting;
371};
372
374
378class PREFERENCES_API EnumValueSymbols : public std::vector< EnumValueSymbol >
379{
380public:
381 EnumValueSymbols() = default;
382 EnumValueSymbols( std::initializer_list<EnumValueSymbol> symbols )
383 : vector( symbols )
384 {}
385 EnumValueSymbols( std::vector< EnumValueSymbol > symbols )
386 : vector( symbols )
387 {}
388
389 // columnwise constructor; arguments must have same size
390 // (Implicit constructor takes initial tag argument to avoid unintended
391 // overload resolution to the inherited constructor taking
392 // initializer_list, in the case that each column has exactly two strings)
395 const TranslatableStrings &msgids,
396 wxArrayStringEx internals
397 );
398
399 const TranslatableStrings &GetMsgids() const;
400 const wxArrayStringEx &GetInternals() const;
401
402private:
405};
406
409class PREFERENCES_API ChoiceSetting
410{
411public:
414 ChoiceSetting(const SettingPath &, EnumValueSymbols, long = -1) = delete;
415
418 long defaultSymbol = -1)
419 : mKey{ key.GetPath() }
420 , mSymbols{ move(symbols) }
421 , mpOtherSettings{ &key }
422 , mDefaultSymbol{ defaultSymbol }
423 {
424 assert(defaultSymbol < static_cast<long>(mSymbols.size()));
425 }
426
429 long defaultSymbol = -1)
430 : mKey{ key.GetPath() }
431 , mSymbols{ move(symbols) }
432 , mDefaultSymbol{ defaultSymbol }
433 {
434 assert(defaultSymbol < static_cast<long>(mSymbols.size()));
435 }
436
437 const wxString &Key() const { return mKey; }
438 const EnumValueSymbol &Default() const;
439 const EnumValueSymbols &GetSymbols() const { return mSymbols; }
440
441 wxString Read() const;
442
443 // new direct use is discouraged but it may be needed in legacy code:
444 // use a default in case the preference is not defined, which may not be
445 // the default-default stored in this object.
446 wxString ReadWithDefault( const wxString & ) const;
447
448 bool Write( const wxString &value ); // you flush gPrefs afterward
449
451 void SetDefault( long value );
452
453protected:
454 size_t Find( const wxString &value ) const;
455 virtual void Migrate( wxString& );
456
457 const wxString mKey;
459 TransactionalSettingBase *const mpOtherSettings{};
460
461 // stores an internal value
462 mutable bool mMigrated { false };
463
465};
466
471class PREFERENCES_API EnumSettingBase : public ChoiceSetting {
472public:
474 template<typename Key>
476 Key &&key, // moved string, or lvalue reference to another Setting
477 EnumValueSymbols symbols,
478 long defaultSymbol,
479
480 std::vector<int> intValues, // must have same size as symbols
481 const wxString &oldKey = {}
482 ) : ChoiceSetting{ std::forward<Key>(key), move(symbols), defaultSymbol }
483 , mIntValues{ move(intValues) }
484 , mOldKey{ oldKey }
485 {
486 assert (mIntValues.size() == mSymbols.size());
487 }
488
489protected:
490
491 // Read and write the encoded values
492 int ReadInt() const;
493
494 // new direct use is discouraged but it may be needed in legacy code:
495 // use a default in case the preference is not defined, which may not be
496 // the default-default stored in this object.
497 int ReadIntWithDefault( int defaultValue ) const;
498
499 bool WriteInt( int code ); // you flush gPrefs afterward
500
501 size_t FindInt( int code ) const;
502 void Migrate( wxString& ) override;
503
504private:
505 std::vector<int> mIntValues;
506 const wxString mOldKey;
507};
508
510template< typename Enum >
512{
513public:
514
516 template<typename Key>
518 Key &&key, // moved string, or lvalue reference to another Setting
519 EnumValueSymbols symbols,
520 long defaultSymbol,
521
522 std::vector< Enum > values, // must have same size as symbols
523 const wxString &oldKey = {}
524 )
526 std::forward<Key>(key), move(symbols), defaultSymbol,
527 ConvertValues(values), oldKey
528 }
529 {}
530
531 // Wrap ReadInt() and ReadIntWithDefault() and WriteInt()
532 Enum ReadEnum() const
533 { return static_cast<Enum>( ReadInt() ); }
534
535 // new direct use is discouraged but it may be needed in legacy code:
536 // use a default in case the preference is not defined, which may not be
537 // the default-default stored in this object.
538 Enum ReadEnumWithDefault( Enum defaultValue ) const
539 {
540 auto integer = static_cast<int>(defaultValue);
541 return static_cast<Enum>( ReadIntWithDefault( integer ) );
542 }
543
544 bool WriteEnum( Enum value )
545 { return WriteInt( static_cast<int>( value ) ); }
546
547private:
548 std::vector<int> ConvertValues( const std::vector< Enum > &values)
549 {
550 // To convert scoped enums. This would be easier with std::ranges
551 std::vector<int> result;
552 result.reserve(values.size());
553 for (auto value : values)
554 result.push_back(static_cast<int>(value));
555 return result;
556 }
557};
558
560class PREFERENCES_API PrefsListener
561{
562public:
564
571 static void Broadcast(int id = 0);
572
574 virtual ~PrefsListener();
575
576 // Called when all preferences should be updated.
577 // PrefsListener::UpdatePrefs() is defined, and does nothing
578 virtual void UpdatePrefs() = 0;
579
580protected:
581 // Called when only selected preferences are to be updated.
582 // id is some value generated by wxNewId() that identifies the portion
583 // of preferences.
584 // Default function does nothing.
585 virtual void UpdateSelectedPrefs( int id );
586
587private:
588 struct Impl;
589 std::unique_ptr<Impl> mpImpl;
590};
591
595PREFERENCES_API
596wxString WarningDialogKey(const wxString &internalDialogName);
597
602struct PREFERENCES_API PreferenceInitializer {
604 virtual ~PreferenceInitializer();
605 virtual void operator () () = 0;
606
607 static void ReinitializeAll();
608};
609
610// Special extra-sticky settings
611extern PREFERENCES_API BoolSetting DefaultUpdatesCheckingFlag;
612
613#endif
const wxChar * values
wxString RegistryPath
Definition: Identifier.h:218
static const AudacityProject::AttachedObjects::RegisteredFactory key
gPrefs Read(wxT("/GUI/VerticalZooming"), &bVZoom, false)
PREFERENCES_API BoolSetting DefaultUpdatesCheckingFlag
Definition: Prefs.cpp:63
PREFERENCES_API void GetPreferencesVersion(int &vMajor, int &vMinor, int &vMicro)
Definition: Prefs.cpp:210
PREFERENCES_API wxString WarningDialogKey(const wxString &internalDialogName)
Definition: Prefs.cpp:484
PREFERENCES_API void SetPreferencesVersion(int vMajor, int vMinor, int vMicor)
Definition: Prefs.cpp:217
PREFERENCES_API void FinishPreferences()
Definition: Prefs.cpp:243
PREFERENCES_API void ResetPreferences()
Call this to reset preferences to an (almost)-"new" default state.
Definition: Prefs.cpp:224
PREFERENCES_API ByColumns_t ByColumns
Definition: Prefs.cpp:489
PREFERENCES_API void InitPreferences(std::unique_ptr< audacity::BasicSettings > uPrefs)
Definition: Prefs.cpp:202
int gMenusDirty
Definition: Prefs.cpp:69
PREFERENCES_API audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
std::vector< TranslatableString > TranslatableStrings
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:344
Class template adds an in-memory cache of a value to TransactionalSettingBase and support for Setting...
Definition: Prefs.h:162
CachingSettingBase(const CachingSettingBase &)=default
CachingSettingBase(const SettingBase &path)
Definition: Prefs.h:165
const wxString & Key() const
Definition: Prefs.h:437
const wxString mKey
Definition: Prefs.h:457
ChoiceSetting(const SettingBase &key, EnumValueSymbols symbols, long defaultSymbol=-1)
Definition: Prefs.h:428
const EnumValueSymbols mSymbols
Definition: Prefs.h:458
ChoiceSetting(const SettingPath &, EnumValueSymbols, long=-1)=delete
const EnumValueSymbols & GetSymbols() const
Definition: Prefs.h:439
long mDefaultSymbol
Definition: Prefs.h:464
ChoiceSetting(TransactionalSettingBase &key, EnumValueSymbols symbols, long defaultSymbol=-1)
Definition: Prefs.h:417
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Specialization of Setting for double.
Definition: Prefs.h:361
const wxString mOldKey
Definition: Prefs.h:506
std::vector< int > mIntValues
Definition: Prefs.h:505
EnumSettingBase(Key &&key, EnumValueSymbols symbols, long defaultSymbol, std::vector< int > intValues, const wxString &oldKey={})
Definition: Prefs.h:475
Adapts EnumSettingBase to a particular enumeration type.
Definition: Prefs.h:512
std::vector< int > ConvertValues(const std::vector< Enum > &values)
Definition: Prefs.h:548
bool WriteEnum(Enum value)
Definition: Prefs.h:544
EnumSetting(Key &&key, EnumValueSymbols symbols, long defaultSymbol, std::vector< Enum > values, const wxString &oldKey={})
Definition: Prefs.h:517
Enum ReadEnumWithDefault(Enum defaultValue) const
Definition: Prefs.h:538
Enum ReadEnum() const
Definition: Prefs.h:532
EnumValueSymbols()=default
wxArrayStringEx mInternals
Definition: Prefs.h:404
EnumValueSymbols(std::vector< EnumValueSymbol > symbols)
Definition: Prefs.h:385
EnumValueSymbols(std::initializer_list< EnumValueSymbol > symbols)
Definition: Prefs.h:382
TranslatableStrings mMsgids
Definition: Prefs.h:403
Specialization of Setting for int.
Definition: Prefs.h:354
A listener notified of changes in preferences.
Definition: Prefs.h:561
std::unique_ptr< Impl > mpImpl
Definition: Prefs.h:588
Base class for settings objects. It holds a configuration key path.
Definition: Prefs.h:80
audacity::BasicSettings * GetConfig() const
Definition: Prefs.cpp:518
SettingBase(const wxChar *path)
Definition: Prefs.h:83
SettingBase(const wxString &path)
Definition: Prefs.h:84
SettingBase(const char *path)
Definition: Prefs.h:82
SettingBase(const SettingBase &)=default
const SettingPath & GetPath() const
Definition: Prefs.h:88
const SettingPath mPath
Definition: Prefs.h:95
Definition: Prefs.h:178
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:257
T Read() const
overload of Read, always returning a value
Definition: Prefs.h:231
Setting(const SettingBase &path, const T &defaultValue)
Usual overload supplies a default value.
Definition: Prefs.h:185
T ReadWithDefault(const T &defaultValue) const
new direct use is discouraged but it may be needed in legacy code
Definition: Prefs.h:239
void EnterTransaction(size_t depth) override
Definition: Prefs.h:293
void Invalidate() override
Definition: Prefs.h:287
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:211
void Rollback() noexcept override
Definition: Prefs.h:315
bool Reset()
Reset to the default value.
Definition: Prefs.h:282
bool DoWrite()
Write cached value to config and return true if successful.
Definition: Prefs.h:330
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:205
std::function< T() > DefaultValueFunction
Definition: Prefs.h:182
std::vector< T > mPreviousValues
Definition: Prefs.h:339
const T & GetDefault() const
Definition: Prefs.h:197
Setting(const SettingBase &path, DefaultValueFunction function)
This overload causes recomputation of the default each time it is needed.
Definition: Prefs.h:191
bool Commit() override
Definition: Prefs.h:301
const DefaultValueFunction mFunction
Definition: Prefs.h:337
Makes temporary changes to preferences, then rolls them back at destruction.
Definition: Prefs.h:120
bool mCommitted
Definition: Prefs.h:138
static AddResult Add(TransactionalSettingBase &setting)
Definition: Prefs.cpp:278
SettingScope(const SettingScope &)=delete
~SettingScope() noexcept
Definition: Prefs.cpp:261
SettingScope & operator=(const SettingScope &)=delete
@ NotAdded
Definition: Prefs.h:133
@ PreviouslyAdded
Definition: Prefs.h:133
std::set< TransactionalSettingBase * > mPending
Definition: Prefs.h:137
Extend SettingScope with Commit() which flushes updates in a batch.
Definition: Prefs.h:149
Specialization of Setting for strings.
Definition: Prefs.h:368
friend class SettingScope
Definition: Prefs.h:109
virtual void Rollback() noexcept=0
virtual void EnterTransaction(size_t depth)=0
virtual void Invalidate()=0
virtual bool Commit()=0
Base class for objects that provide facility to store data persistently, and access it with string ke...
Definition: BasicSettings.h:31
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)
RegistryPath mPath
Definition: Prefs.h:73