[gtkmm-documentation] Application example: Show the new command-line parsing API



commit 4fd9b57fa81634ef269a5932cd0f3ea4de63f9db
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Wed May 14 15:38:13 2014 +0200

    Application example: Show the new command-line parsing API
    
    * examples/Makefile.am: Delete exampleoptiongroup.[cc|h].
    * examples/book/application/command_line_handling/exampleapplication.[cc|h]:
    Show how to use Gio::Application::add_main_option_entry().
    * examples/book/application/command_line_handling/exampleoptiongroup.[cc|h]:
    Deleted files. Bug #727822.

 examples/Makefile.am                               |    2 -
 .../command_line_handling/exampleapplication.cc    |  166 +++++++++++++++-----
 .../command_line_handling/exampleapplication.h     |    9 +
 .../command_line_handling/exampleoptiongroup.cc    |   42 -----
 .../command_line_handling/exampleoptiongroup.h     |   33 ----
 5 files changed, 138 insertions(+), 114 deletions(-)
---
diff --git a/examples/Makefile.am b/examples/Makefile.am
index fe89ad8..fd34320 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -158,8 +158,6 @@ book_application_simple_example_SOURCES =           \
 book_application_command_line_handling_example_SOURCES =               \
        book/application/command_line_handling/exampleapplication.cc    \
        book/application/command_line_handling/exampleapplication.h     \
-       book/application/command_line_handling/exampleoptiongroup.cc    \
-       book/application/command_line_handling/exampleoptiongroup.h     \
        book/application/command_line_handling/examplewindow.cc \
        book/application/command_line_handling/examplewindow.h  \
        book/application/command_line_handling/main.cc
diff --git a/examples/book/application/command_line_handling/exampleapplication.cc 
b/examples/book/application/command_line_handling/exampleapplication.cc
index b202376..4c2c627 100644
--- a/examples/book/application/command_line_handling/exampleapplication.cc
+++ b/examples/book/application/command_line_handling/exampleapplication.cc
@@ -16,7 +16,6 @@
 
 #include "exampleapplication.h"
 #include "examplewindow.h"
-#include "exampleoptiongroup.h"
 #include <iostream>
 
 ExampleApplication::ExampleApplication()
@@ -24,6 +23,32 @@ ExampleApplication::ExampleApplication()
     Gio::ApplicationFlags(Gio::APPLICATION_HANDLES_OPEN | Gio::APPLICATION_HANDLES_COMMAND_LINE))
 {
   Glib::set_application_name("Gtk::Application Example");
+
+  signal_handle_local_options().connect(
+    sigc::mem_fun(*this, &ExampleApplication::on_handle_local_options), false);
+
+  //These are just pointless command-line arguments to show the use of the API:
+
+  //A bool.
+  add_main_option_entry(Gio::Application::OPTION_TYPE_BOOL, "foo", 'f', "Enable foo.");
+
+  //A std::string.
+  add_main_option_entry(Gio::Application::OPTION_TYPE_FILENAME, "goo", 'g', "The file name of goo to use.", 
"file");
+
+  //A Glib::ustring.
+  add_main_option_entry(Gio::Application::OPTION_TYPE_STRING, "hoo", 'h', "The hoo to use.", "", 
Glib::OptionEntry::FLAG_HIDDEN);
+
+  //An int.
+  add_main_option_entry(Gio::Application::OPTION_TYPE_INT, "bar", 'b', "The bar to use.", "number");
+
+  //A std::vector<std::string>.
+  add_main_option_entry(Gio::Application::OPTION_TYPE_FILENAME_VECTOR, G_OPTION_REMAINING);
+
+  //Custom-decoded arguments
+  add_main_option_entry(sigc::mem_fun(*this, &ExampleApplication::on_option_arg_string),
+    "string", 's', "The string to use", "string", Glib::OptionEntry::FLAG_OPTIONAL_ARG);
+  add_main_option_entry_filename(sigc::mem_fun(*this, &ExampleApplication::on_option_arg_filename),
+    "name", 'n', "The filename to use", "file");
 }
 
 Glib::RefPtr<ExampleApplication> ExampleApplication::create()
@@ -77,9 +102,9 @@ void ExampleApplication::on_open(const Gio::Application::type_vec_files& files,
   // The application has been asked to open some files,
   // so let's open a new window for each one.
   //std::cout << "debug: files.size()=" << files.size() << std::endl;
-  for(guint i = 0; i < files.size(); i++)
+  for(std::size_t i = 0; i < files.size(); i++)
   {
-    Glib::RefPtr<Gio::File> file = files[0];
+    Glib::RefPtr<Gio::File> file = files[i];
     if(!file)
     {
       std::cerr << G_STRFUNC << ": file is null." << std::endl;
@@ -92,54 +117,121 @@ void ExampleApplication::on_open(const Gio::Application::type_vec_files& files,
   Gtk::Application::on_open(files, hint);
 }
 
-int ExampleApplication::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>& command_line)
+template <typename T_ArgType>
+static bool get_arg_value(const Glib::RefPtr<Glib::VariantDict>& options, const Glib::ustring& arg_name, 
T_ArgType& arg_value)
 {
-  //Parse command-line arguments that were passed either to the main (first) instance
-  //or to subsequent instances.
-  //Note that this parsing is happening in the main (not remote) instance.
-  int argc = 0;
-  char** argv =        command_line->get_arguments(argc);
-
-  Glib::OptionContext context;
-  ExampleOptionGroup group;
-  context.set_main_group(group);
-
-  try
+  arg_value = T_ArgType();
+  if(options->lookup_value(arg_name, arg_value))
   {
-    context.parse(argc, argv);
+    //std::cout << "The \"" << arg_name << "\" value was in the options VariantDict." << std::endl;
+    return true;
   }
-  catch(const Glib::Error& ex)
+  else
   {
-    std::cerr << "Exception parsing command-line: " << ex.what() << std::endl;
-    std::cerr << context.get_help() << std::endl;
-    return EXIT_FAILURE;
+    GVariant* gvariant = g_variant_dict_lookup_value(options->gobj(), arg_name.c_str(), NULL);
+    if(!gvariant)
+    {
+      std::cerr << "The \"" << arg_name << "\" value was not in the options VariantDict." << std::endl;
+    }
+    else
+    {
+      std::cerr <<
+        "The \"" << arg_name <<"\" value was of type " << g_variant_get_type_string(gvariant) <<
+        " instead of " << Glib::Variant<T_ArgType>::variant_type().get_string() << std::endl;
+    }
   }
 
-  // The GOption documentation says that options without names will be returned
-  // to the application as "rest arguments", meaning they will be left in the argv.
-  std::string filepath;
-  if(argc > 1)
-  {
-    const char* pch = argv[1];
-    if(pch)
-      filepath = pch;
-  }
+  return false;
+}
+
+int ExampleApplication::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>& command_line)
+{
+  const Glib::RefPtr<Glib::VariantDict> options = command_line->get_options_dict();
+  if(!options)
+    std::cerr << G_STRFUNC << ": options is null." << std::endl;
 
-  if(filepath.empty())
+  //Parse command-line arguments that were passed either to the primary (first) instance
+  //or to subsequent instances.
+  //Note that this parsing is happening in the primary (not local) instance.
+  bool foo_value = false;
+  get_arg_value(options, "foo", foo_value);
+  std::string goo_value;
+  get_arg_value(options, "goo", goo_value);
+  Glib::ustring hoo_value;
+  get_arg_value(options, "hoo", hoo_value);
+  int bar_value = 0;
+  get_arg_value(options, "bar", bar_value);
+
+  //The remaining filenames:
+  std::vector<std::string> vec_remaining;
+  get_arg_value(options, G_OPTION_REMAINING, vec_remaining);
+
+  std::cout << "on_command_line(), parsed values: " << std::endl <<
+    "  foo = " << (foo_value ? "true" : "false") << std::endl <<
+    "  goo = " << goo_value << std::endl <<
+    "  hoo = " << hoo_value << std::endl <<
+    "  bar = " << bar_value << std::endl <<
+    "  remaining =";
+  for (std::size_t i = 0; i < vec_remaining.size(); ++i)
+    std::cout << ' ' << vec_remaining[i];
+  std::cout << std::endl; 
+
+  if(vec_remaining.empty())
   {
     //Open a new "document" instead:
     activate();
     return EXIT_FAILURE;
   }
 
-  std::cout << "debug: parsed values: " << std::endl <<
-    "  foo = " << group.m_arg_foo << std::endl <<
-    "  goo = " << group.m_arg_goo << std::endl <<
-    "  filepath = " << filepath << std::endl;
-
-  Glib::RefPtr<Gio::File> file = Gio::File::create_for_path(filepath);
-  open(file);
+  Gio::Application::type_vec_files vec_files;
+  for (std::size_t i = 0; i < vec_remaining.size(); ++i)
+    vec_files.push_back(Gio::File::create_for_path(vec_remaining[i]));
+  open(vec_files);
 
   //The local instance will eventually exit with this status code:
   return EXIT_SUCCESS;
 }
+
+int ExampleApplication::on_handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options)
+{
+  if(!options)
+    std::cerr << G_STRFUNC << ": options is null." << std::endl;
+
+  bool foo_value = false;
+  get_arg_value(options, "foo", foo_value);
+  std::string goo_value;
+  get_arg_value(options, "goo", goo_value);
+  Glib::ustring hoo_value;
+  get_arg_value(options, "hoo", hoo_value);
+  int bar_value = 0;
+  get_arg_value(options, "bar", bar_value);
+
+  std::cout << "on_handle_local_options(), parsed values: " << std::endl <<
+    "  foo = " << (foo_value ? "true" : "false") << std::endl <<
+    "  goo = " << goo_value << std::endl <<
+    "  hoo = " << hoo_value << std::endl <<
+    "  bar = " << bar_value << std::endl;
+
+  //Remove some options to show that we have handled them in the local instance,
+  //so they won't be passed to the primary (remote) instance:
+  options->remove("foo");
+  options->remove("goo");
+
+  return EXIT_SUCCESS;
+}
+
+bool ExampleApplication::on_option_arg_string(const Glib::ustring& option_name,
+  const Glib::ustring& value, bool has_value)
+{
+  std::cout << "on_option_arg_string(), parsed value: " << std::endl <<
+    "  " << option_name << " = " << value << (has_value ? "" : "(no value)") << std::endl;
+  return true;
+}
+
+bool ExampleApplication::on_option_arg_filename(const Glib::ustring& option_name,
+  const std::string& value, bool has_value)
+{
+  std::cout << "on_option_arg_filename(), parsed value: " << std::endl <<
+    "  " << option_name << " = " << value << (has_value ? "" : "(no value)") << std::endl;
+  return true;
+}
diff --git a/examples/book/application/command_line_handling/exampleapplication.h 
b/examples/book/application/command_line_handling/exampleapplication.h
index c968e02..9ad3678 100644
--- a/examples/book/application/command_line_handling/exampleapplication.h
+++ b/examples/book/application/command_line_handling/exampleapplication.h
@@ -34,6 +34,15 @@ protected:
     const Glib::ustring& hint);
   virtual int on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>& command_line);
 
+  //A regular signal handler, because there is no default signal handler for this:
+  int on_handle_local_options(const Glib::RefPtr<Glib::VariantDict>& options);
+
+  //Callback functions for handling some command-line arguments
+  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);
+    
 private:
   void create_window(const Glib::RefPtr<Gio::File>& file = Glib::RefPtr<Gio::File>());
 


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