Skip to content

Commit

Permalink
Add a flexible mechanism to combine user and default plugins
Browse files Browse the repository at this point in the history
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
  • Loading branch information
azeey committed Jul 30, 2024
1 parent 12b4dd0 commit cc1e997
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 106 deletions.
4 changes: 4 additions & 0 deletions include/gz/gui/Application.hh
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ namespace gz::gui
/// \sa InitializeDialogs
public: bool LoadConfig(const std::string &_path);

public: bool LoadWindowConfig(const tinyxml2::XMLElement &_window);

/// \brief Load the configuration from the default config file.
/// \return True if successful
/// \sa SetDefaultConfigPath
Expand All @@ -120,6 +122,8 @@ namespace gz::gui
/// \sa SetDefaultConfigPath
public: std::string DefaultConfigPath();

public: std::string ResolveConfigFile(const std::string &_path);

/// \brief Set the environment variable which defines the paths to
/// look for plugins.
/// \param[in] _env Name of environment variable.
Expand Down
225 changes: 119 additions & 106 deletions src/Application.cc
Original file line number Diff line number Diff line change
Expand Up @@ -325,31 +325,7 @@ 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 environment variable
std::string configPathEnv;
common::env("GZ_GUI_RESOURCE_PATH", configPathEnv);

if (!configPathEnv.empty())
{
std::vector<std::string> parentPaths = common::Split(configPathEnv, ':');
for (const auto &parentPath : parentPaths)
{
std::string tempPath = common::joinPaths(parentPath, configFull);
if (common::exists(tempPath))
{
configFull = tempPath;
break;
}
}
}
}
const auto configFull = this->ResolveConfigFile(_config);

// Use tinyxml to read config
tinyxml2::XMLDocument doc;
Expand Down Expand Up @@ -404,108 +380,114 @@ bool Application::LoadConfig(const std::string &_config)
// Process window properties
if (auto *winElem = doc.FirstChildElement("window"))
{
gzdbg << "Loading window config" << std::endl;
this->LoadWindowConfig(*winElem);
}

this->ApplyConfig();

return true;
}

/////////////////////////////////////////////////
bool Application::LoadWindowConfig(const tinyxml2::XMLElement &_winElem)
{
gzdbg << "Loading window config" << std::endl;

tinyxml2::XMLPrinter printer;
if (!_winElem.Accept(&printer))
{
gzwarn << "There was an error parsing the <window> element"
<< std::endl;
return false;
}
this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr()));

tinyxml2::XMLPrinter printer;
if (!winElem->Accept(&printer))
// Closing behavior.
if (auto *defaultExitActionElem =
_winElem.FirstChildElement("default_exit_action"))
{
ExitAction action{ExitAction::CLOSE_GUI};
const auto value = common::lowercase(defaultExitActionElem->GetText());
if (value == "shutdown_server")
{
gzwarn << "There was an error parsing the <window> element"
<< std::endl;
return false;
action = ExitAction::SHUTDOWN_SERVER;
}
this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr()));

// Closing behavior.
if (auto *defaultExitActionElem =
winElem->FirstChildElement("default_exit_action"))
else if (value != "close_gui" && !value.empty())
{
ExitAction action{ExitAction::CLOSE_GUI};
const auto value = common::lowercase(defaultExitActionElem->GetText());
if (value == "shutdown_server")
{
action = ExitAction::SHUTDOWN_SERVER;
}
else if (value != "close_gui" && !value.empty())
{
gzwarn << "Value '" << value << "' of <default_exit_action> is "
<< "invalid. Allowed values are CLOSE_GUI and SHUTDOWN_SERVER. "
<< "Selecting CLOSE_GUI as fallback." << std::endl;
}
this->dataPtr->mainWin->SetDefaultExitAction(action);
gzwarn << "Value '" << value << "' of <default_exit_action> is "
<< "invalid. Allowed values are CLOSE_GUI and SHUTDOWN_SERVER. "
<< "Selecting CLOSE_GUI as fallback." << std::endl;
}
this->dataPtr->mainWin->SetDefaultExitAction(action);
}

// Dialog on exit
if (auto *dialogOnExitElem = _winElem.FirstChildElement("dialog_on_exit"))
{
bool showDialogOnExit{false};
dialogOnExitElem->QueryBoolText(&showDialogOnExit);
this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit);
}

// Dialog on exit
if (auto *dialogOnExitElem = winElem->FirstChildElement("dialog_on_exit"))
if (auto *dialogOnExitOptionsElem =
_winElem.FirstChildElement("dialog_on_exit_options"))
{
if (auto *promptElem =
dialogOnExitOptionsElem->FirstChildElement("prompt_text"))
{
bool showDialogOnExit{false};
dialogOnExitElem->QueryBoolText(&showDialogOnExit);
this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit);
this->dataPtr->mainWin->SetDialogOnExitText(
QString::fromStdString(promptElem->GetText()));
}

if (auto *dialogOnExitOptionsElem =
winElem->FirstChildElement("dialog_on_exit_options"))
if (auto *showShutdownElem =
dialogOnExitOptionsElem->FirstChildElement("show_shutdown_button"))
{
if (auto *promptElem =
dialogOnExitOptionsElem->FirstChildElement("prompt_text"))
{
this->dataPtr->mainWin->SetDialogOnExitText(
QString::fromStdString(promptElem->GetText()));
}
if (auto *showShutdownElem =
dialogOnExitOptionsElem->FirstChildElement("show_shutdown_button"))
{
bool showShutdownButton{false};
showShutdownElem->QueryBoolText(&showShutdownButton);
this->dataPtr->mainWin->SetExitDialogShowShutdown(showShutdownButton);
}
if (auto *showCloseGuiElem =
dialogOnExitOptionsElem->FirstChildElement("show_close_gui_button"))
{
bool showCloseGuiButton{false};
showCloseGuiElem->QueryBoolText(&showCloseGuiButton);
this->dataPtr->mainWin->SetExitDialogShowCloseGui(showCloseGuiButton);
}
if (auto *shutdownTextElem =
dialogOnExitOptionsElem->FirstChildElement("shutdown_button_text"))
{
this->dataPtr->mainWin->SetExitDialogShutdownText(
QString::fromStdString(shutdownTextElem->GetText()));
}
if (auto *closeGuiTextElem =
dialogOnExitOptionsElem->FirstChildElement("close_gui_button_text"))
{
this->dataPtr->mainWin->SetExitDialogCloseGuiText(
QString::fromStdString(closeGuiTextElem->GetText()));
}
bool showShutdownButton{false};
showShutdownElem->QueryBoolText(&showShutdownButton);
this->dataPtr->mainWin->SetExitDialogShowShutdown(showShutdownButton);
}

// Server control service topic
std::string serverControlService{"/server_control"};
auto *serverControlElem =
winElem->FirstChildElement("server_control_service");
if (nullptr != serverControlElem && nullptr != serverControlElem->GetText())
if (auto *showCloseGuiElem =
dialogOnExitOptionsElem->FirstChildElement("show_close_gui_button"))
{
serverControlService = transport::TopicUtils::AsValidTopic(
serverControlElem->GetText());
bool showCloseGuiButton{false};
showCloseGuiElem->QueryBoolText(&showCloseGuiButton);
this->dataPtr->mainWin->SetExitDialogShowCloseGui(showCloseGuiButton);
}

if (serverControlService.empty())
if (auto *shutdownTextElem =
dialogOnExitOptionsElem->FirstChildElement("shutdown_button_text"))
{
gzerr << "Failed to create valid server control service" << std::endl;
this->dataPtr->mainWin->SetExitDialogShutdownText(
QString::fromStdString(shutdownTextElem->GetText()));
}
else
if (auto *closeGuiTextElem =
dialogOnExitOptionsElem->FirstChildElement("close_gui_button_text"))
{
gzmsg << "Using server control service [" << serverControlService
<< "]" << std::endl;
this->dataPtr->mainWin->SetServerControlService(serverControlService);
this->dataPtr->mainWin->SetExitDialogCloseGuiText(
QString::fromStdString(closeGuiTextElem->GetText()));
}
}

this->ApplyConfig();
// Server control service topic
std::string serverControlService{"/server_control"};
auto *serverControlElem =
_winElem.FirstChildElement("server_control_service");
if (nullptr != serverControlElem && nullptr != serverControlElem->GetText())
{
serverControlService = transport::TopicUtils::AsValidTopic(
serverControlElem->GetText());
}

if (serverControlService.empty())
{
gzerr << "Failed to create valid server control service" << std::endl;
}
else
{
gzmsg << "Using server control service [" << serverControlService
<< "]" << std::endl;
this->dataPtr->mainWin->SetServerControlService(serverControlService);
}
return true;
}

/////////////////////////////////////////////////
bool Application::LoadDefaultConfig()
{
Expand All @@ -524,6 +506,37 @@ std::string Application::DefaultConfigPath()
return this->dataPtr->defaultConfigPath;
}

std::string Application::ResolveConfigFile(const std::string &_path)
{
std::string configFull = _path;

// 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 environment variable
std::string configPathEnv;
common::env("GZ_GUI_RESOURCE_PATH", configPathEnv);

if (!configPathEnv.empty())
{
std::vector<std::string> parentPaths = common::Split(configPathEnv, ':');
for (const auto &parentPath : parentPaths)
{
std::string tempPath = common::joinPaths(parentPath, configFull);
if (common::exists(tempPath))
{
configFull = tempPath;
break;
}
}
}
}

return configFull;
}

/////////////////////////////////////////////////
bool Application::LoadPlugin(const std::string &_filename,
const tinyxml2::XMLElement *_pluginElem)
Expand Down

0 comments on commit cc1e997

Please sign in to comment.