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