Audacity  3.0.3
Prefs.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Prefs.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//*******************************************************************/
51 
52 
53 #include "Prefs.h"
54 
55 #include <wx/defs.h>
56 #include <wx/app.h>
57 #include <wx/intl.h>
58 #include <wx/filename.h>
59 #include <wx/stdpaths.h>
60 
61 #include "Internat.h"
62 #include "MemoryX.h"
63 #include "BasicUI.h"
64 
66  L"/Update/DefaultUpdatesChecking", true };
67 
68 std::unique_ptr<FileConfig> ugPrefs {};
69 
70 FileConfig *gPrefs = nullptr;
71 int gMenusDirty = 0;
72 
73 struct MyEvent : wxEvent
74 {
75 public:
76  explicit MyEvent(int id) : mId{id} {}
77  virtual wxEvent *Clone() const override { return new MyEvent{mId}; }
78  int mId;
79 };
80 
81 wxDECLARE_EVENT(EVT_PREFS_UPDATE, MyEvent);
82 wxDEFINE_EVENT(EVT_PREFS_UPDATE, MyEvent);
83 
84 struct PrefsListener::Impl : wxEvtHandler
85 {
86  Impl( PrefsListener &owner );
87  ~Impl();
88  void OnEvent(wxEvent&);
90 };
91 
92 static wxEvtHandler hub;
93 
95 {
96  BasicUI::CallAfter([id]{
97  MyEvent event{ id };
98  hub.ProcessEvent(event);
99  });
100 }
101 
103  : mOwner{ owner }
104 {
105  hub.Bind(EVT_PREFS_UPDATE, &PrefsListener::Impl::OnEvent, this);
106 }
107 
109 {
110 }
111 
113  : mpImpl{ std::make_unique<Impl>( *this ) }
114 {
115 }
116 
118 {
119 }
120 
122 {
123 }
124 
125 void PrefsListener::Impl::OnEvent( wxEvent &evt )
126 {
127  evt.Skip();
128  auto id = evt.GetId();
129  if (id <= 0)
131  else
133 }
134 
135 #if 0
136 // Copy one entry from one wxConfig object to another
137 static void CopyEntry(wxString path, wxConfigBase *src, wxConfigBase *dst, wxString entry)
138 {
139  switch(src->GetEntryType(entry)) {
140  case wxConfigBase::Type_Unknown:
141  case wxConfigBase::Type_String: {
142  wxString value = src->Read(entry, wxT(""));
143  dst->Write(path + entry, value);
144  break;
145  }
146  case wxConfigBase::Type_Boolean: {
147  bool value = false;
148  src->Read(entry, &value, value);
149  dst->Write(path + entry, value);
150  break;
151  }
152  case wxConfigBase::Type_Integer: {
153  long value = false;
154  src->Read(entry, &value, value);
155  dst->Write(path + entry, value);
156  break;
157  }
158  case wxConfigBase::Type_Float: {
159  double value = false;
160  src->Read(entry, &value, value);
161  dst->Write(path + entry, value);
162  break;
163  }
164  }
165 }
166 
167 
168 // Recursive routine to copy all groups and entries from one wxConfig object to another
169 static void CopyEntriesRecursive(wxString path, wxConfigBase *src, wxConfigBase *dst)
170 {
171  wxString entryName;
172  long entryIndex;
173  bool entryKeepGoing;
174 
175  entryKeepGoing = src->GetFirstEntry(entryName, entryIndex);
176  while (entryKeepGoing) {
177  CopyEntry(path, src, dst, entryName);
178  entryKeepGoing = src->GetNextEntry(entryName, entryIndex);
179  }
180 
181  wxString groupName;
182  long groupIndex;
183  bool groupKeepGoing;
184 
185  groupKeepGoing = src->GetFirstGroup(groupName, groupIndex);
186  while (groupKeepGoing) {
187  wxString subPath = path+groupName+wxT("/");
188  src->SetPath(subPath);
189  CopyEntriesRecursive(subPath, src, dst);
190  src->SetPath(path);
191  groupKeepGoing = src->GetNextGroup(groupName, groupIndex);
192  }
193 }
194 #endif
195 
196 void InitPreferences( std::unique_ptr<FileConfig> uPrefs )
197 {
198  gPrefs = uPrefs.get();
199  ugPrefs = std::move(uPrefs);
200  wxConfigBase::Set(gPrefs);
201 }
202 
204 {
205  // Future: make this a static registry table, so the settings objects
206  // don't need to be defined in this source code file to avoid dependency
207  // cycles
208  std::pair<BoolSetting &, bool> stickyBoolSettings[] {
210  // ... others?
211  };
212  for (auto &pair : stickyBoolSettings)
213  pair.second = pair.first.Read();
214 
215  bool savedValue = DefaultUpdatesCheckingFlag.Read();
216  gPrefs->DeleteAll();
217 
218  for (auto &pair : stickyBoolSettings)
219  pair.first.Write(pair.second);
220 }
221 
223 {
224  if (gPrefs) {
225  wxConfigBase::Set(NULL);
226  ugPrefs.reset();
227  gPrefs = NULL;
228  }
229 }
230 
233  ByColumns_t,
234  const TranslatableStrings &msgids,
235  wxArrayStringEx internals
236 )
237  : mInternals( std::move( internals ) )
238 {
239  auto size = mInternals.size(), size2 = msgids.size();
240  if ( size != size2 ) {
241  wxASSERT( false );
242  size = std::min( size, size2 );
243  }
244  reserve( size );
245  auto iter1 = mInternals.begin();
246  auto iter2 = msgids.begin();
247  while( size-- )
248  emplace_back( *iter1++, *iter2++ );
249 }
250 
252 {
253  if ( mMsgids.empty() )
254  mMsgids = transform_container<TranslatableStrings>( *this,
255  std::mem_fn( &EnumValueSymbol::Msgid ) );
256  return mMsgids;
257 }
258 
260 {
261  if ( mInternals.empty() )
262  mInternals = transform_container<wxArrayStringEx>( *this,
263  std::mem_fn( &EnumValueSymbol::Internal ) );
264  return mInternals;
265 }
266 
269 {
270  if ( mDefaultSymbol >= 0 && mDefaultSymbol < (long)mSymbols.size() )
271  return mSymbols[ mDefaultSymbol ];
272  static EnumValueSymbol empty;
273  return empty;
274 }
275 
276 wxString ChoiceSetting::Read() const
277 {
278  const auto &defaultValue = Default().Internal();
279  return ReadWithDefault( defaultValue );
280 }
281 
282 wxString ChoiceSetting::ReadWithDefault( const wxString &defaultValue ) const
283 {
284  wxString value;
285  if ( !gPrefs->Read(mKey, &value, defaultValue) )
286  if (!mMigrated) {
287  const_cast<ChoiceSetting*>(this)->Migrate( value );
288  mMigrated = true;
289  }
290 
291  // Remap to default if the string is not known -- this avoids surprises
292  // in case we try to interpret config files from future versions
293  auto index = Find( value );
294  if ( index >= mSymbols.size() )
295  value = defaultValue;
296  return value;
297 }
298 
299 size_t ChoiceSetting::Find( const wxString &value ) const
300 {
301  auto start = GetSymbols().begin();
302  return size_t(
303  std::find( start, GetSymbols().end(), EnumValueSymbol{ value, {} } )
304  - start );
305 }
306 
307 void ChoiceSetting::Migrate( wxString &value )
308 {
309  (void)value;// Compiler food
310 }
311 
312 bool ChoiceSetting::Write( const wxString &value )
313 {
314  auto index = Find( value );
315  if (index >= mSymbols.size())
316  return false;
317 
318  auto result = gPrefs->Write( mKey, value );
319  mMigrated = true;
320  return result;
321 }
322 
324  const SettingBase &key,
325  EnumValueSymbols symbols,
326  long defaultSymbol,
327 
328  std::vector<int> intValues, // must have same size as symbols
329  const wxString &oldKey
330 )
331  : ChoiceSetting{ key, std::move( symbols ), defaultSymbol }
332  , mIntValues{ std::move( intValues ) }
333  , mOldKey{ oldKey }
334 {
335  auto size = mSymbols.size();
336  if( mIntValues.size() != size ) {
337  wxASSERT( false );
338  mIntValues.resize( size );
339  }
340 }
341 
342 void ChoiceSetting::SetDefault( long value )
343 {
344  if ( value < (long)mSymbols.size() )
345  mDefaultSymbol = value;
346  else
347  wxASSERT( false );
348 }
349 
351 {
352  auto index = Find( Read() );
353 
354  wxASSERT( index < mIntValues.size() );
355  return mIntValues[ index ];
356 }
357 
358 int EnumSettingBase::ReadIntWithDefault( int defaultValue ) const
359 {
360  wxString defaultString;
361  auto index0 = FindInt( defaultValue );
362  if ( index0 < mSymbols.size() )
363  defaultString = mSymbols[ index0 ].Internal();
364  else
365  wxASSERT( false );
366 
367  auto index = Find( ReadWithDefault( defaultString ) );
368 
369  wxASSERT( index < mSymbols.size() );
370  return mIntValues[ index ];
371 }
372 
373 size_t EnumSettingBase::FindInt( int code ) const
374 {
375  const auto start = mIntValues.begin();
376  return size_t(
377  std::find( start, mIntValues.end(), code )
378  - start );
379 }
380 
381 void EnumSettingBase::Migrate( wxString &value )
382 {
383  int intValue = 0;
384  if ( !mOldKey.empty() &&
385  gPrefs->Read(mOldKey, &intValue, 0) ) {
386  // Make the migration, only once and persistently.
387  // Do not DELETE the old key -- let that be read if user downgrades
388  // Audacity. But further changes will be stored only to the NEW key
389  // and won't be seen then.
390  auto index = (long) FindInt( intValue );
391  if ( index >= (long)mSymbols.size() )
392  index = mDefaultSymbol;
393  if ( index >= 0 && index < (long)mSymbols.size() ) {
394  value = mSymbols[index].Internal();
395  Write(value);
396  gPrefs->Flush();
397  }
398  }
399 }
400 
401 bool EnumSettingBase::WriteInt( int code ) // you flush gPrefs afterward
402 {
403  auto index = FindInt( code );
404  if ( index >= mSymbols.size() )
405  return false;
406  return Write( mSymbols[index].Internal() );
407 }
408 
409 wxString WarningDialogKey(const wxString &internalDialogName)
410 {
411  return wxT("/Warnings/") + internalDialogName;
412 }
413 
415 
416 #include <set>
417 
418 namespace {
419  using PreferenceInitializers = std::set< PreferenceInitializer* >;
421  {
422  static PreferenceInitializers theSet;
423  return theSet;
424  }
425 }
426 
428 {
429  allInitializers().insert( this );
430 }
431 
433 {
434  allInitializers().erase( this );
435 }
436 
438 {
439  for ( auto pInitializer : allInitializers() )
440  (*pInitializer)();
441 }
442 
443 wxConfigBase *SettingBase::GetConfig() const
444 {
445  return gPrefs;
446 }
447 
449 {
450  auto config = GetConfig();
451  return config && config->DeleteEntry( GetPath() );
452 }
453 
455 {
456  bool value = Read();
457  if ( Write( !value ) )
458  return !value;
459  else
460  return value;
461 }
SettingBase
Base class for settings objects. It holds a configuration key path.
Definition: Prefs.h:67
EnumSettingBase::Migrate
void Migrate(wxString &) override
Definition: Prefs.cpp:381
PrefsListener::~PrefsListener
virtual ~PrefsListener()
Definition: Prefs.cpp:117
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
SettingBase::GetPath
const wxString & GetPath() const
Definition: Prefs.h:75
EnumSettingBase::mIntValues
std::vector< int > mIntValues
Definition: Prefs.h:344
TranslatableStrings
std::vector< TranslatableString > TranslatableStrings
Definition: TranslatableString.h:295
ChoiceSetting::Find
size_t Find(const wxString &value) const
Definition: Prefs.cpp:299
EnumValueSymbols::EnumValueSymbols
EnumValueSymbols()=default
Setting< bool >::Write
bool Write(const bool &value)
Write value to config and return true if successful.
Definition: Prefs.h:172
ChoiceSetting::Write
bool Write(const wxString &value)
Definition: Prefs.cpp:312
MyEvent::Clone
virtual wxEvent * Clone() const override
Definition: Prefs.cpp:77
FinishPreferences
void FinishPreferences()
Definition: Prefs.cpp:222
SettingBase::Delete
bool Delete()
Delete the key if present, and return true iff it was.
Definition: Prefs.cpp:448
BoolSetting
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:204
EnumValueSymbols::GetMsgids
const TranslatableStrings & GetMsgids() const
Definition: Prefs.cpp:251
EnumSettingBase::ReadInt
int ReadInt() const
Definition: Prefs.cpp:350
PreferenceInitializer::ReinitializeAll
static void ReinitializeAll()
Definition: Prefs.cpp:437
BasicUI::CallAfter
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Definition: BasicUI.cpp:38
anonymous_namespace{Prefs.cpp}::allInitializers
PreferenceInitializers & allInitializers()
Definition: Prefs.cpp:420
PrefsListener::Impl::Impl
Impl(PrefsListener &owner)
Definition: Prefs.cpp:102
EnumValueSymbols::GetInternals
const wxArrayStringEx & GetInternals() const
Definition: Prefs.cpp:259
ComponentInterfaceSymbol::Msgid
const TranslatableString & Msgid() const
Definition: ComponentInterfaceSymbol.h:56
wxArrayStringEx
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
Definition: wxArrayStringEx.h:18
PrefsListener::Broadcast
static void Broadcast(int id=0)
Call this static function to notify all PrefsListener objects.
Definition: Prefs.cpp:94
EnumSettingBase::EnumSettingBase
EnumSettingBase(const SettingBase &key, EnumValueSymbols symbols, long defaultSymbol, std::vector< int > intValues, const wxString &oldKey={})
Definition: Prefs.cpp:323
EnumValueSymbols::mMsgids
TranslatableStrings mMsgids
Definition: Prefs.h:260
ComponentInterfaceSymbol
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Definition: ComponentInterfaceSymbol.h:27
hub
static wxEvtHandler hub
Definition: Prefs.cpp:92
Setting::Read
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:128
PrefsListener
A listener notified of changes in preferences.
Definition: Prefs.h:389
EnumValueSymbols
Definition: Prefs.h:239
PreferenceInitializer::PreferenceInitializer
PreferenceInitializer()
Definition: Prefs.cpp:427
ugPrefs
std::unique_ptr< FileConfig > ugPrefs
Definition: Prefs.cpp:68
EnumSettingBase::ReadIntWithDefault
int ReadIntWithDefault(int defaultValue) const
Definition: Prefs.cpp:358
ByColumns_t
Definition: Prefs.h:61
PrefsListener::UpdateSelectedPrefs
virtual void UpdateSelectedPrefs(int id)
Definition: Prefs.cpp:121
DefaultUpdatesCheckingFlag
BoolSetting DefaultUpdatesCheckingFlag
Definition: Prefs.cpp:65
wxDECLARE_EVENT
wxDECLARE_EVENT(EVT_PREFS_UPDATE, MyEvent)
ChoiceSetting
Definition: Prefs.h:267
ResetPreferences
void ResetPreferences()
Call this to reset preferences to an (almost)-"new" default state.
Definition: Prefs.cpp:203
MyEvent::mId
int mId
Definition: Prefs.cpp:78
MyEvent
Definition: Prefs.cpp:74
InitPreferences
void InitPreferences(std::unique_ptr< FileConfig > uPrefs)
Definition: Prefs.cpp:196
Setting< bool >::Read
bool Read() const
overload of Read, always returning a value
Definition: Prefs.h:154
PreferenceInitializer::~PreferenceInitializer
virtual ~PreferenceInitializer()
Definition: Prefs.cpp:432
EnumSettingBase::mOldKey
const wxString mOldKey
Definition: Prefs.h:345
EnumSettingBase::WriteInt
bool WriteInt(int code)
Definition: Prefs.cpp:401
ChoiceSetting::mDefaultSymbol
long mDefaultSymbol
Definition: Prefs.h:309
ChoiceSetting::SetDefault
void SetDefault(long value)
Definition: Prefs.cpp:342
ChoiceSetting::ReadWithDefault
wxString ReadWithDefault(const wxString &) const
Definition: Prefs.cpp:282
PrefsListener::Impl::OnEvent
void OnEvent(wxEvent &)
Definition: Prefs.cpp:125
ChoiceSetting::GetSymbols
const EnumValueSymbols & GetSymbols() const
Definition: Prefs.h:285
ChoiceSetting::mMigrated
bool mMigrated
Definition: Prefs.h:307
ChoiceSetting::mKey
const wxString mKey
Definition: Prefs.h:302
EnumValueSymbols::mInternals
wxArrayStringEx mInternals
Definition: Prefs.h:261
FileConfig
Definition: FileConfig.h:22
BasicUI.h
Toolkit-neutral facade for basic user interface services.
Internat.h
PrefsListener::Impl::~Impl
~Impl()
Definition: Prefs.cpp:108
ChoiceSetting::Read
wxString Read() const
Definition: Prefs.cpp:276
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
PrefsListener::Impl
Definition: Prefs.cpp:85
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
key
static const AudacityProject::AttachedObjects::RegisteredFactory key
Definition: CommandManager.cpp:197
ChoiceSetting::Default
const EnumValueSymbol & Default() const
Definition: Prefs.cpp:268
MemoryX.h
ChoiceSetting::Migrate
virtual void Migrate(wxString &)
Definition: Prefs.cpp:307
SettingBase::GetConfig
wxConfigBase * GetConfig() const
Definition: Prefs.cpp:443
WarningDialogKey
wxString WarningDialogKey(const wxString &internalDialogName)
Definition: Prefs.cpp:409
EnumSettingBase::FindInt
size_t FindInt(int code) const
Definition: Prefs.cpp:373
BoolSetting::Toggle
bool Toggle()
Write the negation of the previous value, and then return the current value.
Definition: Prefs.cpp:454
ComponentInterfaceSymbol::Internal
const wxString & Internal() const
Definition: ComponentInterfaceSymbol.h:55
ExceptionType::Internal
@ Internal
Indicates internal failure from Audacity.
FileConfig::DeleteAll
virtual bool DeleteAll() wxOVERRIDE
Definition: FileConfig.cpp:229
PrefsListener::UpdatePrefs
virtual void UpdatePrefs()=0
PrefsListener::Impl::mOwner
PrefsListener & mOwner
Definition: Prefs.cpp:89
anonymous_namespace{Prefs.cpp}::PreferenceInitializers
std::set< PreferenceInitializer * > PreferenceInitializers
Definition: Prefs.cpp:419
Prefs.h
ByColumns
ByColumns_t ByColumns
Definition: Prefs.cpp:414
PrefsListener::mpImpl
std::unique_ptr< Impl > mpImpl
Definition: Prefs.h:415
PrefsListener::PrefsListener
PrefsListener()
Definition: Prefs.cpp:112
gMenusDirty
int gMenusDirty
Definition: Prefs.cpp:71
ChoiceSetting::mSymbols
const EnumValueSymbols mSymbols
Definition: Prefs.h:304
MyEvent::MyEvent
MyEvent(int id)
Definition: Prefs.cpp:76
wxDEFINE_EVENT
wxDEFINE_EVENT(EVT_PREFS_UPDATE, MyEvent)