[glibmm] OptionGroup: Add add_entry() that takes a slot with callback function.



commit 94a1f3d568decbde9c3fab84c34db5741ffcad62
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Mon Feb 14 16:24:27 2011 +0100

    OptionGroup: Add add_entry() that takes a slot with callback function.
    
    * glib/src/optiongroup.[hg|ccg]: Add add_entry() and add_entry_filename()
    that take a slot. Add protected option_arg_callback().
    An exception thrown by on_pre_parse() or on_post_parse() is propagated
    to the error argument of g_callback_pre_parse() or post_parse_callback().
    * glib/src/optionentry.hg: Add description of set_flags().
    * examples/options/main.cc: Add more OptionEntries and callback functions
    for parsing command option values.
    Bug 589197 (Hubert Figuiere)

 ChangeLog                |   13 ++
 examples/options/main.cc |   94 +++++++++++++++-
 glib/src/optionentry.hg  |    8 +-
 glib/src/optiongroup.ccg |  273 ++++++++++++++++++++++++++++++++++++++++-----
 glib/src/optiongroup.hg  |   15 +++
 5 files changed, 365 insertions(+), 38 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e2243ae..ce458d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2011-02-14  Kjell Ahlstedt  <kjell ahlstedt bredband net>
+
+  OptionGroup: Add add_entry() that takes a slot with callback function.
+
+	* glib/src/optiongroup.[hg|ccg]: Add add_entry() and add_entry_filename()
+	that take a slot. Add protected option_arg_callback().
+	An exception thrown by on_pre_parse() or on_post_parse() is propagated
+	to the error argument of g_callback_pre_parse() or post_parse_callback().
+	* glib/src/optionentry.hg: Add description of set_flags().
+	* examples/options/main.cc: Add more OptionEntries and callback functions
+	for parsing command option values.
+	Bug #589197 (Hubert Figuiere)
+
 2011-02-15  Murray Cumming  <murrayc murrayc com>
 
 	Dealt with several TODOs.
diff --git a/examples/options/main.cc b/examples/options/main.cc
index 0ba5372..ee524da 100644
--- a/examples/options/main.cc
+++ b/examples/options/main.cc
@@ -28,7 +28,12 @@ public:
   virtual bool on_pre_parse(Glib::OptionContext& context, Glib::OptionGroup& group);
   virtual bool on_post_parse(Glib::OptionContext& context, Glib::OptionGroup& group);
   virtual void on_error(Glib::OptionContext& context, Glib::OptionGroup& group);
-  
+
+  bool on_option_arg_string(const Glib::ustring& option_name,
+    const Glib::ustring& value, bool has_value);
+  bool on_option_arg_filename(const Glib::ustring& option_name,
+    const std::string& value, bool has_value);
+
   //These members should live as long as the OptionGroup to which they are added, 
   //and as long as the OptionContext to which that OptionGroup is added.
   int m_arg_foo;
@@ -37,6 +42,8 @@ public:
   bool m_arg_boolean;
   Glib::OptionGroup::vecustrings m_arg_list;
   Glib::OptionGroup::vecustrings m_remaining_list;
+  Glib::ustring m_arg_x_string;
+  std::string m_arg_x_filename;
 };
 
 ExampleOptionGroup::ExampleOptionGroup()
@@ -73,6 +80,22 @@ ExampleOptionGroup::ExampleOptionGroup()
   entry5.set_description("A List");
   add_entry(entry5, m_arg_list);
 
+  Glib::OptionEntry entry6;
+  entry6.set_long_name("x-string");
+  entry6.set_short_name('x');
+  entry6.set_description("A string with custom parsing");
+  entry6.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
+  m_arg_x_string = "not specified";
+  add_entry(entry6, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_string));
+
+  Glib::OptionEntry entry7;
+  entry7.set_long_name("x-filename");
+  entry7.set_short_name('X');
+  entry7.set_description("A filename with custom parsing");
+  entry7.set_flags(Glib::OptionEntry::FLAG_OPTIONAL_ARG);
+  m_arg_x_filename = "not specified";
+  add_entry_filename(entry7, sigc::mem_fun(*this, &ExampleOptionGroup::on_option_arg_filename));
+
   Glib::OptionEntry entry_remaining;
   entry_remaining.set_long_name(G_OPTION_REMAINING);
   entry_remaining.set_arg_description(G_OPTION_REMAINING);
@@ -103,6 +126,66 @@ void ExampleOptionGroup::on_error(Glib::OptionContext& /* context */, Glib::Opti
   std::cout << "on_error called" << std::endl;
 }
 
+bool ExampleOptionGroup::on_option_arg_string(const Glib::ustring& option_name,
+    const Glib::ustring& value, bool has_value)
+{
+  if(option_name != "-x" && option_name != "--x-string")
+  {
+    m_arg_x_string = "on_option_arg_string called with unexpected option_name: " + option_name;
+    throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_string);
+  }
+
+  if(!has_value)
+  {
+    m_arg_x_string = "no value";
+    return true;
+  }
+
+  if(value.empty())
+  {
+    m_arg_x_string = "empty string";
+    return true;
+  }
+
+  m_arg_x_string = value;
+  if(value == "error")
+  {
+    throw Glib::OptionError(Glib::OptionError::BAD_VALUE,
+      "on_option_arg_string called with value = " + m_arg_x_string);
+  }
+  return value != "false";
+}
+
+bool ExampleOptionGroup::on_option_arg_filename(const Glib::ustring& option_name,
+    const std::string& value, bool has_value)
+{
+  if(option_name != "-X" && option_name != "--x-filename")
+  {
+    m_arg_x_filename = "on_option_arg_filename called with unexpected option_name: " + option_name;
+    throw Glib::OptionError(Glib::OptionError::UNKNOWN_OPTION, m_arg_x_filename);
+  }
+
+  if(!has_value)
+  {
+    m_arg_x_filename = "no value";
+    return true;
+  }
+
+  if(value.empty())
+  {
+    m_arg_x_filename = "empty string";
+    return true;
+  }
+
+  m_arg_x_filename = value;
+  if(value == "error")
+  {
+    throw Glib::OptionError(Glib::OptionError::BAD_VALUE,
+      "on_option_arg_filename called with value = " + m_arg_x_filename);
+  }
+  return value != "false";
+}
+
 
 int main(int argc, char** argv)
 {
@@ -111,7 +194,10 @@ int main(int argc, char** argv)
   //./example --help
   
   Glib::init();
-   
+
+  //Set up the current locale.
+  setlocale(LC_ALL, "");
+
   Glib::OptionContext context;
   
   ExampleOptionGroup group;
@@ -130,7 +216,9 @@ int main(int argc, char** argv)
     "  foo = " << group.m_arg_foo << std::endl << 
     "  filename = " << group.m_arg_filename << std::endl <<
     "  activate_something = " << (group.m_arg_boolean ? "enabled" : "disabled") << std::endl <<
-    "  goo = " << group.m_arg_goo << std::endl;
+    "  goo = " << group.m_arg_goo << std::endl <<
+    "  x-string = " << group.m_arg_x_string << std::endl <<
+    "  x-filename = " << group.m_arg_x_filename << std::endl;
     
   //This one shows the results of multiple instance of the same option, such as --list=1 --list=a --list=b
   std::cout << "  list = ";
diff --git a/glib/src/optionentry.hg b/glib/src/optionentry.hg
index 74d74de..5bab0e5 100644
--- a/glib/src/optionentry.hg
+++ b/glib/src/optionentry.hg
@@ -75,20 +75,20 @@ public:
   _MEMBER_SET(short_name, short_name, gchar, gchar)
   
   _MEMBER_GET(flags, flags, int, int)
+  /** Set one or more OptionEntry::Flags.
+   * Do not set FLAG_FILENAME. Character encoding is chosen when the OptionEntry
+   * is added to an OptionGroup.
+   */
   _MEMBER_SET(flags, flags, int, int)
   
-  //TODO: G_OPTION_ARG_CALLBACK,
-    
   _MEMBER_GET(description, description, Glib::ustring, const char*)
 
   void set_description(const Glib::ustring& value);
   
-  
   _MEMBER_GET(arg_description, arg_description, Glib::ustring, const char*)
 
   void set_arg_description(const Glib::ustring& value);
   
-  
   GOptionEntry*       gobj()       { return gobject_; }
   const GOptionEntry* gobj() const { return gobject_; }
   
diff --git a/glib/src/optiongroup.ccg b/glib/src/optiongroup.ccg
index ed5e45a..358d866 100644
--- a/glib/src/optiongroup.ccg
+++ b/glib/src/optiongroup.ccg
@@ -31,25 +31,79 @@ namespace Glib
 namespace //anonymous
 {
 
+//A pointer to an OptionArgCallback instance is stored in CppOptionEntry::cpparg_
+//when a callback function shall parse the command option's value.
+class OptionArgCallback
+{
+public:
+  OptionArgCallback(const OptionGroup::SlotOptionArgString& slot)
+  : slot_string(new OptionGroup::SlotOptionArgString(slot)), slot_filename(0)
+  { }
+
+  OptionArgCallback(const OptionGroup::SlotOptionArgFilename& slot)
+  : slot_string(0), slot_filename(new OptionGroup::SlotOptionArgFilename(slot))
+  { }
+
+  bool is_filename_option() const { return slot_filename != 0; }
+  const OptionGroup::SlotOptionArgString* get_slot_string() const { return slot_string; }
+  const OptionGroup::SlotOptionArgFilename* get_slot_filename() const { return slot_filename; }
+
+  ~OptionArgCallback()
+  {
+    delete slot_string;
+    delete slot_filename;
+  }
+
+private:
+  //One of these slot pointers is 0 and the other one points to a slot.
+  OptionGroup::SlotOptionArgString* slot_string;
+  OptionGroup::SlotOptionArgFilename* slot_filename;
+
+  //Not copyable
+  OptionArgCallback(const OptionArgCallback&);
+  OptionArgCallback& operator=(const OptionArgCallback&);
+};
+
 extern "C"
 {
 
-static gboolean g_callback_pre_parse(GOptionContext* context, GOptionGroup* /* group */, gpointer data, GError** /* TODO error */)
+static gboolean g_callback_pre_parse(GOptionContext* context,
+  GOptionGroup* /* group */, gpointer data, GError** error)
 {
   OptionContext cppContext(context, false /* take_ownership */);
-  //OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
 
   OptionGroup* option_group = static_cast<OptionGroup*>(data);
-  if(option_group)
-    return option_group->on_pre_parse(cppContext, *option_group);
-  else
+  if(!option_group)
+  {
+    OptionError(OptionError::FAILED, "Glib::OptionGroup: g_callback_pre_parse(): "
+      "No OptionGroup pointer available").propagate(error);
     return false;
+  }
+
+  try
+  {
+    return option_group->on_pre_parse(cppContext, *option_group);
+  }
+  catch(Glib::Error& err)
+  {
+    err.propagate(error);
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+  return false;
 }
 
-static void g_callback_error(GOptionContext* context, GOptionGroup* /* group */, gpointer data, GError** /* TODO error*/)
+static void g_callback_error(GOptionContext* context,
+  GOptionGroup* /* group */, gpointer data, GError** /* TODO error */)
 {
+  // TODO GError** error is input data containing information on an error that
+  // has occurred before this function is called. When API can be broken,
+  // the function prototype of on_error ought to be changed to
+  // void on_error(OptionContext& context, Error& error).
+
   OptionContext cppContext(context, false /* take_ownership */);
-  //OptionGroup cppGroup(group); //Maybe this should be option_group.
 
   OptionGroup* option_group = static_cast<OptionGroup*>(data);
   if(option_group)
@@ -86,33 +140,133 @@ static void OptionGroup_Translate_glibmm_callback_destroy(void* data)
 
 //static
 gboolean OptionGroup::post_parse_callback(GOptionContext* context,
-  GOptionGroup* /* group */, gpointer data, GError** /* TODO error */)
+  GOptionGroup* /* group */, gpointer data, GError** error)
 {
   OptionContext cppContext(context, false /* take_ownership */);
-  //OptionGroup cppGroup(group, true /* take_copy */); //Maybe this should be option_group.
 
   OptionGroup* option_group = static_cast<OptionGroup*>(data);
-  if(option_group)
+  if(!option_group)
   {
-    //The C args have now been given values by g_option_context_parse().
-    //Convert C values to C++ values:
+    OptionError(OptionError::FAILED, "Glib::OptionGroup::post_parse_callback(): "
+      "No OptionGroup pointer available").propagate(error);
+    return false;
+  }
 
-    for(type_map_entries::iterator iter = option_group->map_entries_.begin();
-        iter != option_group->map_entries_.end(); ++iter)
-    {
-      CppOptionEntry& cpp_entry = iter->second;
-      cpp_entry.convert_c_to_cpp();
-    }
+  //The C args have now been given values by g_option_context_parse().
+  //Convert C values to C++ values:
+  for(type_map_entries::iterator iter = option_group->map_entries_.begin();
+      iter != option_group->map_entries_.end(); ++iter)
+  {
+    CppOptionEntry& cpp_entry = iter->second;
+    cpp_entry.convert_c_to_cpp();
+  }
+
+  try
+  {
     return option_group->on_post_parse(cppContext, *option_group);
   }
+  catch(Glib::Error& err)
+  {
+    err.propagate(error);
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+  return false;
+}
+
+//static
+gboolean OptionGroup::option_arg_callback(const gchar* option_name, const gchar* value,
+  gpointer data, GError** error)
+{
+  const Glib::ustring cpp_option_name(option_name);
+  const OptionGroup* const option_group = static_cast<const OptionGroup*>(data);
+  if(!option_group)
+  {
+    OptionError(OptionError::FAILED, "Glib::OptionGroup::option_arg_callback(): "
+      "No OptionGroup pointer available for option " + cpp_option_name).propagate(error);
+    return false;
+  }
+
+  //option_name is either a single dash followed by a single letter (for a
+  //short name) or two dashes followed by a long option name.
+  OptionGroup::type_map_entries::const_iterator iterFind = option_group->map_entries_.end();
+  if(option_name[1] == '-')
+  {
+    //Long option name.
+    const Glib::ustring long_option_name = Glib::ustring(option_name+2);
+    iterFind = option_group->map_entries_.find(long_option_name);
+  }
   else
+  {
+    //Short option name.
+    const gchar short_option_name = option_name[1];
+    for(iterFind = option_group->map_entries_.begin();
+        iterFind != option_group->map_entries_.end(); ++iterFind)
+    {
+      const OptionGroup::CppOptionEntry& cppOptionEntry = iterFind->second;
+      if (cppOptionEntry.entry_ &&
+          cppOptionEntry.entry_->get_short_name() == short_option_name)
+        break;
+    }
+  }
+
+  if(iterFind == option_group->map_entries_.end())
+  {
+    OptionError(OptionError::UNKNOWN_OPTION, "Glib::OptionGroup::option_arg_callback(): "
+      "Unknown option " + cpp_option_name).propagate(error);
+    return false;
+  }
+
+  const OptionGroup::CppOptionEntry& cppOptionEntry = iterFind->second;
+  if (cppOptionEntry.carg_type_ != G_OPTION_ARG_CALLBACK)
+  {
+    OptionError(OptionError::FAILED, "Glib::OptionGroup::option_arg_callback() "
+      "called for non-callback option " + cpp_option_name).propagate(error);
     return false;
+  }
+
+  const bool has_value = (value != 0);
+  const OptionArgCallback* const option_arg =
+    static_cast<const OptionArgCallback*>(cppOptionEntry.cpparg_);
+  try
+  {
+    if (option_arg->is_filename_option())
+    {
+      const OptionGroup::SlotOptionArgFilename* the_slot = option_arg->get_slot_filename();
+      const std::string cpp_value(value ? value : "");
+      return (*the_slot)(cpp_option_name, cpp_value, has_value);
+    }
+    else
+    {
+      const OptionGroup::SlotOptionArgString* the_slot = option_arg->get_slot_string();
+      const Glib::ustring cpp_value(value ? value : "");
+      return (*the_slot)(cpp_option_name, cpp_value, has_value);
+    }
+  }
+  catch(Glib::Error& err)
+  {
+    err.propagate(error);
+  }
+  catch(...)
+  {
+    Glib::exception_handlers_invoke();
+  }
+  return false;
 }
 
 OptionGroup::OptionGroup(const Glib::ustring& name, const Glib::ustring& description, const Glib::ustring& help_description)
-: gobject_( g_option_group_new(name.c_str(), description.c_str(), help_description.c_str(), this, 0 /* destroy_func */) ),
+: gobject_( g_option_group_new(name.c_str(), description.c_str(), help_description.c_str(),
+            this /* user_data */, 0 /* destroy_func */) ),
   has_ownership_(true)
 {
+  //g_callback_pre_parse(), post_parse_callback(), g_callback_error(), and
+  //option_arg_callback() depend on user_data being this. The first three
+  //functions get a GOptionGroup*, but it would not be correct to use it for
+  //creating a new OptionGroup. They must call their virtual functions in the
+  //original OptionGroup instance.
+
   //Connect callbacks, so that derived classes can override the virtual methods:
   g_option_group_set_parse_hooks(gobj(), &g_callback_pre_parse, &post_parse_callback);
   g_option_group_set_error_hook(gobj(), &g_callback_error);
@@ -191,7 +345,30 @@ void OptionGroup::add_entry_filename(const OptionEntry& entry, vecstrings& arg)
 {
   add_entry_with_wrapper(entry, G_OPTION_ARG_FILENAME_ARRAY, &arg);
 }
- 
+
+// When the command argument value is to be parsed by a user-supplied function
+// (indicated by G_OPTION_ARG_CALLBACK), the FLAG_FILENAME in 'entry' is ignored.
+// set_c_arg_default() clears or sets it as required in a copy of 'entry'.
+//
+// The glib API is inconsistent here. The choice between UTF-8 and filename
+// encoding is done with G_OPTION_ARG_STRING, G_OPTION_ARG_FILENAME,
+// G_OPTION_ARG_STRING_ARRAY, and G_OPTION_ARG_FILENAME_ARRAY, which in glibmm
+// are set by OptionGroup::add_entry[_filename]. But when a callback function
+// is chosen, there is only G_OPTION_ARG_CALLBACK, and the encoding is chosen
+// with G_OPTION_FLAG_FILENAME. Other option flags are set by OptionEntry::set_flags().
+
+void OptionGroup::add_entry(const OptionEntry& entry, const SlotOptionArgString& slot)
+{
+  //The OptionArgCallback is deleted in release_c_arg().
+  add_entry_with_wrapper(entry, G_OPTION_ARG_CALLBACK, new OptionArgCallback(slot));
+}
+
+void OptionGroup::add_entry_filename(const OptionEntry& entry, const SlotOptionArgFilename& slot)
+{
+  //The OptionArgCallback is deleted in release_c_arg().
+  add_entry_with_wrapper(entry, G_OPTION_ARG_CALLBACK, new OptionArgCallback(slot));
+}
+
 void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg arg_type, void* cpp_arg)
 {
   const Glib::ustring name = entry.get_long_name();
@@ -199,6 +376,10 @@ void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg ar
   if( iterFind == map_entries_.end() ) //If we have not added this entry already
   {
     CppOptionEntry cppEntry;
+    //g_option_group_add_entry() does not take its own copy, so we must keep the instance alive.
+    cppEntry.entry_ = new OptionEntry(entry);
+    //cppEntry.entry_ is deleted in release_c_arg(), via the destructor.
+
     cppEntry.carg_type_ = arg_type;
     cppEntry.allocate_c_arg();
     cppEntry.set_c_arg_default(cpp_arg);
@@ -206,10 +387,6 @@ void OptionGroup::add_entry_with_wrapper(const OptionEntry& entry, GOptionArg ar
     cppEntry.cpparg_ = cpp_arg;
 
     //Give the information to the C API:
-
-    cppEntry.entry_ = new OptionEntry(entry); //g_option_group_add_entry() does not take its own copy, so we must keep the instance alive. */
-    //cppEntry.entry_ is deleted in release_c_arg(), via the destructor.
-
     cppEntry.entry_->gobj()->arg = arg_type;
     cppEntry.entry_->gobj()->arg_data = cppEntry.carg_;
 
@@ -256,7 +433,8 @@ void OptionGroup::CppOptionEntry::allocate_c_arg()
   //Create an instance of the appropriate C type.
   //This will be destroyed in the OptionGroup destructor.
   //
-  //We must also call set_c_arg_default() to give these C types the specified defaults based on the C++-typed arguments.
+  //We must also call set_c_arg_default() to give these C types the specified
+  //defaults based on the C++-typed arguments.
   switch(carg_type_)
   {
     case G_OPTION_ARG_STRING: //The char* will be for UTF8 strins.
@@ -303,6 +481,13 @@ void OptionGroup::CppOptionEntry::allocate_c_arg()
 
       break;
     }
+    case G_OPTION_ARG_CALLBACK:
+    {
+      //The C arg pointer is a function pointer.
+      carg_ = reinterpret_cast<void*>(&OptionGroup::option_arg_callback);
+
+      break;
+    }
     default:
     {
       break;
@@ -389,6 +574,22 @@ void OptionGroup::CppOptionEntry::set_c_arg_default(void* cpp_arg)
       }
       break;
     }
+    case G_OPTION_ARG_CALLBACK:
+    {
+      //No value to set here. The arg pointer is a function pointer.
+
+      //Set or clear FLAG_FILENAME in *entry_.
+      const OptionArgCallback* const option_arg = static_cast<const OptionArgCallback*>(cpp_arg);
+      if (option_arg->is_filename_option())
+      {
+        entry_->set_flags(entry_->get_flags() | OptionEntry::FLAG_FILENAME);
+      }
+      else
+      {
+        entry_->set_flags(entry_->get_flags() & ~OptionEntry::FLAG_FILENAME);
+      }
+      break;
+    }
     default:
     {
       break;
@@ -440,11 +641,18 @@ void OptionGroup::CppOptionEntry::release_c_arg()
 
         break;
       }
+      case G_OPTION_ARG_CALLBACK:
+      {
+        //Delete the OptionArgCallback instance that was allocated by add_entry()
+        //or add_entry_filename().
+        OptionArgCallback* option_arg = static_cast<OptionArgCallback*>(cpparg_);
+        delete option_arg;
+        cpparg_ = 0;
+
+        break;
+      }
       default:
       {
-        /* TODO:
-        G_OPTION_ARG_CALLBACK,
-        */
         break;
       }
     }
@@ -560,11 +768,14 @@ void OptionGroup::CppOptionEntry::convert_c_to_cpp()
       *(static_cast<bool*>(cpparg_)) = *(static_cast<gboolean*>(carg_));
       break;
     }
+    case G_OPTION_ARG_CALLBACK:
+    {
+      //Nothing to convert here. That's a task for the callback function
+      //(the SlotOptionArgString or SlotOptionArgFilename).
+      break;
+    }
     default:
     {
-      /* TODO:
-      G_OPTION_ARG_CALLBACK,
-      */
       break;
     }
   }
diff --git a/glib/src/optiongroup.hg b/glib/src/optiongroup.hg
index 8d687b2..f31015d 100644
--- a/glib/src/optiongroup.hg
+++ b/glib/src/optiongroup.hg
@@ -51,6 +51,16 @@ public:
    */
   typedef sigc::slot<Glib::ustring, const Glib::ustring&> SlotTranslate;
 
+  /** For example bool on_option_arg_string(const Glib::ustring& option_name,
+   *  const Glib::ustring& value, bool has_value);.
+   */
+  typedef sigc::slot<bool, const Glib::ustring&, const Glib::ustring&, bool> SlotOptionArgString;
+   
+  /** For example bool on_option_arg_filename(const Glib::ustring& option_name,
+   *  const std::string& value, bool has_value);.
+   */
+  typedef sigc::slot<bool, const Glib::ustring&, const std::string&, bool> SlotOptionArgFilename;
+
   OptionGroup(const Glib::ustring& name, const Glib::ustring& description, const Glib::ustring& help_description = Glib::ustring());
 
   /** This always takes ownership of the underlying GOptionGroup, 
@@ -81,6 +91,8 @@ public:
   void add_entry_filename(const OptionEntry& entry, std::string& arg);  
   void add_entry(const OptionEntry& entry, vecustrings& arg);
   void add_entry_filename(const OptionEntry& entry, vecstrings& arg);
+  void add_entry(const OptionEntry& entry, const SlotOptionArgString& slot);
+  void add_entry_filename(const OptionEntry& entry, const SlotOptionArgFilename& slot);
 
   /** Sets the function which is used to translate user-visible strings, for
    * --help output. Different groups can use a different SlotTranslate. If a
@@ -128,6 +140,9 @@ protected:
   static gboolean post_parse_callback(GOptionContext* context,
     GOptionGroup* group, gpointer data, GError** error);
 
+  static gboolean option_arg_callback(const gchar* option_name, const gchar* value,
+    gpointer data, GError** error);
+
   //Map of entry names to CppOptionEntry:
   typedef std::map<Glib::ustring, CppOptionEntry> type_map_entries;
   type_map_entries map_entries_;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]