Skip to content

Commit d68674e

Browse files
author
Addisu Z. Taddese
authored
Add a flexible mechanism to combine user and default plugins (#631)
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
1 parent 833883f commit d68674e

File tree

2 files changed

+140
-108
lines changed

2 files changed

+140
-108
lines changed

include/gz/gui/Application.hh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ namespace gz::gui
9898
/// \sa InitializeDialogs
9999
public: bool LoadConfig(const std::string &_path);
100100

101+
/// \brief Load window configuration from XML element.
102+
/// This is the `<window>` element inside a gui config file.
103+
/// \param[in] _window XML element that contains the window configuration
104+
/// \return True if successful
105+
public: bool LoadWindowConfig(const tinyxml2::XMLElement &_window);
106+
101107
/// \brief Load the configuration from the default config file.
102108
/// \return True if successful
103109
/// \sa SetDefaultConfigPath
@@ -118,7 +124,14 @@ namespace gz::gui
118124
/// \return The default configuration path.
119125
/// \sa LoadDefaultConfig
120126
/// \sa SetDefaultConfigPath
121-
public: std::string DefaultConfigPath();
127+
public: std::string DefaultConfigPath() const;
128+
129+
/// \brief Given an input config path, resolve its absolute path,
130+
/// potentially searching for it in locations specified by
131+
/// `GZ_GUI_RESOURCE_PATH`.
132+
/// \param[in] _path Path to a config file. If the path is absolute
133+
/// \return The resolved path
134+
public: std::string ResolveConfigFile(const std::string &_path) const;
122135

123136
/// \brief Set the environment variable which defines the paths to
124137
/// look for plugins.

src/Application.cc

Lines changed: 126 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -325,31 +325,7 @@ bool Application::LoadConfig(const std::string &_config)
325325
return false;
326326
}
327327

328-
std::string configFull = _config;
329-
330-
// Check if the passed in config file exists.
331-
// (If the default config path doesn't exist yet, it's expected behavior.
332-
// It will be created the first time the user presses "Save configuration".)
333-
if (!common::exists(configFull) && (configFull != this->DefaultConfigPath()))
334-
{
335-
// If not, then check environment variable
336-
std::string configPathEnv;
337-
common::env("GZ_GUI_RESOURCE_PATH", configPathEnv);
338-
339-
if (!configPathEnv.empty())
340-
{
341-
std::vector<std::string> parentPaths = common::Split(configPathEnv, ':');
342-
for (const auto &parentPath : parentPaths)
343-
{
344-
std::string tempPath = common::joinPaths(parentPath, configFull);
345-
if (common::exists(tempPath))
346-
{
347-
configFull = tempPath;
348-
break;
349-
}
350-
}
351-
}
352-
}
328+
const auto configFull = this->ResolveConfigFile(_config);
353329

354330
// Use tinyxml to read config
355331
tinyxml2::XMLDocument doc;
@@ -404,108 +380,114 @@ bool Application::LoadConfig(const std::string &_config)
404380
// Process window properties
405381
if (auto *winElem = doc.FirstChildElement("window"))
406382
{
407-
gzdbg << "Loading window config" << std::endl;
383+
this->LoadWindowConfig(*winElem);
384+
}
385+
386+
this->ApplyConfig();
387+
388+
return true;
389+
}
390+
391+
/////////////////////////////////////////////////
392+
bool Application::LoadWindowConfig(const tinyxml2::XMLElement &_winElem)
393+
{
394+
gzdbg << "Loading window config" << std::endl;
395+
396+
tinyxml2::XMLPrinter printer;
397+
if (!_winElem.Accept(&printer))
398+
{
399+
gzwarn << "There was an error parsing the <window> element"
400+
<< std::endl;
401+
return false;
402+
}
403+
this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr()));
408404

409-
tinyxml2::XMLPrinter printer;
410-
if (!winElem->Accept(&printer))
405+
// Closing behavior.
406+
if (auto *defaultExitActionElem =
407+
_winElem.FirstChildElement("default_exit_action"))
408+
{
409+
ExitAction action{ExitAction::CLOSE_GUI};
410+
const auto value = common::lowercase(defaultExitActionElem->GetText());
411+
if (value == "shutdown_server")
411412
{
412-
gzwarn << "There was an error parsing the <window> element"
413-
<< std::endl;
414-
return false;
413+
action = ExitAction::SHUTDOWN_SERVER;
415414
}
416-
this->dataPtr->windowConfig.MergeFromXML(std::string(printer.CStr()));
417-
418-
// Closing behavior.
419-
if (auto *defaultExitActionElem =
420-
winElem->FirstChildElement("default_exit_action"))
415+
else if (value != "close_gui" && !value.empty())
421416
{
422-
ExitAction action{ExitAction::CLOSE_GUI};
423-
const auto value = common::lowercase(defaultExitActionElem->GetText());
424-
if (value == "shutdown_server")
425-
{
426-
action = ExitAction::SHUTDOWN_SERVER;
427-
}
428-
else if (value != "close_gui" && !value.empty())
429-
{
430-
gzwarn << "Value '" << value << "' of <default_exit_action> is "
431-
<< "invalid. Allowed values are CLOSE_GUI and SHUTDOWN_SERVER. "
432-
<< "Selecting CLOSE_GUI as fallback." << std::endl;
433-
}
434-
this->dataPtr->mainWin->SetDefaultExitAction(action);
417+
gzwarn << "Value '" << value << "' of <default_exit_action> is "
418+
<< "invalid. Allowed values are CLOSE_GUI and SHUTDOWN_SERVER. "
419+
<< "Selecting CLOSE_GUI as fallback." << std::endl;
435420
}
421+
this->dataPtr->mainWin->SetDefaultExitAction(action);
422+
}
436423

437-
// Dialog on exit
438-
if (auto *dialogOnExitElem = winElem->FirstChildElement("dialog_on_exit"))
424+
// Dialog on exit
425+
if (auto *dialogOnExitElem = _winElem.FirstChildElement("dialog_on_exit"))
426+
{
427+
bool showDialogOnExit{false};
428+
dialogOnExitElem->QueryBoolText(&showDialogOnExit);
429+
this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit);
430+
}
431+
432+
if (auto *dialogOnExitOptionsElem =
433+
_winElem.FirstChildElement("dialog_on_exit_options"))
434+
{
435+
if (auto *promptElem =
436+
dialogOnExitOptionsElem->FirstChildElement("prompt_text"))
439437
{
440-
bool showDialogOnExit{false};
441-
dialogOnExitElem->QueryBoolText(&showDialogOnExit);
442-
this->dataPtr->mainWin->SetShowDialogOnExit(showDialogOnExit);
438+
this->dataPtr->mainWin->SetDialogOnExitText(
439+
QString::fromStdString(promptElem->GetText()));
443440
}
444-
445-
if (auto *dialogOnExitOptionsElem =
446-
winElem->FirstChildElement("dialog_on_exit_options"))
441+
if (auto *showShutdownElem =
442+
dialogOnExitOptionsElem->FirstChildElement("show_shutdown_button"))
447443
{
448-
if (auto *promptElem =
449-
dialogOnExitOptionsElem->FirstChildElement("prompt_text"))
450-
{
451-
this->dataPtr->mainWin->SetDialogOnExitText(
452-
QString::fromStdString(promptElem->GetText()));
453-
}
454-
if (auto *showShutdownElem =
455-
dialogOnExitOptionsElem->FirstChildElement("show_shutdown_button"))
456-
{
457-
bool showShutdownButton{false};
458-
showShutdownElem->QueryBoolText(&showShutdownButton);
459-
this->dataPtr->mainWin->SetExitDialogShowShutdown(showShutdownButton);
460-
}
461-
if (auto *showCloseGuiElem =
462-
dialogOnExitOptionsElem->FirstChildElement("show_close_gui_button"))
463-
{
464-
bool showCloseGuiButton{false};
465-
showCloseGuiElem->QueryBoolText(&showCloseGuiButton);
466-
this->dataPtr->mainWin->SetExitDialogShowCloseGui(showCloseGuiButton);
467-
}
468-
if (auto *shutdownTextElem =
469-
dialogOnExitOptionsElem->FirstChildElement("shutdown_button_text"))
470-
{
471-
this->dataPtr->mainWin->SetExitDialogShutdownText(
472-
QString::fromStdString(shutdownTextElem->GetText()));
473-
}
474-
if (auto *closeGuiTextElem =
475-
dialogOnExitOptionsElem->FirstChildElement("close_gui_button_text"))
476-
{
477-
this->dataPtr->mainWin->SetExitDialogCloseGuiText(
478-
QString::fromStdString(closeGuiTextElem->GetText()));
479-
}
444+
bool showShutdownButton{false};
445+
showShutdownElem->QueryBoolText(&showShutdownButton);
446+
this->dataPtr->mainWin->SetExitDialogShowShutdown(showShutdownButton);
480447
}
481-
482-
// Server control service topic
483-
std::string serverControlService{"/server_control"};
484-
auto *serverControlElem =
485-
winElem->FirstChildElement("server_control_service");
486-
if (nullptr != serverControlElem && nullptr != serverControlElem->GetText())
448+
if (auto *showCloseGuiElem =
449+
dialogOnExitOptionsElem->FirstChildElement("show_close_gui_button"))
487450
{
488-
serverControlService = transport::TopicUtils::AsValidTopic(
489-
serverControlElem->GetText());
451+
bool showCloseGuiButton{false};
452+
showCloseGuiElem->QueryBoolText(&showCloseGuiButton);
453+
this->dataPtr->mainWin->SetExitDialogShowCloseGui(showCloseGuiButton);
490454
}
491-
492-
if (serverControlService.empty())
455+
if (auto *shutdownTextElem =
456+
dialogOnExitOptionsElem->FirstChildElement("shutdown_button_text"))
493457
{
494-
gzerr << "Failed to create valid server control service" << std::endl;
458+
this->dataPtr->mainWin->SetExitDialogShutdownText(
459+
QString::fromStdString(shutdownTextElem->GetText()));
495460
}
496-
else
461+
if (auto *closeGuiTextElem =
462+
dialogOnExitOptionsElem->FirstChildElement("close_gui_button_text"))
497463
{
498-
gzmsg << "Using server control service [" << serverControlService
499-
<< "]" << std::endl;
500-
this->dataPtr->mainWin->SetServerControlService(serverControlService);
464+
this->dataPtr->mainWin->SetExitDialogCloseGuiText(
465+
QString::fromStdString(closeGuiTextElem->GetText()));
501466
}
502467
}
503468

504-
this->ApplyConfig();
469+
// Server control service topic
470+
std::string serverControlService{"/server_control"};
471+
auto *serverControlElem =
472+
_winElem.FirstChildElement("server_control_service");
473+
if (nullptr != serverControlElem && nullptr != serverControlElem->GetText())
474+
{
475+
serverControlService = transport::TopicUtils::AsValidTopic(
476+
serverControlElem->GetText());
477+
}
505478

479+
if (serverControlService.empty())
480+
{
481+
gzerr << "Failed to create valid server control service" << std::endl;
482+
}
483+
else
484+
{
485+
gzmsg << "Using server control service [" << serverControlService
486+
<< "]" << std::endl;
487+
this->dataPtr->mainWin->SetServerControlService(serverControlService);
488+
}
506489
return true;
507490
}
508-
509491
/////////////////////////////////////////////////
510492
bool Application::LoadDefaultConfig()
511493
{
@@ -519,11 +501,48 @@ void Application::SetDefaultConfigPath(const std::string &_path)
519501
}
520502

521503
/////////////////////////////////////////////////
522-
std::string Application::DefaultConfigPath()
504+
std::string Application::DefaultConfigPath() const
523505
{
524506
return this->dataPtr->defaultConfigPath;
525507
}
526508

509+
/////////////////////////////////////////////////
510+
std::string Application::ResolveConfigFile(const std::string &_path) const
511+
{
512+
std::string configFull = _path;
513+
514+
// Check if the passed in config file exists.
515+
// (If the default config path doesn't exist yet, it's expected behavior.
516+
// It will be created the first time the user presses "Save configuration".)
517+
if (!common::exists(configFull) && (configFull != this->DefaultConfigPath()))
518+
{
519+
// If not, then check environment variable
520+
std::string configPathEnv;
521+
common::env("GZ_GUI_RESOURCE_PATH", configPathEnv);
522+
523+
if (!configPathEnv.empty())
524+
{
525+
std::vector<std::string> parentPaths = common::Split(configPathEnv, ':');
526+
for (const auto &parentPath : parentPaths)
527+
{
528+
std::string tempPath = common::joinPaths(parentPath, configFull);
529+
if (common::exists(tempPath))
530+
{
531+
configFull = tempPath;
532+
break;
533+
}
534+
}
535+
}
536+
}
537+
538+
if (common::isRelativePath(configFull))
539+
{
540+
configFull = common::absPath(configFull);
541+
}
542+
543+
return configFull;
544+
}
545+
527546
/////////////////////////////////////////////////
528547
bool Application::LoadPlugin(const std::string &_filename,
529548
const tinyxml2::XMLElement *_pluginElem)

0 commit comments

Comments
 (0)