Permalink
Browse files

ENH: Support per user per revision extensions settings

There is now a clear distinction between:
 - userSettings -> i.e. ~/.config/NA-MIC/Slicer.ini
 - revisionUserSettings -> i.e. ~/.config/NA-MIC/Slicer-<revision>.ini

The following slicer settings are now revision specific:
 - Extensions/ManagerEnabled
 - Extensions/ServerUrl
 - Extensions/InstallPath
 - Modules/AdditonalPath
 - Modules/IgnoreModules

Additionally, the launcher version has also been updated to be able to
consider settings associated with a user, application and revision. This is
captured by the new parameter APPLICATION_REVISION, ORGANIZATION_DOMAIN,
ORGANIZATION_NAME and USER_ADDITIONAL_SETTINGS_FILEBASENAME passed to the CMake
function "ctkAppLauncherConfigure".

qSlicerCoreApplication API has also been extended and now includes methods
like:
  - QSettings* userSettings()  [settings() method is deprecated and kept for backward compatibility]
  - QSettings* revisionUserSettings()
  - QString launcherRevisionUserSettingsFilePath()
  - QString slicerUserSettingsFilePath()
  - QString slicerRevisionUserSettingsFilePath()

In addition to the settings, the extensions install path is also revision
specific, it means that it's now possible to have multiple version of slicer
running with different set of extensions.

Fixes #2791, #2143, #2720, #2533


Since the version of the launcher is updated, launcher will return EXIT_FAILURE
also when no application is been set in the launcher settings.

Fixes #2767

git-svn-id: http://svn.slicer.org/Slicer4/trunk@21482 3bd1e089-480b-0410-8dfb-8563597acbee
  • Loading branch information...
1 parent e048030 commit e6fb116c13d1b64731d6d13cf9ccfd2e3a67beb1 @jcfr jcfr committed Dec 7, 2012
Showing with 337 additions and 170 deletions.
  1. +4 −0 Applications/SlicerApp/CMakeLists.txt
  2. +1 −1 Applications/SlicerApp/Main.cxx
  3. +8 −7 Applications/SlicerApp/qSlicerAppMainWindow.cxx
  4. +16 −3 Base/Logic/Testing/vtkSlicerApplicationLogicTest1.cxx
  5. +7 −5 Base/Logic/vtkSlicerApplicationLogic.cxx
  6. +6 −1 Base/Logic/vtkSlicerApplicationLogic.h
  7. +4 −5 Base/QTApp/qSlicerApplicationHelper.cxx
  8. +2 −1 Base/QTCLI/qSlicerCLIModuleFactoryHelper.cxx
  9. +1 −1 Base/QTCore/Testing/Cxx/qSlicerCoreApplicationTest1.cxx
  10. +52 −20 Base/QTCore/Testing/Cxx/qSlicerExtensionsManagerModelTest.cxx
  11. BIN Base/QTCore/Testing/Data/Input/19615-macosx-amd64-CLIExtensionTemplate-svn19615-2012-03-18.tar.gz
  12. BIN ...QTCore/Testing/Data/Input/19615-macosx-amd64-LoadableExtensionTemplate-svn19615-2012-03-18.tar.gz
  13. BIN ...esting/Data/Input/19615-macosx-amd64-ScriptedLoadableExtensionTemplate-svn19615-2012-03-18.tar.gz
  14. BIN ...ting/Data/Input/19615-macosx-amd64-SuperBuildLoadableExtensionTemplate-svn19615-2012-03-18.tar.gz
  15. +88 −27 Base/QTCore/qSlicerCoreApplication.cxx
  16. +24 −3 Base/QTCore/qSlicerCoreApplication.h
  17. +2 −1 Base/QTCore/qSlicerCoreApplication_p.h
  18. +1 −1 Base/QTCore/qSlicerCoreCommandOptions.cxx
  19. +1 −1 Base/QTCore/qSlicerCoreCommandOptions.h
  20. +60 −61 Base/QTCore/qSlicerExtensionsManagerModel.cxx
  21. +3 −3 Base/QTCore/qSlicerExtensionsManagerModel.h
  22. +2 −1 Base/QTCore/qSlicerLoadableModuleFactory.cxx
  23. +6 −4 Base/QTGUI/qSlicerExtensionsManagerDialog.cxx
  24. +2 −1 Base/QTGUI/qSlicerScriptedLoadableModuleFactory.cxx
  25. +8 −3 Base/QTGUI/qSlicerSettingsExtensionsPanel.cxx
  26. +1 −1 Base/QTGUI/qSlicerSettingsGeneralPanel.cxx
  27. +6 −3 Base/QTGUI/qSlicerSettingsModulesPanel.cxx
  28. +1 −1 CMake/SlicerConfig.cmake.in
  29. +1 −1 CMake/UseSlicer.cmake.in
  30. +7 −1 CMake/vtkSlicerConfigure.h.in
  31. +16 −5 CMakeLists.txt
  32. +1 −1 Modules/Loadable/Colors/qSlicerColorsModule.cxx
  33. +1 −1 Modules/Scripted/Scripts/DICOM.py
  34. +0 −1 SuperBuild.cmake
  35. +1 −1 SuperBuild/External_CTK.cmake
  36. +4 −4 SuperBuild/External_CTKAPPLAUNCHER.cmake
@@ -286,6 +286,10 @@ if(${PROJECT_NAME} STREQUAL ${Slicer_MAIN_PROJECT})
TARGET ${PROJECT_NAME}${SlicerApp_EXE_SUFFIX}
APPLICATION_INSTALL_SUBDIR ${Slicer_INSTALL_BIN_DIR}
APPLICATION_NAME ${SlicerApp_APPLICATION_NAME}
+ APPLICATION_REVISION ${Slicer_WC_REVISION}
+ ORGANIZATION_DOMAIN ${Slicer_ORGANIZATION_DOMAIN}
+ ORGANIZATION_NAME ${Slicer_ORGANIZATION_NAME}
+ USER_ADDITIONAL_SETTINGS_FILEBASENAME ${SLICER_REVISION_SPECIFIC_USER_SETTINGS_FILEBASENAME}
SPLASH_IMAGE_PATH ${splash_image_path}
SPLASH_IMAGE_INSTALL_SUBDIR ${Slicer_INSTALL_BIN_DIR}
SPLASHSCREEN_HIDE_DELAY_MS 3000
@@ -66,7 +66,7 @@ namespace
void setEnableQtTesting()
{
if (qSlicerApplication::application()->commandOptions()->enableQtTesting() ||
- qSlicerApplication::application()->settings()->value("QtTesting/Enabled").toBool())
+ qSlicerApplication::application()->userSettings()->value("QtTesting/Enabled").toBool())
{
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
}
@@ -823,9 +823,11 @@ void qSlicerAppMainWindow::setupMenuActions()
connect(d->actionLoadDICOM, SIGNAL(triggered()),
this, SLOT(loadDICOMActionTriggered()));
- QSettings settings;
+ qSlicerApplication * app = qSlicerApplication::application();
+
#ifdef Slicer_BUILD_EXTENSIONMANAGER_SUPPORT
- d->actionViewExtensionManager->setVisible(settings.value("Extensions/ManagerEnabled").toBool());
+ d->actionViewExtensionManager->setVisible(
+ app->revisionUserSettings()->value("Extensions/ManagerEnabled").toBool());
#else
d->actionViewExtensionManager->setVisible(false);
#endif
@@ -834,16 +836,15 @@ void qSlicerAppMainWindow::setupMenuActions()
#endif
#if defined Slicer_USE_QtTesting && defined Slicer_BUILD_CLI_SUPPORT
- if (qSlicerApplication::application()->commandOptions()->enableQtTesting() ||
- settings.value("QtTesting/Enabled").toBool())
+ if (app->commandOptions()->enableQtTesting() ||
+ app->userSettings()->value("QtTesting/Enabled").toBool())
{
d->actionEditPlayMacro->setVisible(true);
d->actionEditRecordMacro->setVisible(true);
- qSlicerApplication::application()->testingUtility()->addPlayer(
- new qSlicerCLIModuleWidgetEventPlayer());
+ app->testingUtility()->addPlayer(new qSlicerCLIModuleWidgetEventPlayer());
}
#endif
-
+ Q_UNUSED(app);
}
#undef qSlicerAppMainWindowCore_connect
@@ -137,38 +137,51 @@ int vtkSlicerApplicationLogicTest1(int , char * [])
TestRowType row;
row.push_back("/home/jchris/Projects/MRIChangeDetector-build/lib/Slicer-X.Y/qt-scripted-modules/MRIChangeDetector.pyc");
row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build");
+ row.push_back("4810");
row.push_back("0");
data.push_back(row);
}
{
TestRowType row;
row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build/lib/Slicer-X.Y/qt-scripted-modules/MRIChangeDetector.pyc");
row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build");
+ row.push_back("4810");
row.push_back("1");
data.push_back(row);
}
{
TestRowType row;
row.push_back("/home/jchris/Projects/Slicer.app/Contents/lib/Slicer-4.1/qt-loadable-modules/libqSlicerAnnotationsModule.dylib");
row.push_back("/home/jchris/Projects/Slicer.app/Contents");
+ row.push_back("4810");
row.push_back("1");
data.push_back(row);
}
{
TestRowType row;
- row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build/bin/Slicer.app/Contents/Extensions/Reporting/lib/Slicer-4.1/qt-loadable-modules/Python/vtkSlicerReportingModuleLogic.py");
+ row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build/bin/Slicer.app/Contents/Extensions-4810/Reporting/lib/Slicer-4.1/qt-loadable-modules/Python/vtkSlicerReportingModuleLogic.py");
row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build");
+ row.push_back("4810");
row.push_back("0");
data.push_back(row);
}
+ {
+ TestRowType row;
+ row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build/bin/Slicer.app/Contents/Extensions-4810/Reporting/lib/Slicer-4.1/qt-loadable-modules/Python/vtkSlicerReportingModuleLogic.py");
+ row.push_back("/home/jchris/Projects/Slicer4-Superbuild-Debug/Slicer-build");
+ row.push_back("4811");
+ row.push_back("1");
+ data.push_back(row);
+ }
for(TestDataType::size_type rowIdx = 0; rowIdx < data.size(); ++rowIdx)
{
std::string filePath(data.at(rowIdx).at(0));
std::string applicationHomeDir(data.at(rowIdx).at(1));
- std::string isEmbeddedExpectedAsStr(data.at(rowIdx).at(2));
+ std::string slicerRevision(data.at(rowIdx).at(2));
+ std::string isEmbeddedExpectedAsStr(data.at(rowIdx).at(3));
bool isEmbeddedExpected = (isEmbeddedExpectedAsStr == "1");
- bool isEmbedded = vtkSlicerApplicationLogic::IsEmbeddedModule(filePath, applicationHomeDir);
+ bool isEmbedded = vtkSlicerApplicationLogic::IsEmbeddedModule(filePath, applicationHomeDir, slicerRevision);
if (isEmbeddedExpected != isEmbedded)
{
std::cerr << "Line " << __LINE__ << " - Problem with isEmbedded ! - Row:" << rowIdx << "\n"
@@ -1547,7 +1547,9 @@ void vtkSlicerApplicationLogic::ProcessWriteSceneData(WriteDataRequest& req)
}
//----------------------------------------------------------------------------
-bool vtkSlicerApplicationLogic::IsEmbeddedModule(const std::string& filePath, const std::string& applicationHomeDir)
+bool vtkSlicerApplicationLogic::IsEmbeddedModule(const std::string& filePath,
+ const std::string& applicationHomeDir,
+ const std::string& slicerRevision)
{
if (filePath.empty())
{
@@ -1562,10 +1564,10 @@ bool vtkSlicerApplicationLogic::IsEmbeddedModule(const std::string& filePath, co
std::string extensionPath = itksys::SystemTools::GetFilenamePath(filePath);
bool isEmbedded = itksys::SystemTools::StringStartsWith(extensionPath.c_str(), applicationHomeDir.c_str());
#ifdef Slicer_BUILD_EXTENSIONMANAGER_SUPPORT
- // On MacOSX extensions are installed in the "Extensions" folder being a sub directory of the
- // application dir, an extra test is required to make sure the tested filePath
- // doesn't belong to that "Extensions" folder.
- if (isEmbedded && extensionPath.find(Slicer_BUNDLE_LOCATION "/" Slicer_BUNDLE_EXTENSIONS_DIRNAME) != std::string::npos)
+ // On MacOSX extensions are installed in the "<Slicer_EXTENSIONS_DIRBASENAME>-<slicerRevision>"
+ // folder being a sub directory of the application dir, an extra test is required to make sure the
+ // tested filePath doesn't belong to that "<Slicer_EXTENSIONS_DIRBASENAME>-<slicerRevision>" folder.
+ if (isEmbedded && extensionPath.find(Slicer_BUNDLE_LOCATION "/" Slicer_EXTENSIONS_DIRBASENAME "-" + slicerRevision) != std::string::npos)
{
isEmbedded = false;
}
@@ -133,7 +133,12 @@ class VTK_SLICER_BASE_LOGIC_EXPORT vtkSlicerApplicationLogic
void SetTracingOff () { this->Tracing = 0; }
/// Return True if \a filePath is a descendant of \a applicationHomeDir.
- static bool IsEmbeddedModule(const std::string& filePath, const std::string& applicationHomeDir);
+ /// \note On MacOSX extensions are installed in the "<Slicer_EXTENSIONS_DIRBASENAME>-<slicerRevision>"
+ /// folder being a sub directory of the application dir, an extra test is performed to make sure the
+ /// tested filePath doesn't belong to that "<Slicer_EXTENSIONS_DIRBASENAME>-<slicerRevision>" folder.
+ /// If this is the case, False will be returned.
+ static bool IsEmbeddedModule(const std::string& filePath, const std::string& applicationHomeDir,
+ const std::string& slicerRevision);
/// Return \a true if the plugin identified with its \a filePath is loaded from an install tree.
/// \warning Since internally the function looks for the existence of CMakeCache.txt, it will
@@ -100,14 +100,13 @@ void qSlicerApplicationHelper::setupModuleFactoryManager(qSlicerModuleFactoryMan
}
#endif
- QSettings settings;
#ifdef Slicer_BUILD_CLI_SUPPORT
if (!options->disableCLIModules() && !options->runPythonAndExit())
{
QString tempDirectory =
qSlicerCoreApplication::application()->coreCommandOptions()->tempDirectory();
bool preferExecutableCLIs =
- settings.value("Modules/PreferExecutableCLI", false).toBool();
+ app->userSettings()->value("Modules/PreferExecutableCLI", false).toBool();
moduleFactoryManager->registerFactory(
new qSlicerCLILoadableModuleFactory(tempDirectory), preferExecutableCLIs ? 0 : 1);
// Option to prefer executable CLIs to limit memory consumption.
@@ -125,9 +124,9 @@ void qSlicerApplicationHelper::setupModuleFactoryManager(qSlicerModuleFactoryMan
}
#endif
moduleFactoryManager->addSearchPaths(
- settings.value("Modules/AdditionalPaths").toStringList());
+ app->revisionUserSettings()->value("Modules/AdditionalPaths").toStringList());
moduleFactoryManager->setModulesToIgnore(
- settings.value("Modules/IgnoreModules").toStringList());
+ app->revisionUserSettings()->value("Modules/IgnoreModules").toStringList());
moduleFactoryManager->setVerboseModuleDiscovery(app->commandOptions()->verboseModuleDiscovery());
}
@@ -138,7 +137,7 @@ void qSlicerApplicationHelper::loadTranslations(const QString& dir)
Q_ASSERT(app);
QString localeFilter =
- QString( QString("*") + app->settings()->value("language").toString());
+ QString( QString("*") + app->userSettings()->value("language").toString());
localeFilter.resize(3);
localeFilter += QString(".qm");
@@ -55,7 +55,8 @@ const QStringList qSlicerCLIModuleFactoryHelper::modulePaths()
}
}
- QStringList additionalModulePaths = QSettings().value("Modules/AdditionalPaths").toStringList();
+ QSettings * settings = app->revisionUserSettings();
+ QStringList additionalModulePaths = settings->value("Modules/AdditionalPaths").toStringList();
QStringList cmdLineModulePaths = additionalModulePaths + defaultCmdLineModulePaths;
foreach(const QString& path, cmdLineModulePaths)
{
@@ -73,7 +73,7 @@ int qSlicerCoreApplicationTest1(int argc, char * argv [] )
return EXIT_FAILURE;
}
- QSettings * settings = app.settings();
+ QSettings * settings = app.userSettings();
if( settings == 0 )
{
std::cerr << "Problem with settings()" << std::endl;
Oops, something went wrong.

0 comments on commit e6fb116

Please sign in to comment.