text: /*
   * Copyright (C) 2012-2016 Open Source Robotics Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
  */
  #ifdef _WIN32
    // Ensure that Winsock2.h is included before Windows.h, which can get
    // pulled in by anybody (e.g., Boost).
    #include <Winsock2.h>
    #define snprintf _snprintf
  #endif
  
  #include <signal.h>
  #include <boost/program_options.hpp>
  #include <boost/property_tree/ini_parser.hpp>
  
  #include "gazebo/gui/qt.h"
  #include "gazebo/gazebo_client.hh"
  
  #include "gazebo/common/Time.hh"
  #include "gazebo/common/ModelDatabase.hh"
  #include "gazebo/common/Console.hh"
  #include "gazebo/common/Plugin.hh"
  #include "gazebo/common/CommonTypes.hh"
  #include "gazebo/gui/SplashScreen.hh"
  #include "gazebo/gui/MainWindow.hh"
  #include "gazebo/gui/ModelRightMenu.hh"
  #include "gazebo/gui/GuiIface.hh"
  
  #ifdef WIN32
  # define HOMEDIR "HOMEPATH"
  #else
  # define HOMEDIR "HOME"
  #endif  // WIN32
  
  // These are needed by QT. They need to stay valid during the entire
  // lifetime of the application, and argc > 0 and argv must contain one valid
  // character string
  int g_argc = 1;
  char **g_argv;
  
  namespace po = boost::program_options;
  po::variables_map vm;
  
  boost::property_tree::ptree g_propTree;
  
  using namespace gazebo;
  
  gui::ModelRightMenu *g_modelRightMenu = NULL;
  
  std::string g_worldname = "default";
  
  QApplication *g_app;
  gui::SplashScreen *g_splashScreen = NULL;
  gui::MainWindow *g_main_win = NULL;
  rendering::UserCameraPtr g_active_camera;
  bool g_fullscreen = false;
  
  // This makes it possible to use common::Time in QT signals and slots.
  // qRegisterMetaType is also required, see below.
  Q_DECLARE_METATYPE(common::Time)
  
  //////////////////////////////////////////////////
  void print_usage()
  {
    std::cerr << "gzclient -- Gazebo GUI Client\n\n";
    std::cerr << "`gzclient` [options]\n\n";
    std::cerr << "Gazebo GUI client which allows visualization and user "
      << "interaction.\n\n";
  }
  
  //////////////////////////////////////////////////
  void signal_handler(int)
  {
    gazebo::gui::stop();
    gazebo::client::shutdown();
  }
  
  //////////////////////////////////////////////////
  bool parse_args(int _argc, char **_argv)
  {
    po::options_description v_desc("Options");
    v_desc.add_options()
      ("version,v", "Output version information.")
      ("verbose", "Increase the messages written to the terminal.")
      ("help,h", "Produce this help message.")
      ("gui-plugin,g", po::value<std::vector<std::string> >(), "Load a plugin.");
  
    po::options_description desc("Options");
    desc.add(v_desc);
  
    try
    {
      po::store(po::command_line_parser(_argc,
            _argv).options(desc).allow_unregistered().run(), vm);
      po::notify(vm);
    } catch(boost::exception &_e)
    {
      std::cerr << "Error. Gui Invalid arguments\n";
      return false;
    }
  
    if (vm.count("version"))
    {
      std::cout << GAZEBO_VERSION_HEADER << std::endl;
      return false;
    }
  
    if (vm.count("help"))
    {
      print_usage();
      std::cerr << v_desc << "\n";
      return false;
    }
  
    if (vm.count("verbose"))
    {
      gazebo::client::printVersion();
      gazebo::common::Console::SetQuiet(false);
    }
  
    /// Load all the plugins specified on the command line
    if (vm.count("gui-plugin"))
    {
      std::vector<std::string> pp =
        vm["gui-plugin"].as<std::vector<std::string> >();
  
      for (std::vector<std::string>::iterator iter = pp.begin();
           iter != pp.end(); ++iter)
      {
        gazebo::client::addPlugin(*iter);
      }
    }
  
    return true;
  }
  
  namespace gazebo
  {
    namespace gui
    {
      void set_style()
      {
        QFile file(":/style.qss");
        file.open(QFile::ReadOnly);
        QString styleSheet = QLatin1String(file.readAll());
        g_app->setStyleSheet(styleSheet);
      }
  
      /////////////////////////////////////////////////
      void fini()
      {
        // Cleanup model database.
        common::ModelDatabase::Instance()->Fini();
  
        gui::clear_active_camera();
        rendering::fini();
        fflush(stdout);
      }
    }
  }
  
  /////////////////////////////////////////////////
  void gui::init()
  {
    g_modelRightMenu->Init();
    g_main_win->Init();
  }
  
  /////////////////////////////////////////////////
  bool gui::loadINI(boost::filesystem::path _file)
  {
    bool result = true;
  
    // Only use the environment variables if _file is empty.
    if (_file.empty())
    {
      // Get the gui.ini path environment variable
      char *guiINIFile = getenv("GAZEBO_GUI_INI_FILE");
      char *home = getenv(HOMEDIR);
  
      // If the environment variable was specified
      if (guiINIFile)
      {
        _file = guiINIFile;
        if (!boost::filesystem::exists(_file))
        {
          gzerr << "GAZEBO_GUI_INI_FILE does not exist: " << _file << std::endl;
          return false;
        }
      }
      else if (home)
      {
        // Check the home directory
        // Construct the path to gui.ini
        _file = home;
        _file = _file / ".gazebo" / "gui.ini";
      }
    }
  
    // Create the gui.ini file if it doesn't exist.
    if (!boost::filesystem::exists(_file))
    {
      gui::setINIProperty("geometry.x", 0);
      gui::setINIProperty("geometry.y", 0);
      gui::saveINI(_file);
      gzwarn << "Couldn't locate specified .ini. Creating file at " << _file
            << std::endl;
    }
  
    try
    {
      // Read all configuration properties
      boost::property_tree::ini_parser::read_ini(_file.string(), g_propTree);
    }
    catch(...)
    {
      gzerr << "Unable to read configuration file " << _file << "\n";
      result = false;
    }
  
    gzlog << "Loaded .ini file from: " << _file << std::endl;
    return result;
  }
  
  /////////////////////////////////////////////////
  bool gui::load()
  {
    gui::loadINI();
  
    g_modelRightMenu = new gui::ModelRightMenu();
  
    // Load the rendering engine.
    rendering::load();
    rendering::init();
  
    g_argv = new char*[g_argc];
    for (int i = 0; i < g_argc; i++)
    {
      g_argv[i] = new char[strlen("gazebo")];
      snprintf(g_argv[i], strlen("gazebo"), "gazebo");
    }
  
    g_app = new QApplication(g_argc, g_argv);
    set_style();
  
    // Register common::Time as a type that can be used in signals and slots.
    // Q_DECLARE_METATYPE is also required, see above.
    qRegisterMetaType<common::Time>();
  
    g_splashScreen = new gui::SplashScreen();
  
    g_main_win = new gui::MainWindow();
  
    g_main_win->Load();
  
    return true;
  }
  
  /////////////////////////////////////////////////
  unsigned int gui::get_entity_id(const std::string &_name)
  {
    if (g_main_win)
      return g_main_win->EntityId(_name);
    else
      return 0;
  }
  
  /////////////////////////////////////////////////
  bool gui::run(int _argc, char **_argv)
  {
    // Initialize the informational logger. This will log warnings, and errors.
    gzLogInit("client-", "gzclient.log");
  
    // Make sure the model database has started
    gazebo::common::ModelDatabase::Instance()->Start();
  
    if (!parse_args(_argc, _argv))
      return false;
  
    if (!gazebo::client::setup(_argc, _argv))
      return false;
  
    if (!gazebo::gui::load())
      return false;
  
    gazebo::gui::init();
  
  #ifndef _WIN32
    // Now that we're about to run, install a signal handler to allow for
    // graceful shutdown on Ctrl-C.
    struct sigaction sigact;
    sigact.sa_flags = 0;
    sigact.sa_handler = signal_handler;
    if (sigemptyset(&sigact.sa_mask) != 0)
      std::cerr << "sigemptyset failed while setting up for SIGINT" << std::endl;
    if (sigaction(SIGINT, &sigact, NULL))
    {
      std::cerr << "signal(2) failed while setting up for SIGINT" << std::endl;
      return false;
    }
  #endif
  
    g_app->exec();
  
    gazebo::gui::fini();
    gazebo::client::shutdown();
  
    delete g_splashScreen;
    delete g_main_win;
    return true;
  }
  
  /////////////////////////////////////////////////
  void gui::stop()
  {
    gazebo::client::shutdown();
    g_active_camera.reset();
    g_app->quit();
  }
  
  /////////////////////////////////////////////////
  void gui::set_world(const std::string &_name)
  {
    g_worldname = _name;
  }
  
  /////////////////////////////////////////////////
  std::string gui::get_world()
  {
    return g_worldname;
  }
  
  /////////////////////////////////////////////////
  void gui::set_active_camera(rendering::UserCameraPtr _cam)
  {
    g_active_camera = _cam;
  }
  
  /////////////////////////////////////////////////
  void gui::clear_active_camera()
  {
    g_active_camera.reset();
  }
  
  /////////////////////////////////////////////////
  rendering::UserCameraPtr gui::get_active_camera()
  {
    return g_active_camera;
  }
  
  /////////////////////////////////////////////////
  bool gui::has_entity_name(const std::string &_name)
  {
    return g_main_win->HasEntityName(_name);
  }
  
  /////////////////////////////////////////////////
  bool gui::saveINI(const boost::filesystem::path &_file)
  {
    bool result = true;
    try
    {
      boost::property_tree::ini_parser::write_ini(_file.string(), g_propTree);
    }
    catch(...)
    {
      gzerr << "Unable to save INI file[" << _file << "]\n";
      result = false;
    }
    return result;
  }
  
  /////////////////////////////////////////////////
  gui::MainWindow *gui::get_main_window()
  {
    return g_main_win;
  }
  