From 95bef9040273f2ab5dd1bd1c2346502d798e3bb1 Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Tue, 12 Apr 2022 23:44:51 -0400 Subject: [PATCH 1/7] add env var to --config Signed-off-by: Mabel Zhang --- src/cmd/cmdgui.rb.in | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/cmd/cmdgui.rb.in b/src/cmd/cmdgui.rb.in index 2b766662f..fc31d929b 100644 --- a/src/cmd/cmdgui.rb.in +++ b/src/cmd/cmdgui.rb.in @@ -182,8 +182,48 @@ class Cmd Importer.extern 'void cmdStandalone(const char *)' Importer.cmdStandalone(options['standalone']) elsif options.key?('config') + + # Check if the passed in config file exists. + if File.exists?(options['config']) + path = options['config'] + # If not, then first check the IGN_GUI_CONFIG_PATH environment + # variable, then IGN_GUI_RESOURCES. + else + configPathEnv = ENV['IGN_GUI_CONFIG_PATH'] + if !configPathEnv.nil? + configPaths = configPathEnv.split(':') + for configPath in configPaths + filePath = File.join(configPath, options['config']) + if File.exists?(filePath) + path = filePath + break + end + end + end + + if path.nil? + resourcePathEnv = ENV['IGN_GUI_RESOURCES'] + if !resourcePathEnv.nil? + resourcePaths = resourcePathEnv.split(':') + for resourcePath in resourcePaths + filePath = File.join(resourcePath, options['config']) + if File.exists?(filePath) + path = filePath + break + end + end + end + end + + if path.nil? + puts "Unable to find config file " + options['config'] + exit(-1) + end + end + Importer.extern 'void cmdConfig(const char *)' - Importer.cmdConfig(options['config']) + Importer.cmdConfig(path) + elsif options.key?('emptywindow') Importer.extern 'void cmdEmptyWindow()' Importer.cmdEmptyWindow() From 9d92fa47e5435b8b460f1265a6bc6ec1a1bc748c Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Wed, 13 Apr 2022 18:46:40 -0400 Subject: [PATCH 2/7] add test Signed-off-by: Mabel Zhang --- src/ign_TEST.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/ign_TEST.cc b/src/ign_TEST.cc index cf3ba5ea7..2049b7e8e 100644 --- a/src/ign_TEST.cc +++ b/src/ign_TEST.cc @@ -96,3 +96,30 @@ TEST_F(CmdLine, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(list)) EXPECT_TRUE(common::exists(common::joinPaths(this->kFakeHome, ".ignition", "gui"))); } + +///////////////////////////////////////////////// +TEST_F(CmdLine, ConfigPath) +{ + std::string cmd = "ign gui --config style.config"; + + // No path + std::string output = custom_exec_str(cmd); + EXPECT_NE(output.find("Unable to find config file style.config"), + std::string::npos) << output; + + // Correct path + auto path = std::string("IGN_GUI_CONFIG_PATH=") + + PROJECT_SOURCE_PATH + "/examples/config "; + + output = custom_exec_str(path + cmd); + EXPECT_EQ(output.find("Unable to find config file style.config"), + std::string::npos) << output; + + // Several paths + path = std::string("IGN_GUI_RESOURCES=banana:") + + PROJECT_SOURCE_PATH + "/examples/config:orange "; + + output = custom_exec_str(path + cmd); + EXPECT_EQ(output.find("Unable to find config file style.config"), + std::string::npos) << output; +} From 5d743578ac7903904a382e514605f14bd0c47ff6 Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Wed, 13 Apr 2022 20:16:38 -0400 Subject: [PATCH 3/7] comment out tests with GUI windows Signed-off-by: Mabel Zhang --- src/ign_TEST.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ign_TEST.cc b/src/ign_TEST.cc index 2049b7e8e..691b76686 100644 --- a/src/ign_TEST.cc +++ b/src/ign_TEST.cc @@ -107,6 +107,7 @@ TEST_F(CmdLine, ConfigPath) EXPECT_NE(output.find("Unable to find config file style.config"), std::string::npos) << output; + /* Need to find a way to close window automatically // Correct path auto path = std::string("IGN_GUI_CONFIG_PATH=") + PROJECT_SOURCE_PATH + "/examples/config "; @@ -122,4 +123,5 @@ TEST_F(CmdLine, ConfigPath) output = custom_exec_str(path + cmd); EXPECT_EQ(output.find("Unable to find config file style.config"), std::string::npos) << output; + */ } From c51e161a2f8e9407e9100772b43924c6d36b4812 Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Thu, 14 Apr 2022 18:34:15 -0400 Subject: [PATCH 4/7] move env var logic to Application Signed-off-by: Mabel Zhang --- src/Application.cc | 36 +++++++++++++++++++++++++++++++---- src/Application_TEST.cc | 22 +++++++++++++++++++++ src/cmd/cmdgui.rb.in | 42 +---------------------------------------- src/ign_TEST.cc | 29 ---------------------------- 4 files changed, 55 insertions(+), 74 deletions(-) diff --git a/src/Application.cc b/src/Application.cc index 95d1e2a55..7f79e09d0 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -19,7 +19,9 @@ #include #include +#include #include +#include #include #include @@ -222,24 +224,50 @@ bool Application::LoadConfig(const std::string &_config) return false; } + std::string configFull = _config; + + // Check if the passed in config file exists. + // (If the default config path doesn't exist yet, it's expected behavior. + // It will be created the first time the user presses "Save configuration".) + if (!common::exists(configFull) && (configFull != this->DefaultConfigPath())) + { + // If not, then check the IGN_GUI_RESOURCE_PATH environment variable + std::string configPathEnv; + common::env("IGN_GUI_RESOURCE_PATH", configPathEnv); + + if (!configPathEnv.empty()) + { + std::vector parentPaths = common::Split(configPathEnv, ':'); + for (auto parentPath : parentPaths) + { + std::string tempPath = common::joinPaths(parentPath, configFull); + if (common::exists(tempPath)) + { + configFull = tempPath; + break; + } + } + } + } + // Use tinyxml to read config tinyxml2::XMLDocument doc; - auto success = !doc.LoadFile(_config.c_str()); + auto success = !doc.LoadFile(configFull.c_str()); if (!success) { // We do not show an error message if the default config path doesn't exist // yet. It's expected behavior, it will be created the first time the user // presses "Save configuration". - if (_config != this->DefaultConfigPath()) + if (configFull != this->DefaultConfigPath()) { - ignerr << "Failed to load file [" << _config << "]: XMLError" + ignerr << "Failed to load file [" << configFull << "]: XMLError" << std::endl; } return false; } - ignmsg << "Loading config [" << _config << "]" << std::endl; + ignmsg << "Loading config [" << configFull << "]" << std::endl; // Clear all previous plugins auto plugins = this->dataPtr->mainWin->findChildren(); diff --git a/src/Application_TEST.cc b/src/Application_TEST.cc index 5d575a3c9..f65bf76ba 100644 --- a/src/Application_TEST.cc +++ b/src/Application_TEST.cc @@ -172,6 +172,28 @@ TEST(ApplicationTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(LoadConfig)) auto testSourcePath = std::string(PROJECT_SOURCE_PATH) + "/test/"; EXPECT_TRUE(app.LoadConfig(testSourcePath + "config/test.config")); } + + // Test environment variable and relative path + { + // Environment variable not set + Application app(g_argc, g_argv); + EXPECT_FALSE(app.LoadConfig("ignore.config")); + + // Invalid path + setenv("IGN_GUI_RESOURCE_PATH", "invalidPath", 1); + EXPECT_FALSE(app.LoadConfig("ignore.config")); + + // Valid path + setenv("IGN_GUI_RESOURCE_PATH", + (std::string(PROJECT_SOURCE_PATH) + "/test/config").c_str(), 1); + EXPECT_TRUE(app.LoadConfig("ignore.config")); + + // Multiple paths, one valid + setenv("IGN_GUI_RESOURCE_PATH", + ("banana:" + std::string(PROJECT_SOURCE_PATH) + "/test/config" + + ":orange").c_str(), 1); + EXPECT_TRUE(app.LoadConfig("ignore.config")); + } } ////////////////////////////////////////////////// diff --git a/src/cmd/cmdgui.rb.in b/src/cmd/cmdgui.rb.in index fc31d929b..2b766662f 100644 --- a/src/cmd/cmdgui.rb.in +++ b/src/cmd/cmdgui.rb.in @@ -182,48 +182,8 @@ class Cmd Importer.extern 'void cmdStandalone(const char *)' Importer.cmdStandalone(options['standalone']) elsif options.key?('config') - - # Check if the passed in config file exists. - if File.exists?(options['config']) - path = options['config'] - # If not, then first check the IGN_GUI_CONFIG_PATH environment - # variable, then IGN_GUI_RESOURCES. - else - configPathEnv = ENV['IGN_GUI_CONFIG_PATH'] - if !configPathEnv.nil? - configPaths = configPathEnv.split(':') - for configPath in configPaths - filePath = File.join(configPath, options['config']) - if File.exists?(filePath) - path = filePath - break - end - end - end - - if path.nil? - resourcePathEnv = ENV['IGN_GUI_RESOURCES'] - if !resourcePathEnv.nil? - resourcePaths = resourcePathEnv.split(':') - for resourcePath in resourcePaths - filePath = File.join(resourcePath, options['config']) - if File.exists?(filePath) - path = filePath - break - end - end - end - end - - if path.nil? - puts "Unable to find config file " + options['config'] - exit(-1) - end - end - Importer.extern 'void cmdConfig(const char *)' - Importer.cmdConfig(path) - + Importer.cmdConfig(options['config']) elsif options.key?('emptywindow') Importer.extern 'void cmdEmptyWindow()' Importer.cmdEmptyWindow() diff --git a/src/ign_TEST.cc b/src/ign_TEST.cc index 691b76686..cf3ba5ea7 100644 --- a/src/ign_TEST.cc +++ b/src/ign_TEST.cc @@ -96,32 +96,3 @@ TEST_F(CmdLine, IGN_UTILS_TEST_ENABLED_ONLY_ON_LINUX(list)) EXPECT_TRUE(common::exists(common::joinPaths(this->kFakeHome, ".ignition", "gui"))); } - -///////////////////////////////////////////////// -TEST_F(CmdLine, ConfigPath) -{ - std::string cmd = "ign gui --config style.config"; - - // No path - std::string output = custom_exec_str(cmd); - EXPECT_NE(output.find("Unable to find config file style.config"), - std::string::npos) << output; - - /* Need to find a way to close window automatically - // Correct path - auto path = std::string("IGN_GUI_CONFIG_PATH=") + - PROJECT_SOURCE_PATH + "/examples/config "; - - output = custom_exec_str(path + cmd); - EXPECT_EQ(output.find("Unable to find config file style.config"), - std::string::npos) << output; - - // Several paths - path = std::string("IGN_GUI_RESOURCES=banana:") + - PROJECT_SOURCE_PATH + "/examples/config:orange "; - - output = custom_exec_str(path + cmd); - EXPECT_EQ(output.find("Unable to find config file style.config"), - std::string::npos) << output; - */ -} From f658daa3234ca176f8e29b949fa8f3acbe17436d Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Thu, 14 Apr 2022 18:54:03 -0400 Subject: [PATCH 5/7] add env var to usage msg Signed-off-by: Mabel Zhang --- src/cmd/cmdgui.rb.in | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd/cmdgui.rb.in b/src/cmd/cmdgui.rb.in index 2b766662f..839db2f26 100644 --- a/src/cmd/cmdgui.rb.in +++ b/src/cmd/cmdgui.rb.in @@ -52,7 +52,10 @@ COMMANDS = { 'gui' => " The default verbosity is 1, use -v without\n"\ " arguments for level 3.\n"\ "\n" + - COMMON_OPTIONS, + COMMON_OPTIONS + "\n\n" + + "Environment variables: \n"\ + " IGN_GUI_RESOURCE_PATH Colon separated paths used to locate GUI \n"\ + " resources such as configuration files. \n"\ } # From 89371e5539ae1b0d4188a3d43edbf65312318332 Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Thu, 14 Apr 2022 19:08:26 -0400 Subject: [PATCH 6/7] change env var name to GZ_* Signed-off-by: Mabel Zhang --- src/Application.cc | 4 ++-- src/Application_TEST.cc | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Application.cc b/src/Application.cc index 7f79e09d0..38facd1c4 100644 --- a/src/Application.cc +++ b/src/Application.cc @@ -231,9 +231,9 @@ bool Application::LoadConfig(const std::string &_config) // It will be created the first time the user presses "Save configuration".) if (!common::exists(configFull) && (configFull != this->DefaultConfigPath())) { - // If not, then check the IGN_GUI_RESOURCE_PATH environment variable + // If not, then check environment variable std::string configPathEnv; - common::env("IGN_GUI_RESOURCE_PATH", configPathEnv); + common::env("GZ_GUI_RESOURCE_PATH", configPathEnv); if (!configPathEnv.empty()) { diff --git a/src/Application_TEST.cc b/src/Application_TEST.cc index f65bf76ba..9ca02cc90 100644 --- a/src/Application_TEST.cc +++ b/src/Application_TEST.cc @@ -180,16 +180,16 @@ TEST(ApplicationTest, IGN_UTILS_TEST_DISABLED_ON_WIN32(LoadConfig)) EXPECT_FALSE(app.LoadConfig("ignore.config")); // Invalid path - setenv("IGN_GUI_RESOURCE_PATH", "invalidPath", 1); + setenv("GZ_GUI_RESOURCE_PATH", "invalidPath", 1); EXPECT_FALSE(app.LoadConfig("ignore.config")); // Valid path - setenv("IGN_GUI_RESOURCE_PATH", + setenv("GZ_GUI_RESOURCE_PATH", (std::string(PROJECT_SOURCE_PATH) + "/test/config").c_str(), 1); EXPECT_TRUE(app.LoadConfig("ignore.config")); // Multiple paths, one valid - setenv("IGN_GUI_RESOURCE_PATH", + setenv("GZ_GUI_RESOURCE_PATH", ("banana:" + std::string(PROJECT_SOURCE_PATH) + "/test/config" + ":orange").c_str(), 1); EXPECT_TRUE(app.LoadConfig("ignore.config")); From 6d25226dfecdd9732b07567a2745d9f63daf1fd5 Mon Sep 17 00:00:00 2001 From: Mabel Zhang Date: Tue, 3 May 2022 03:32:31 -0400 Subject: [PATCH 7/7] tutorial update; print update Signed-off-by: Mabel Zhang --- src/cmd/cmdgui.rb.in | 2 +- tutorials/07_config.md | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/cmd/cmdgui.rb.in b/src/cmd/cmdgui.rb.in index 839db2f26..5ecdd4260 100644 --- a/src/cmd/cmdgui.rb.in +++ b/src/cmd/cmdgui.rb.in @@ -54,7 +54,7 @@ COMMANDS = { 'gui' => "\n" + COMMON_OPTIONS + "\n\n" + "Environment variables: \n"\ - " IGN_GUI_RESOURCE_PATH Colon separated paths used to locate GUI \n"\ + " GZ_GUI_RESOURCE_PATH Colon separated paths used to locate GUI \n"\ " resources such as configuration files. \n"\ } diff --git a/tutorials/07_config.md b/tutorials/07_config.md index 240ac6786..8178cbda6 100644 --- a/tutorials/07_config.md +++ b/tutorials/07_config.md @@ -15,9 +15,19 @@ By default, Ignition GUI will load the config file at Configuration files can also be loaded from the command line or through the C++ API. -From the command line, use the `--config` / `-c` option, for example: +From the command line, use the `--config` / `-c` option. +For example, you can specify an absolute path: -`ign gui -c path/to/example.config` +`ign gui -c /absolute/path/to/example.config` + +Or a path relative to the current working directory: + +`ign gui -c relative/path/to/example.config` + +Or a path relative to a custom directory, which you can specify by setting the +environment variable `GZ_GUI_RESOURCE_PATH`, like so: + +`GZ_GUI_RESOURCE_PATH=/absolute/path/to/ ign gui --config example.config` From the C++ API, pass the file path to [Application::LoadConfig](https://ignitionrobotics.org/api/gui/3.0/classignition_1_1gui_1_1Application.html#a03c4c3a1b1e58cc4bff05658f21fff17).