]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Support of additional environment-defined path to plugins. Also make plugins.xml... Dev_PluginPathExtension
authormpv <mpv@opencascade.com>
Fri, 20 Oct 2017 16:20:57 +0000 (19:20 +0300)
committermpv <mpv@opencascade.com>
Fri, 20 Oct 2017 16:20:57 +0000 (19:20 +0300)
src/Config/CMakeLists.txt
src/Config/Config_FeatureMessage.h
src/Config/Config_Keywords.h
src/Config/Config_ModuleReader.cpp
src/Config/Config_PluginMessage.cpp [new file with mode: 0644]
src/Config/Config_PluginMessage.h [new file with mode: 0644]
src/Config/Config_XMLReader.cpp
src/Config/Config_XMLReader.h
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModuleBase/ModuleBase_IconFactory.cpp

index d1a1781ab6de12b2112495fbf6dac7cbcf7ac683..e120e21b8a9fb69a62d309835331b1408dc0f4aa 100644 (file)
@@ -29,6 +29,7 @@ INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Events
 SET(PROJECT_HEADERS
   Config_def.h
   Config_FeatureMessage.h
+  Config_PluginMessage.h
   Config_XMLReader.h
   Config_ModuleReader.h
   Config_FeatureReader.h
@@ -48,6 +49,7 @@ SET(PROJECT_HEADERS
 
 SET(PROJECT_SOURCES
   Config_FeatureMessage.cpp
+  Config_PluginMessage.cpp
   Config_XMLReader.cpp
   Config_ModuleReader.cpp
   Config_FeatureReader.cpp
index 86d30868414a40e9f875bfb97d44d3cccff5d018..a4c6105511b5301f98fc00626e1c5c3fb1a3cfe7 100644 (file)
@@ -18,8 +18,8 @@
 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
 //
 
-#ifndef CONFIG_MESSAGE_H
-#define CONFIG_MESSAGE_H
+#ifndef CONFIG_FEATUREMESSAGE_H
+#define CONFIG_FEATUREMESSAGE_H
 
 #include <Config_def.h>
 #include <Events_Message.h>
index 81a8d8dea00fbb40980983a7a9919cead4c0234f..95a54bb42ca7226ee5c27aea6cbc43963170f30c 100644 (file)
@@ -123,6 +123,7 @@ const static char* PLUGIN_CONFIG = "configuration";
 const static char* PLUGIN_LIBRARY = "library";
 const static char* PLUGIN_SCRIPT = "script";
 const static char* PLUGIN_DEPENDENCY = "dependency";
+const static char* PLUGIN_USES = "uses";
 
 /*
  * Hardcoded xml entities of dataModel.xml
index 168983a5eb2d7a28c7c1f0bb2848f69a41c6c6d9..67b4ee990d1c4c77fa670541ba093130f80e18f1 100644 (file)
@@ -24,6 +24,7 @@
 #include <Config_Common.h>
 #include <Config_ModuleReader.h>
 #include <Config_FeatureReader.h>
+#include <Config_PluginMessage.h>
 #include <Events_InfoMessage.h>
 
 #include <libxml/parser.h>
@@ -102,6 +103,13 @@ void Config_ModuleReader::processNode(xmlNodePtr theNode)
     std::string aPluginLibrary = getProperty(theNode, PLUGIN_LIBRARY);
     std::string aPluginScript = getProperty(theNode, PLUGIN_SCRIPT);
     std::string aPluginName = addPlugin(aPluginLibrary, aPluginScript, aPluginConf);
+    std::string aUsesPlugin = getProperty(theNode, PLUGIN_USES);
+    if (!aUsesPlugin.empty()) { // send information about hte plugin dependencies
+      std::shared_ptr<Config_PluginMessage> aMess(new Config_PluginMessage(
+        Events_Loop::loop()->eventByName(Config_PluginMessage::EVENT_ID()), aPluginName));
+      aMess->setUses(aUsesPlugin);
+      Events_Loop::loop()->send(aMess);
+    }
 
     std::list<std::string> aFeatures = importPlugin(aPluginName, aPluginConf);
     std::list<std::string>::iterator it = aFeatures.begin();
@@ -167,6 +175,12 @@ std::string Config_ModuleReader::addPlugin(const std::string& aPluginLibrary,
 
 void Config_ModuleReader::loadPlugin(const std::string& thePluginName)
 {
+  // informs model that plugin loading is started
+  static const Events_ID kEVENT_ID =
+    Events_Loop::loop()->eventByName(Config_PluginMessage::EVENT_ID());
+  std::shared_ptr<Config_PluginMessage> aMess(new Config_PluginMessage(kEVENT_ID, thePluginName));
+  Events_Loop::loop()->send(aMess);
+
   PluginType aType = Config_ModuleReader::Binary;
   if(myPluginTypes.find(thePluginName) != myPluginTypes.end()) {
     aType = myPluginTypes.at(thePluginName);
diff --git a/src/Config/Config_PluginMessage.cpp b/src/Config/Config_PluginMessage.cpp
new file mode 100644 (file)
index 0000000..eaee691
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "Config_PluginMessage.h"
+
+Config_PluginMessage::Config_PluginMessage(const Events_ID theId,
+  const std::string& thePluginId, const void* theParent)
+    : Events_Message(theId, theParent)
+{
+  myPluginId = thePluginId;
+}
+
+Config_PluginMessage::~Config_PluginMessage()
+{
+
+}
+
+const std::string& Config_PluginMessage::pluginId() const
+{
+  return myPluginId;
+}
+
+const std::string& Config_PluginMessage::uses() const
+{
+  return myUses;
+}
+
+void Config_PluginMessage::setUses(const std::string& theUses)
+{
+  myUses = theUses;
+}
diff --git a/src/Config/Config_PluginMessage.h b/src/Config/Config_PluginMessage.h
new file mode 100644 (file)
index 0000000..8778c3d
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef CONFIG_PLUGINMESSAGE_H
+#define CONFIG_PLUGINMESSAGE_H
+
+#include <Config_def.h>
+#include <Events_Message.h>
+
+#include <string>
+
+/*!
+ * \class Config_PluginMessage
+ * \ingroup Config
+ * \brief Information that plugin is started to load.
+ *
+ * Contains the plugin name. Event is posted just before load of the plugin
+ * before registerPlugin call.
+ */
+class Config_PluginMessage : public Events_Message
+{
+  std::string myPluginId;  ///< Plugin unique id
+  std::string myUses;  ///< Which plugins are used by this one Id
+
+ public:
+  /// Event ID that plugin will be loaded
+  inline static const char* EVENT_ID()
+  {
+    static const char * MY_EVENT_ID("BeforePluginLoad");
+    return MY_EVENT_ID;
+  }
+
+  /// Constructs Config_PluginMessage
+  CONFIG_EXPORT Config_PluginMessage(const Events_ID theId,
+    const std::string& thePluginId, const void* theParent = 0);
+  /// Deletes Config_PluginMessage
+  CONFIG_EXPORT virtual ~Config_PluginMessage();
+
+  /// Plugin Id
+  CONFIG_EXPORT const std::string& pluginId() const;
+  /// Which plugins are used by this one Id
+  CONFIG_EXPORT const std::string& uses() const;
+  /// Sets which plugins are used by this one Id
+  CONFIG_EXPORT void setUses(const std::string& theUses);
+};
+
+#endif // CONFIG_MESSAGE_H
index 6b29a5851b9d3c50d3bc1f249e461be338806b72..0ab7ce325ab49fb54694def552a30ed183b7d54d 100644 (file)
@@ -30,6 +30,7 @@
 #include <libxml/tree.h>
 
 #include <fstream>
+#include <sstream>
 
 #ifdef WIN32
 #pragma warning(disable : 4996) // for getenv
 #endif
 
 Config_XMLReader::Config_XMLReader(const std::string& theXmlFileName)
-    : myXmlDoc(NULL)
+    : myXmlDoc(NULL), myRootFileName(theXmlFileName)
 {
-  std::string prefix = "";
-  Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
-  if (aProp)
-    prefix = aProp->value();
-  /*
-   * Get path to *.xml files (typically ./bin/../plugins/)
-
-   * the problem: application may be launched using python executable,
-   * to use environment variable (at least for the current moment)
-   */
-  if (prefix.empty())
-    prefix = pluginConfigFile();
-
-  myDocumentPath = prefix + FSEP + theXmlFileName;
-  std::ifstream aTestFile(myDocumentPath);
-  if (!aTestFile)
-    Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(myDocumentPath).send();
-  aTestFile.close();
+  myDocumentPath = findConfigFile(theXmlFileName);
+  if (myDocumentPath.empty()) {
+    Events_InfoMessage("Config_XMLReader", "Unable to open %1").arg(theXmlFileName).send();
+  }
 }
 
 Config_XMLReader::~Config_XMLReader()
@@ -89,13 +76,84 @@ std::string Config_XMLReader::pluginConfigFile()
   return aValue;
 }
 
+std::string Config_XMLReader::findConfigFile(const std::string theFileName, const int theFindIndex)
+{
+  int aResultIndex = 0;
+  for(int aSolution = 0; aSolution < 12; aSolution++) {
+    std::string aFileName;
+    if (aSolution == 0) {
+      Config_Prop* aProp = Config_PropManager::findProp("Plugins", "default_path");
+      if (!aProp)
+        continue;
+      aFileName = aProp->value();
+    } else {
+      std::ostringstream anEnvName;
+      if (aSolution == 1)
+        anEnvName<<"SHAPER_ROOT_DIR";
+      else if (aSolution == 2)
+        anEnvName<<"OPENPARTS_ROOT_DIR";
+      else
+        anEnvName<<"OPENPARTS_PLUGINS_DIR";
+
+      char* anEnv = getenv(anEnvName.str().c_str());
+      if (!anEnv)
+        continue;
+      if (aSolution > 2) { // there may be several paths separated by ";" symbol
+        std::string anEnvPart = anEnv;
+        size_t aPosStart = 0, aPosEnd;
+        for(int aSubNum = 0; aSubNum < aSolution - 3; aSubNum++) {
+          aPosStart++;
+          aPosStart = anEnvPart.find(';', aPosStart);
+          if (aPosStart == std::string::npos)
+            break;
+        }
+        if (aPosStart == std::string::npos)
+          break;
+        if (aPosStart != 0)
+          aPosStart++;
+        aPosEnd = anEnvPart.find(';', aPosStart);
+        aFileName = anEnvPart.substr(aPosStart,
+          aPosEnd == std::string::npos ? aPosEnd : aPosEnd - aPosStart) + FSEP;
+      } else {
+        aFileName = std::string(anEnv) + FSEP;
+      }
+      if (aSolution == 1)
+        aFileName += std::string("share") + FSEP + "salome" + FSEP + "resources" + FSEP + "shaper";
+      else if (aSolution == 2)
+        aFileName += "plugins";
+    }
+
+    aFileName += FSEP + theFileName;
+    std::ifstream aTestFile(aFileName);
+    if (aTestFile) {
+      if (aResultIndex == theFindIndex)
+        return aFileName;
+      aResultIndex++;
+      if (aSolution == 1) // don't allow SHAPER and OpenParts paths treated simultaneously
+        aSolution++;
+    }
+  }
+  return ""; // no files found
+}
+
 void Config_XMLReader::readAll()
 {
-  // to load external modules dependencies (like GEOm for Connector Feature
+  // to load external modules dependencies (like GEOM for Connector Feature)
   Config_ModuleReader::loadScript("salome.shaper.initConfig", false);
 
-  xmlNodePtr aRoot = findRoot();
-  readRecursively(aRoot);
+  for(int aSolution = 0; true; aSolution++) {
+    std::string aFoundFile = findConfigFile(myRootFileName, aSolution);
+    if (aFoundFile.empty()) {
+      break; // no more solutions
+    }
+
+    if (myXmlDoc != NULL) { // clear the previous XML document - now the new one will be opened
+      xmlFreeDoc(myXmlDoc);
+      myXmlDoc = NULL;
+    }
+    xmlNodePtr aRoot = findRoot(aFoundFile);
+    readRecursively(aRoot);
+  }
 }
 
 void Config_XMLReader::processNode(xmlNodePtr theNode)
@@ -120,14 +178,15 @@ bool Config_XMLReader::processChildren(xmlNodePtr aNode)
   return true;
 }
 
-xmlNodePtr Config_XMLReader::findRoot()
+xmlNodePtr Config_XMLReader::findRoot(const std::string theDocumentPath)
 {
+  std::string aDocPath = theDocumentPath.empty() ? myDocumentPath : theDocumentPath;
   if (myXmlDoc == NULL) {
-    myXmlDoc = xmlParseFile(myDocumentPath.c_str());
+    myXmlDoc = xmlParseFile(aDocPath.c_str());
   }
   if (myXmlDoc == NULL) {
 #ifdef _DEBUG
-    std::cout << "Config_XMLReader::import: " << "Document " << myDocumentPath
+    std::cout << "Config_XMLReader::import: " << "Document " << aDocPath
     << " is not parsed successfully." << std::endl;
 #endif
     return NULL;
index 53b07024f1b9dac0ed5864c83061276863665a29..6b4fde6ba7aa64fed52de459b502dd293357725c 100644 (file)
@@ -66,13 +66,18 @@ class Config_XMLReader
    */
   CONFIG_EXPORT void readAll();
   /*!
-   * Returns xmlNodePtr to the root of reader's document
-   * or NULL if not found
+   * Returns xmlNodePtr to the root of reader's document or NULL if not found.
+   * If the path to the document to read is empty, uses myDocumentPath.
    */
-  CONFIG_EXPORT xmlNodePtr findRoot();
+  CONFIG_EXPORT xmlNodePtr findRoot(const std::string theDocumentPath = "");
 
   CONFIG_EXPORT const char* encoding() const;
 
+  /// Checks all possible paths to configuration file given
+  /// Uses theFindIndex if several solutions can be found (this is the number of solution to find)
+  CONFIG_EXPORT static std::string
+    findConfigFile(const std::string theFileName, const int theFindIndex = 0);
+
  protected:
   /*!
    * \brief Allows to customize reader's behavior for a node. Virtual.
@@ -117,6 +122,7 @@ class Config_XMLReader
  protected:
   std::string myDocumentPath; ///< Path to the xml document
   xmlDocPtr myXmlDoc; ///< Root of the xml document
+  std::string myRootFileName; ///< name of the root file
   /// A map to store all parent's attributes.
   /// The key has from "Node_Name:Node_Attribute"
   std::map<std::string, std::string> myCachedAttributes;
index 10bd28f205db172f7fe67331aa8bf482d3e7ef34..065e6276dbd5e8e95bc5ac4ba7ea445040af3ad6 100644 (file)
@@ -35,6 +35,7 @@
 #include <Config_ValidatorMessage.h>
 #include <Config_ModuleReader.h>
 #include <Config_ValidatorReader.h>
+#include <Config_PluginMessage.h>
 
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_ResultPart.h>
@@ -165,6 +166,29 @@ std::list<std::string> Model_Session::redoList()
   return ROOT_DOC->redoList();
 }
 
+ModelAPI_Plugin* Model_Session::getPlugin(const std::string& thePluginName)
+{
+  if (myPluginObjs.find(thePluginName) == myPluginObjs.end()) {
+    // before load the used plugins
+    if (myUsePlugins.find(thePluginName) != myUsePlugins.end()) {
+      std::string aUse = myUsePlugins[thePluginName];
+      std::stringstream aUseStream(aUse);
+      std::string aPluginName;
+      while (std::getline(aUseStream, aPluginName, ',')) {
+        if (myPluginObjs.find(aPluginName) == myPluginObjs.end())
+          getPlugin(aPluginName);
+      }
+    }
+    // load plugin library if not yet done
+    Config_ModuleReader::loadPlugin(thePluginName);
+  }
+  if (myPluginObjs.find(thePluginName) == myPluginObjs.end()) {
+    Events_InfoMessage("Model_Session", "Can not load plugin '%1'").arg(thePluginName).send();
+    return NULL;
+  }
+  return myPluginObjs[thePluginName];
+}
+
 FeaturePtr Model_Session::createFeature(std::string theFeatureID, Model_Document* theDocOwner)
 {
   if (this != myImpl) {
@@ -178,26 +202,20 @@ FeaturePtr Model_Session::createFeature(std::string theFeatureID, Model_Document
     std::pair<std::string, std::string>& aPlugin = myPlugins[theFeatureID]; // plugin and doc kind
     if (!aPlugin.second.empty() && aPlugin.second != theDocOwner->kind()) {
       Events_InfoMessage("Model_Session",
-          "Feature '%1' can be created only in document '%2' by the XML definition")
-          .arg(theFeatureID).arg(aPlugin.second).send();
+        "Feature '%1' can be created only in document '%2' by the XML definition")
+        .arg(theFeatureID).arg(aPlugin.second).send();
       return FeaturePtr();
     }
-    myCurrentPluginName = aPlugin.first;
-    if (myPluginObjs.find(myCurrentPluginName) == myPluginObjs.end()) {
-      // load plugin library if not yet done
-      Config_ModuleReader::loadPlugin(myCurrentPluginName);
-    }
-    if (myPluginObjs.find(myCurrentPluginName) != myPluginObjs.end()) {
-      FeaturePtr aCreated = myPluginObjs[myCurrentPluginName]->createFeature(theFeatureID);
+    ModelAPI_Plugin* aPluginObj = getPlugin(aPlugin.first);
+    if (aPluginObj) {
+      FeaturePtr aCreated = aPluginObj->createFeature(theFeatureID);
       if (!aCreated) {
-        Events_InfoMessage("Model_Session",
-            "Can not initialize feature '%1' in plugin '%2'")
-            .arg(theFeatureID).arg(myCurrentPluginName).send();
+        Events_InfoMessage("Model_Session", "Can not initialize feature '%1' in plugin '%2'")
+          .arg(theFeatureID).arg(aPlugin.first).send();
       }
       return aCreated;
     } else {
-      Events_InfoMessage("Model_Session",
-        "Can not load plugin '%1'").arg(myCurrentPluginName).send();
+      Events_InfoMessage("Model_Session", "Can not load plugin '%1'").arg(aPlugin.first).send();
     }
   } else {
     Events_InfoMessage("Model_Session",
@@ -416,6 +434,7 @@ Model_Session::Model_Session()
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED), 0, true);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED), 0, true);
   aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VALIDATOR_LOADED));
+  aLoop->registerListener(this, Events_Loop::eventByName(Config_PluginMessage::EVENT_ID()));
 }
 
 void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessage)
@@ -423,6 +442,7 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
   static const Events_ID kFeatureEvent =
     Events_Loop::eventByName(Config_FeatureMessage::MODEL_EVENT());
   static const Events_ID kValidatorEvent = Events_Loop::eventByName(EVENT_VALIDATOR_LOADED);
+  static const Events_ID kPluginEvent = Events_Loop::eventByName(Config_PluginMessage::EVENT_ID());
   if (theMessage->eventID() == kFeatureEvent) {
     const std::shared_ptr<Config_FeatureMessage> aMsg =
       std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
@@ -463,6 +483,15 @@ void Model_Session::processEvent(const std::shared_ptr<Events_Message>& theMessa
                                       aMsg->parameters());
       }
     }
+  } else if (theMessage->eventID() == kPluginEvent) { // plugin is started to load
+    std::shared_ptr<Config_PluginMessage> aMsg =
+      std::dynamic_pointer_cast<Config_PluginMessage>(theMessage);
+    if (aMsg.get()) {
+      myCurrentPluginName = aMsg->pluginId();
+      if (!aMsg->uses().empty()) {
+        myUsePlugins[myCurrentPluginName] = aMsg->uses();
+      }
+    }
   } else {  // create/update/delete
     if (myCheckTransactions && !isOperation())
       Events_InfoMessage("Model_Session",
index 89b9d548c1d5d1b1416b57dde0ad8ec9b92c1aa6..7342ae2d35845dab086fdf2cad9af3d0fa477f91 100644 (file)
@@ -44,6 +44,8 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   std::map<std::string, ModelAPI_Plugin*> myPluginObjs;  ///< instances of the already plugins
   std::string myCurrentPluginName;  ///< name of the plugin that must be loaded currently
   std::shared_ptr<ModelAPI_Document> myCurrentDoc;  ///< current working document
+   ///< map from plugin id to plugins which are used by it (must be loaded before this one)
+  std::map<std::string, std::string> myUsePlugins;
 
   /// if true, generates error if document is updated outside of transaction
   bool myCheckTransactions;
@@ -149,6 +151,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// Creates the feature object using plugins functionality
   FeaturePtr createFeature(std::string theFeatureID, Model_Document* theDocOwner);
 
+  /// Get the plugin by name. If it is not loaded, load plugin.
+  ModelAPI_Plugin* getPlugin(const std::string& thePluginName);
+
   friend class Model_Document;
   friend class Model_Objects;
 };
index 067ef6ea5ca5662a15ee84a353cc02d8cc47e102..a691efd3242079f656ea640db9d3df7c32e8a379 100644 (file)
@@ -62,10 +62,9 @@ QPixmap ModuleBase_IconFactory::loadPixmap(const QString& theValue)
   QPixmap aPixmap(theValue);
 
   if (aPixmap.isNull()) {
-    std::string aPluginPath = Config_XMLReader::pluginConfigFile();
-    QString aPath = QString::fromStdString(aPluginPath) + QDir::separator() + theValue;
-    if (QFile::exists(aPath))
-      aPixmap = QPixmap(aPath);
+    std::string aPath = Config_XMLReader::findConfigFile(theValue.toStdString());
+    if (!aPath.empty())
+      aPixmap = QPixmap(QString::fromStdString(aPath));
   }
   return aPixmap;
 }
@@ -75,10 +74,9 @@ QImage ModuleBase_IconFactory::loadImage(const QString& theValue)
   QImage anImage(theValue);
 
   if (anImage.isNull()) {
-    std::string aPluginPath = Config_XMLReader::pluginConfigFile();
-    QString aPath = QString::fromStdString(aPluginPath) + QDir::separator() + theValue;
-    if (QFile::exists(aPath))
-      anImage = QImage(aPath);
+    std::string aPath = Config_XMLReader::findConfigFile(theValue.toStdString());
+    if (!aPath.empty())
+      anImage = QImage(QString::fromStdString(aPath));
   }
   return anImage;
 }