vtkInitializationHelper.cxx 13.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*=========================================================================

Program:   ParaView
Module:    vtkInitializationHelper.cxx

Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkInitializationHelper.h"
16

17
#include "vtkClientServerInterpreter.h"
18
#include "vtkClientServerInterpreterInitializer.h"
19
#include "vtkNew.h"
20
#include "vtkOutputWindow.h"
21
#include "vtkProcessModule.h"
22 23
#include "vtkPVConfig.h"
#include "vtkPVInitializer.h"
24
#include "vtkPVOptions.h"
25
#include "vtkPVPluginLoader.h"
Cory Quammen's avatar
Cory Quammen committed
26 27
#include "vtkPVSession.h"
#include "vtkSMSettings.h"
28
#include "vtkSmartPointer.h"
29
#include "vtkSMMessage.h"
30
#include "vtkSMProperty.h"
31
#include "vtkSMProxyManager.h"
32

33
#include <string>
34
#include <sstream>
35
#include <vtksys/SystemTools.hxx>
36

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
// Windows-only helper functionality:
#ifdef _WIN32
# include <Windows.h>
#endif

namespace {

#ifdef _WIN32
BOOL CALLBACK listMonitorsCallback(HMONITOR hMonitor, HDC /*hdcMonitor*/,
                                   LPRECT /*lprcMonitor*/, LPARAM dwData)
{
  std::ostringstream *str = reinterpret_cast<std::ostringstream*>(dwData);

  MONITORINFOEX monitorInfo;
  monitorInfo.cbSize = sizeof(monitorInfo);

  if (GetMonitorInfo(hMonitor, &monitorInfo))
    {
      LPRECT rect = &monitorInfo.rcMonitor;
      *str << "Device: \"" << monitorInfo.szDevice << "\" "
           << "Geometry: "
           << std::noshowpos
           << rect->right - rect->left << "x"
           << rect->bottom - rect->top
           << std::showpos
           << rect->left << rect->top << " "
           << ((monitorInfo.dwFlags & MONITORINFOF_PRIMARY)
               ? "(primary)" : "")
           << std::endl;
    }
  return true;
}
#endif // _WIN32

std::string ListAttachedMonitors()
{
#ifndef _WIN32
  return std::string("Monitor detection only implemented for MS Windows.");
#else // _WIN32
  std::ostringstream str;
  EnumDisplayMonitors(NULL, NULL, listMonitorsCallback,
                      reinterpret_cast<LPARAM>(&str));
  return str.str();
#endif // _WIN32
}

} // end anon namespace

85
bool vtkInitializationHelper::LoadSettingsFilesDuringInitialization = true;
86

87
bool vtkInitializationHelper::SaveUserSettingsFileDuringFinalization = false;
88

89
std::string vtkInitializationHelper::OrganizationName = "ParaView";
Cory Quammen's avatar
Cory Quammen committed
90
std::string vtkInitializationHelper::ApplicationName = "GenericParaViewApplication";
91

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
//----------------------------------------------------------------------------
void vtkInitializationHelper::SetLoadSettingsFilesDuringInitialization(bool val)
{
  if (vtkProcessModule::GetProcessModule() &&
    val != vtkInitializationHelper::LoadSettingsFilesDuringInitialization)
    {
    vtkGenericWarningMacro("SetLoadSettingsFilesDuringInitialization should be called "
      "before calling Initialize().");
    }
  else
    {
    vtkInitializationHelper::LoadSettingsFilesDuringInitialization = val;
    }
}

//----------------------------------------------------------------------------
bool vtkInitializationHelper::GetLoadSettingsFilesDuringInitialization()
{
  return vtkInitializationHelper::LoadSettingsFilesDuringInitialization;
}

113 114 115 116 117 118 119 120 121 122 123 124
//----------------------------------------------------------------------------
void vtkInitializationHelper::SetOrganizationName(const std::string & organizationName)
{
  vtkInitializationHelper::OrganizationName = organizationName;
}

//----------------------------------------------------------------------------
const std::string & vtkInitializationHelper::GetOrganizationName()
{
  return vtkInitializationHelper::OrganizationName;
}

125 126 127 128 129 130 131
//----------------------------------------------------------------------------
void vtkInitializationHelper::SetApplicationName(const std::string & appName)
{
  vtkInitializationHelper::ApplicationName = appName;
}

//----------------------------------------------------------------------------
132
const std::string & vtkInitializationHelper::GetApplicationName()
133 134 135 136
{
  return vtkInitializationHelper::ApplicationName;
}

137
//----------------------------------------------------------------------------
138
void vtkInitializationHelper::Initialize(const char* executable, int type)
139
{
140
  vtkInitializationHelper::Initialize(executable, type, NULL);
141 142 143 144
}

//----------------------------------------------------------------------------
void vtkInitializationHelper::Initialize(const char* executable,
145
  int type, vtkPVOptions* options)
146
{
147 148 149 150 151
  if (!executable)
    {
    vtkGenericWarningMacro("Executable name has to be defined.");
    return;
    }
152 153 154 155

  // Pass the program name to make option parser happier
  char* argv = new char[strlen(executable)+1];
  strcpy(argv, executable);
156 157 158 159 160 161

  vtkSmartPointer<vtkPVOptions> newoptions = options;
  if (!options)
    {
    newoptions = vtkSmartPointer<vtkPVOptions>::New();
    }
162
  vtkInitializationHelper::Initialize(1, &argv, type, newoptions);
163 164 165 166
  delete[] argv;
}

//----------------------------------------------------------------------------
167 168
void vtkInitializationHelper::Initialize(int argc, char**argv,
  int type, vtkPVOptions* options)
169
{
170
  if (vtkProcessModule::GetProcessModule())
171
    {
172
    vtkGenericWarningMacro("Process already initialize. Skipping.");
173 174
    return;
    }
175 176 177 178 179 180 181

  if (!options)
    {
    vtkGenericWarningMacro("vtkPVOptions must be specified.");
    return;
    }

182 183 184 185
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;

186 187 188
  vtkProcessModule::Initialize(
    static_cast<vtkProcessModule::ProcessTypes>(type), argc, argv);

189
  std::ostringstream sscerr;
190
  if (argv && !options->Parse(argc, argv) )
191
    {
192 193 194 195 196 197 198 199 200
    if ( options->GetUnknownArgument() )
      {
      sscerr << "Got unknown argument: " << options->GetUnknownArgument() << endl;
      }
    if ( options->GetErrorMessage() )
      {
      sscerr << "Error: " << options->GetErrorMessage() << endl;
      }
    options->SetHelpSelected(1);
201
    }
202
  if (options->GetHelpSelected())
203
    {
204 205 206
    sscerr << options->GetHelp() << endl;
    vtkOutputWindow::GetInstance()->DisplayText( sscerr.str().c_str() );
    // TODO: indicate to the caller that application must quit.
207
    }
208

209 210
  if (options->GetTellVersion() )
    {
211
    std::ostringstream str;
212 213
    str << "paraview version " << PARAVIEW_VERSION_FULL << "\n";
    vtkOutputWindow::GetInstance()->DisplayText(str.str().c_str());
214 215
    // TODO: indicate to the caller that application must quit.
    }
216

217 218
  if (options->GetPrintMonitors())
    {
219
      std::string monitors = ListAttachedMonitors();
220 221 222 223
      vtkOutputWindow::GetInstance()->DisplayText(monitors.c_str());
      // TODO: indicate to the caller that application must quit.
    }

224
  vtkProcessModule::GetProcessModule()->SetOptions(options);
225

226 227 228 229
  // this has to happen after process module is initialized and options have
  // been set.
  PARAVIEW_INITIALIZE();

230 231 232 233
  // Set multi-server flag to vtkProcessModule
  vtkProcessModule::GetProcessModule()->SetMultipleSessionsSupport(
        options->GetMultiServerMode() != 0);

234 235
  // Make sure the ProxyManager get created...
  vtkSMProxyManager::GetProxyManager();
236 237 238 239 240

  // Now load any plugins located in the PV_PLUGIN_PATH environment variable.
  // These are always loaded (not merely located).
  vtkNew<vtkPVPluginLoader> loader;
  loader->LoadPluginsFromPluginSearchPath();
241
  loader->LoadPluginsFromPluginConfigFile();
Cory Quammen's avatar
Cory Quammen committed
242

243 244 245 246 247 248
  vtkInitializationHelper::SaveUserSettingsFileDuringFinalization = false;
  // Load settings files on client-processes.
  if (!options->GetDisableRegistry() &&
    type != vtkProcessModule::PROCESS_SERVER &&
    type != vtkProcessModule::PROCESS_DATA_SERVER &&
    type != vtkProcessModule::PROCESS_RENDER_SERVER)
249 250 251
    {
    vtkInitializationHelper::LoadSettings();
    }
252 253
}

254
//----------------------------------------------------------------------------
255
void vtkInitializationHelper::StandaloneInitialize()
256 257 258 259 260 261
{
  // Verify that the version of the library that we linked against is
  // compatible with the version of the headers we compiled against.
  GOOGLE_PROTOBUF_VERIFY_VERSION;
}

262 263 264
//----------------------------------------------------------------------------
void vtkInitializationHelper::Finalize()
{
265
  if (vtkInitializationHelper::SaveUserSettingsFileDuringFinalization)
266
    {
267
    // Write out settings file(s)
268 269
    std::string userSettingsFilePath =
      vtkInitializationHelper::GetUserSettingsFilePath();
270
    vtkSMSettings* settings = vtkSMSettings::GetInstance();
271
    bool savingSucceeded = settings->SaveSettingsToFile(userSettingsFilePath.c_str());
272 273
    if (!savingSucceeded)
      {
274 275
      vtkGenericWarningMacro(<< "Saving settings file to '"
                             << userSettingsFilePath << "' failed");
276
      }
277 278
    }

279
  vtkSMProxyManager::Finalize();
280
  vtkProcessModule::Finalize();
281 282 283

  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();
284
}
285 286

//----------------------------------------------------------------------------
287
void vtkInitializationHelper::StandaloneFinalize()
288 289 290 291 292
{
  // Optional:  Delete all global objects allocated by libprotobuf.
  google::protobuf::ShutdownProtobufLibrary();
}

293
//----------------------------------------------------------------------------
294
void vtkInitializationHelper::LoadSettings()
295
{
296 297
  if (vtkInitializationHelper::LoadSettingsFilesDuringInitialization == false)
    {
298
    return;
299 300
    }

301
  vtkSMSettings* settings = vtkSMSettings::GetInstance();
302
  int myRank = vtkProcessModule::GetProcessModule()->GetPartitionId();
303

304 305 306
  if (myRank > 0) // don't read files on satellites.
    {
    settings->DistributeSettings();
307
    return;
308 309
    }

310
  // Load user-level settings
311
  std::string userSettingsFilePath = vtkInitializationHelper::GetUserSettingsFilePath();
312 313 314 315 316 317 318 319
  if (!settings->AddCollectionFromFile(userSettingsFilePath, VTK_DOUBLE_MAX))
    {
    // Loading user settings failed, so we need to create an empty
    // collection with highest priority manually. Otherwise, if a
    // setting is changed, a lower-priority collection such as site
    // settings may receive the modified setting values.
    settings->AddCollectionFromString("{}", VTK_DOUBLE_MAX);
    }
320 321

  // Load site-level settings
322 323 324 325
  vtkPVOptions* options = vtkProcessModule::GetProcessModule()->GetOptions();
  std::string app_dir = options->GetApplicationPath();
  app_dir = vtksys::SystemTools::GetProgramPath(app_dir.c_str());

326 327 328 329 330 331
  // If the application path ends with lib/paraview-X.X, shared
  // forwarding of the executable was used. Remove that part of the
  // path to get back to the installation root.
  std::string installDirectory = app_dir.substr(0, app_dir.find("/lib/paraview-" PARAVIEW_VERSION));

  // Remove the trailing /bin if it is there.
Cory Quammen's avatar
Cory Quammen committed
332 333
  if (installDirectory.size() >= 4 &&
      installDirectory.substr(installDirectory.size()-4) == "/bin")
334 335 336 337
    {
    installDirectory = installDirectory.substr(0, installDirectory.size()-4);
    }

338
  std::vector<std::string> pathsToSearch;
339 340 341
  pathsToSearch.push_back(installDirectory + "/share/paraview-" PARAVIEW_VERSION);
  pathsToSearch.push_back(installDirectory + "/lib/");
  pathsToSearch.push_back(installDirectory);
342 343
#if defined(__APPLE__)
  // paths for app
344 345
  pathsToSearch.push_back(installDirectory + "/../../..");
  pathsToSearch.push_back(installDirectory + "/../../../../lib");
346

347 348
  // paths when doing a unix style install.
  pathsToSearch.push_back(installDirectory +"/../lib/paraview-" PARAVIEW_VERSION);
349 350
#endif
  // On windows configuration files are in the parent directory
351
  pathsToSearch.push_back(installDirectory + "/../");
352

353
  std::string filename = vtkInitializationHelper::GetApplicationName() + "-SiteSettings.json";
354 355 356 357
  std::string siteSettingsFile;
  for (size_t cc = 0; cc < pathsToSearch.size(); cc++)
    {
    std::string path = pathsToSearch[cc];
358
    siteSettingsFile = path + "/" + filename;
359
    if (settings->AddCollectionFromFile(siteSettingsFile, 1.0))
360 361 362 363
      {
      break;
      }
    }
364 365
  settings->DistributeSettings();

366
  vtkInitializationHelper::SaveUserSettingsFileDuringFinalization = true;
367 368 369 370 371
}

//----------------------------------------------------------------------------
std::string vtkInitializationHelper::GetUserSettingsDirectory()
{
372
  std::string organizationName(vtkInitializationHelper::GetOrganizationName());
373
  std::string applicationName(vtkInitializationHelper::GetApplicationName());
374 375 376 377 378 379 380
#if defined(WIN32)
  const char* appData = getenv("APPDATA");
  if (!appData)
    {
    return std::string();
    }
  std::string separator("\\");
381 382
  std::string directoryPath(appData);
  if (directoryPath[directoryPath.size()-1] != separator[0])
383
    {
384
    directoryPath.append(separator);
385
    }
386
  directoryPath += applicationName + separator;
387
#else
388 389 390 391 392 393
  std::string directoryPath;
  std::string separator("/");
  
  // Emulating QSettings behavior.
  const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
  if (xdgConfigHome && strlen(xdgConfigHome) > 0)
394
    {
395 396 397 398 399
    directoryPath = xdgConfigHome;
    if (directoryPath[directoryPath.size() - 1] != separator[0])
      {
      directoryPath += separator;
      }
400
    }
401
  else
402
    {
403 404 405 406 407 408 409 410 411 412 413
    const char* home = getenv("HOME");
    if (!home)
      {
      return std::string();
      }
    directoryPath = home;
    if (directoryPath[directoryPath.size() - 1] != separator[0])
      {
      directoryPath += separator;
      }
     directoryPath += ".config/";
414
    }
415
  directoryPath += organizationName + separator;
416
#endif
417
  return directoryPath;
418 419
}

420 421 422 423 424 425 426 427 428 429
//----------------------------------------------------------------------------
std::string vtkInitializationHelper::GetUserSettingsFilePath()
{
  std::string path = vtkInitializationHelper::GetUserSettingsDirectory();
  path.append(vtkInitializationHelper::GetApplicationName());
  path.append("-UserSettings.json");

  return path;
}

430 431 432 433 434
//----------------------------------------------------------------------------
void vtkInitializationHelper::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}