Update of /cvsroot/mahogany/M/src/classes
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10627/src/classes

Modified Files:
        Profile.cpp 
Log Message:
added wxConfigMultiplexer to allow code using wxConfig and not Profile (as 
persistent controls) to still work with multiple config sources

Index: Profile.cpp
===================================================================
RCS file: /cvsroot/mahogany/M/src/classes/Profile.cpp,v
retrieving revision 1.161
retrieving revision 1.162
diff -b -u -2 -r1.161 -r1.162
--- Profile.cpp 12 Jul 2004 00:25:56 -0000      1.161
+++ Profile.cpp 4 Jul 2005 19:51:40 -0000       1.162
@@ -103,4 +103,6 @@
 {
 public:
+   enum Type { LD_LONG, LD_STRING };
+
    LookupData(const String& key, const String& def)
       : m_Key(key), m_Str(def)
@@ -119,5 +121,17 @@
    }
 
-   enum Type { LD_LONG, LD_STRING };
+   // default copy ctor, assignment operator and dtor are ok
+
+
+   // don't compare m_Found field here, just the data
+   bool operator==(const LookupData& other)
+   {
+      if ( other.m_Type != m_Type || other.m_Key != m_Key )
+         return false;
+
+      return m_Type == LD_LONG ? other.m_Long == m_Long
+                               : other.m_Str == m_Str;
+   }
+
 
    Type GetType(void) const { return m_Type; }
@@ -199,5 +213,4 @@
 #endif // OS_UNIX
 
-
 /**
    AllConfigSources is a list of all config source the profiles use.
@@ -220,9 +233,16 @@
       by their priority values.
 
+      Side effect: this ctor also changes the global wxConfig object by
+      creating a new wxConfigMultiplexer instance and setting it as global
+      wxConfig using wxConfig::Set().
+
       @param filename the file used for the default config, may be empty
     */
    AllConfigSources(const String& filename);
 
-   // default dtor is ok
+   /**
+      Destructor destroys wxConfig we had set in ctor.
+    */
+   ~AllConfigSources();
 
 
@@ -289,8 +309,14 @@
 
    /// Return true if the given group exists in any config source
-   bool HasGroup(const String& path) const;
+   bool HasGroup(const String& path) const
+   {
+      return FindGroup(path) != m_sources.end();
+   }
 
    /// Return true if the given entry exists in any config source
-   bool HasEntry(const String& path) const;
+   bool HasEntry(const String& path) const
+   {
+      return FindEntry(path) != m_sources.end();
+   }
 
    //@}
@@ -335,12 +361,28 @@
 
    /**
-      Get wxConfig object associated with the local config source.
+      @name Helper methods for wxConfigMultiplexer only.
+
+      Do not use these methods from elsewhere.
+    */
+   //@{
+
+   /// Get the list of all sources
+   List& GetSources() { return m_sources; }
+   const List& GetSources() const { return m_sources; }
+
+   /// Find the config source containing this entry
+   List::iterator FindEntry(const String& path) const;
 
-      This method is deprecated and must not be used, it is there only to
-      avoid breaking some existing code.
+   /// Find the config source containing this group
+   List::iterator FindGroup(const String& path) const;
+
+   /**
+      Get wxConfig object associated with the local config source.
 
       @param config pointer (not to be deleted by caller) or NULL
     */
-   wxConfigBase *GetConfig() const;
+   wxConfigBase *GetLocalConfig() const;
+
+   //@}
 
 private:
@@ -352,7 +394,6 @@
    List m_sources;
 
-   // we can't be coppied
-   AllConfigSources(const AllConfigSources&);
-   AllConfigSources& operator=(const AllConfigSources&);
+
+   DECLARE_NO_COPY_CLASS(AllConfigSources)
 };
 
@@ -362,4 +403,212 @@
 
 /**
+   wxConfigMultiplexer is a wxConfig façade for AllConfigSources.
+
+   wxConfigMultiplexer presents wxConfig interface for AllConfigSources
+   functionality, i.e. it reads from all config sources and not just from the
+   local config.
+ */
+class wxConfigMultiplexer : public wxConfigBase
+{
+public:
+   wxConfigMultiplexer(AllConfigSources& configSources)
+      : m_configSources(configSources)
+   {
+   }
+
+   virtual void SetPath(const wxString& path)
+   {
+      m_path = path;
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      if ( config )
+         config->SetPath(path);
+   }
+
+   virtual const wxString& GetPath() const { return m_path; }
+
+
+   virtual bool GetFirstGroup(wxString& str, long& lIndex) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config && config->GetFirstGroup(str, lIndex);
+   }
+
+   virtual bool GetNextGroup(wxString& str, long& lIndex) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config && config->GetNextGroup(str, lIndex);
+   }
+
+   virtual bool GetFirstEntry(wxString& str, long& lIndex) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config && config->GetFirstEntry(str, lIndex);
+   }
+
+   virtual bool GetNextEntry(wxString& str, long& lIndex) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config && config->GetNextEntry(str, lIndex);
+   }
+
+
+   virtual size_t GetNumberOfEntries(bool bRecursive = false) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config ? config->GetNumberOfEntries(bRecursive) : 0;
+   }
+
+   virtual size_t GetNumberOfGroups(bool bRecursive = false) const
+   {
+      wxConfigBase * const config = m_configSources.GetLocalConfig();
+      return config ? config->GetNumberOfGroups(bRecursive) : 0;
+   }
+
+
+   virtual bool HasGroup(const wxString& name) const
+   {
+      return m_configSources.HasGroup(name);
+   }
+
+   virtual bool HasEntry(const wxString& name) const
+   {
+      return m_configSources.HasEntry(name);
+   }
+
+
+   virtual bool Flush(bool /* bCurrentOnly */ = false)
+   {
+      return m_configSources.FlushAll();
+   }
+
+   virtual bool
+   RenameEntry(const wxString& /* oldName */, const wxString& /* newName */)
+   {
+      FAIL_MSG( _T("not implemented") );
+
+      return false;
+   }
+
+   virtual bool
+   RenameGroup(const wxString& /* oldName */, const wxString& /* newName */)
+   {
+      FAIL_MSG( _T("not implemented") );
+
+      return false;
+   }
+
+   virtual bool DeleteEntry(const wxString& key, bool /* groupIfEmpty */ = 
true)
+   {
+      wxString path;
+      if ( *key.c_str() == _T('/') )
+         path = key;
+      else
+         path << m_path << _T('/') << key;
+
+      // we need to delete all these entries
+      bool foundAny = false;
+      for ( ;; )
+      {
+         AllConfigSources::List::iterator i = m_configSources.FindEntry(path);
+         if ( i == m_configSources.GetSources().end() )
+         {
+            CHECK( foundAny, false, _T("entry to delete doesn't exist") );
+            break;
+         }
+
+         foundAny = true;
+         if ( !i->DeleteEntry(path) )
+            return false;
+      }
+
+      return true;
+   }
+
+   virtual bool DeleteGroup(const wxString& key)
+   {
+      wxString path;
+      if ( *key.c_str() == _T('/') )
+         path = key;
+      else
+         path << m_path << _T('/') << key;
+
+      bool foundAny = false;
+      for ( ;; )
+      {
+         AllConfigSources::List::iterator i = m_configSources.FindGroup(path);
+         if ( i == m_configSources.GetSources().end() )
+         {
+            CHECK( foundAny, false, _T("group to delete doesn't exist") );
+            break;
+         }
+
+         foundAny = true;
+         if ( !i->DeleteGroup(path) )
+            return false;
+      }
+
+      return true;
+   }
+
+   virtual bool DeleteAll()
+   {
+      // this is too dangerous, we don't provide any way to wipe out all config
+      // information
+      return false;
+   }
+
+protected:
+   bool DoRead(LookupData& ld) const
+   {
+      return m_configSources.Read(m_path, ld);
+   }
+
+   bool DoWrite(LookupData& ld)
+   {
+      return m_configSources.Write(m_path, ld, NULL /* use local config */);
+   }
+
+
+   virtual bool DoReadString(const wxString& key, wxString *pStr) const
+   {
+      LookupData ld(key, _T(""));
+      if ( !DoRead(ld) )
+         return false;
+
+      *pStr = ld.GetString();
+      return true;
+   }
+
+   virtual bool DoReadLong(const wxString& key, long *pl) const
+   {
+      LookupData ld(key, 0l);
+      if ( !DoRead(ld) )
+         return false;
+
+      *pl = ld.GetLong();
+      return true;
+   }
+
+   virtual bool DoWriteString(const wxString& key, const wxString& value)
+   {
+      LookupData ld(key, value);
+      return DoWrite(ld);
+   }
+
+   virtual bool DoWriteLong(const wxString& key, long value)
+   {
+      LookupData ld(key, value);
+      return DoWrite(ld);
+   }
+
+private:
+   AllConfigSources& m_configSources;
+   wxString m_path;
+
+   DECLARE_NO_COPY_CLASS(wxConfigMultiplexer)
+};
+
+
+/**
   ProfileEnumDataImpl is used to store state data while iterating over
   entries/subgroups of a profile.
@@ -482,6 +731,5 @@
    virtual const String& GetName(void) const { return m_ProfileName; }
 
-   virtual wxConfigBase *GetConfig() const
-      { return gs_allConfigSources ? gs_allConfigSources->GetConfig() : NULL; }
+   virtual wxConfigBase *GetConfig() const { return wxConfig::Get(); }
 
    virtual void Suspend(void)
@@ -738,4 +986,11 @@
    }
 
+   // also register out special wxConfig for persistent controls use
+   delete wxConfig::Set(new wxConfigMultiplexer(*this));
+
+
+   // now build the list of all config source we use
+   // ----------------------------------------------
+
    // local config is always first
    m_sources.push_back(configLocal);
@@ -810,4 +1065,10 @@
 }
 
+AllConfigSources::~AllConfigSources()
+{
+   // we can't allow wxConfigMultiplexer to live any longer
+   delete wxConfig::Set(NULL);
+}
+
 // ----------------------------------------------------------------------------
 // AllConfigSources reading and writing
@@ -847,4 +1108,14 @@
 
       config = *m_sources.begin().operator->();
+
+      // avoid writing to local config source the same data that are already
+      // present in another one with lesser priority: this just results in huge
+      // duplication of data without any gain
+      LookupData dataOld(data);
+      if ( Read(path, dataOld) && dataOld == data )
+      {
+         // the same value already present, don't write it
+         return true;
+      }
    }
 
@@ -935,5 +1206,6 @@
 }
 
-bool AllConfigSources::HasGroup(const String& path) const
+AllConfigSources::List::iterator
+AllConfigSources::FindGroup(const String& path) const
 {
    const List::iterator end = m_sources.end();
@@ -941,11 +1213,12 @@
    {
       if ( i->HasGroup(path) )
-         return true;
+         return i;
    }
 
-   return false;
+   return end;
 }
 
-bool AllConfigSources::HasEntry(const String& path) const
+AllConfigSources::List::iterator
+AllConfigSources::FindEntry(const String& path) const
 {
    const List::iterator end = m_sources.end();
@@ -953,8 +1226,8 @@
    {
       if ( i->HasEntry(path) )
-         return true;
+         return i;
    }
 
-   return false;
+   return end;
 }
 
@@ -1068,5 +1341,5 @@
 
 
-wxConfigBase *AllConfigSources::GetConfig() const
+wxConfigBase *AllConfigSources::GetLocalConfig() const
 {
    if ( m_sources.empty() )



-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
Mahogany-cvsupdates mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to