Salome HOME
Implementation of "Import" BREP and STEP functionality
authorsbh <sergey.belash@opencascade.com>
Tue, 2 Sep 2014 15:44:44 +0000 (19:44 +0400)
committersbh <sergey.belash@opencascade.com>
Tue, 2 Sep 2014 15:44:44 +0000 (19:44 +0400)
23 files changed:
CMakeLists.txt
msvc10_env.bat
src/Config/Config_Keywords.h
src/Config/Config_WidgetAPI.h
src/Config/plugins.xml
src/ExchangePlugin/CMakeLists.txt [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_ImportFeature.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Plugin.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Plugin.h [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Validators.cpp [new file with mode: 0644]
src/ExchangePlugin/ExchangePlugin_Validators.h [new file with mode: 0644]
src/ExchangePlugin/plugin-Exchange.xml [new file with mode: 0644]
src/Model/Model_FeatureValidator.cpp
src/ModelAPI/ModelAPI_PluginManager.cpp
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_Operation.cpp
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/ModuleBase/ModuleBase_WidgetFactory.h
src/ModuleBase/ModuleBase_WidgetFileSelector.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_WidgetFileSelector.h [new file with mode: 0644]
src/PartSet/icons/import.png

index de2256284b03851b30e355ef5d298aba6f9b0981..ae2ee1eb047f5ee9d857cf28a9589be4fd994bcb 100644 (file)
@@ -59,6 +59,7 @@ ADD_SUBDIRECTORY (src/ModuleBase)
 ADD_SUBDIRECTORY (src/PartSet)
 ADD_SUBDIRECTORY (src/XGUI)
 ADD_SUBDIRECTORY (src/GeomApp)
+ADD_SUBDIRECTORY (src/ExchangePlugin)
 
 IF(${HAVE_SALOME})
        ADD_SUBDIRECTORY (src/NewGeom)
index 03a087af44c195196912c6cefb45b44f8b8c5031..a684f5e8bb948f3bfaf27a92f25b6f82c34eb1db 100644 (file)
@@ -129,6 +129,12 @@ set PATH=%CMAKEDIR%\bin;%PATH%
 @SET PATH=%ROOT_DIR%\install\plugins;%ROOT_DIR%\install\bin;%PATH%
 @SET PYTHONPATH=%ROOT_DIR%\install\swig;%PYTHONPATH%
 
+@REM -------------------------
+@REM PTHREAD
+@SET PATH=%PDIR%\pthreads-2.9.1\lib;%PATH%
+@REM -------------------------
+
+
 @REM -------------------------
 @REM SUIT
 @SET SUIT_DIR=%PDIR%\suit
index 434857827fbf6137ef20dd5c78d6a4b15ef85899..f1e5e01225c4398f8365020406e4df05412d3940 100644 (file)
@@ -30,13 +30,14 @@ const static char* WDG_SWITCH = "switch";
 const static char* WDG_SWITCH_CASE = "case";
 const static char* WDG_SELECTOR = "selector";
 
-//Specific widget containers
+//Specific widgets
 const static char* WDG_POINT_SELECTOR = "point_selector";
 const static char* WDG_POINT2D_DISTANCE = "point2ddistance";
-
 const static char* WDG_FEATURE_SELECTOR = "feature_selector";
 const static char* WDG_FEATURE_OR_ATTRIBUTE_SELECTOR = "feature_or_attribute_selector";
 const static char* WDG_DOUBLEVALUE_EDITOR = "doublevalue_editor";
+const static char* WDG_FILE_SELECTOR= "file_selector";
+
 
 //Common Widget's or Feature's Properties
 const static char* _ID = "id";
index d7c12e957e09f7bbcc587f0945971e498aacaa1e..ad084049f76e147a9b0e468684e9a7694fceccaf 100644 (file)
@@ -31,6 +31,7 @@ class CONFIG_EXPORT Config_WidgetAPI
   Config_WidgetAPI(std::string theRawXml);
   virtual ~Config_WidgetAPI();
 
+  //TODO(sbh): Make these fields protected, accessible only for WidgetFactory
   bool toNextWidget();
   bool toChildWidget();
   bool toParentWidget();
index a4d1dbdae5e3f237a7e3f8088c232a7f9909908a..7d6b81b6ffe948c4fa9467f0f4ee366cc34b3507 100644 (file)
@@ -3,6 +3,7 @@
   <plugin library="SketchPlugin" configuration="plugin-Sketch.xml"/>
   <plugin library="ConstructionPlugin" configuration="plugin-Construction.xml"/>
   <plugin library="FeaturesPlugin" configuration="plugin-Features.xml"/>
+  <plugin library="ExchangePlugin" configuration="plugin-Exchange.xml"/>
   <plugin library="SketchSolver"/>
   <plugin library="DFBrowser"/>
 </plugins>
diff --git a/src/ExchangePlugin/CMakeLists.txt b/src/ExchangePlugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1a5299a
--- /dev/null
@@ -0,0 +1,42 @@
+INCLUDE(Common)
+
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events
+                    ${PROJECT_SOURCE_DIR}/src/Config
+                    ${PROJECT_SOURCE_DIR}/src/ModelAPI
+                    ${PROJECT_SOURCE_DIR}/src/GeomAPI
+                    ${CAS_INCLUDE_DIRS}
+) 
+
+SET(PROJECT_HEADERS
+    ExchangePlugin.h
+    ExchangePlugin_Plugin.h
+    ExchangePlugin_ImportFeature.h
+    ExchangePlugin_Validators.h
+)
+SET(PROJECT_SOURCES
+    ExchangePlugin_Plugin.cpp
+    ExchangePlugin_ImportFeature.cpp
+    ExchangePlugin_Validators.cpp
+)
+
+SET(XML_RESOURCES
+    plugin-Exchange.xml
+)
+
+SET(PROJECT_LIBRARIES
+    Events
+    ModelAPI
+    Config
+    GeomAPI
+    ${CAS_OCAF}
+    ${CAS_TKCAF}
+)
+
+ADD_DEFINITIONS(-DEXCHANGEPLUGIN_EXPORTS ${CAS_DEFINITIONS})
+ADD_LIBRARY(ExchangePlugin SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+
+TARGET_LINK_LIBRARIES(ExchangePlugin ${PROJECT_LIBRARIES})
+
+INSTALL(TARGETS ExchangePlugin DESTINATION plugins)
+INSTALL(FILES ${XML_RESOURCES} DESTINATION plugins)
diff --git a/src/ExchangePlugin/ExchangePlugin.h b/src/ExchangePlugin/ExchangePlugin.h
new file mode 100644 (file)
index 0000000..183563e
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef EXCHANGEPLUGIN_H
+#define EXCHANGEPLUGIN_H
+
+#if defined EXCHANGEPLUGIN_EXPORTS
+#if defined WIN32
+#define EXCHANGEPLUGIN_EXPORT              __declspec( dllexport )
+#else
+#define EXCHANGEPLUGIN_EXPORT
+#endif
+#else
+#if defined WIN32
+#define EXCHANGEPLUGIN_EXPORT              __declspec( dllimport )
+#else
+#define EXCHANGEPLUGIN_EXPORT
+#endif
+#endif
+
+#endif
diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp
new file mode 100644 (file)
index 0000000..a0c6598
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * ExchangePlugin_ImportFeature.cpp
+ *
+ *  Created on: Aug 28, 2014
+ *      Author: sbh
+ */
+
+#include <ExchangePlugin_ImportFeature.h>
+
+#include <GeomAPI_Shape.h>
+#include <Config_Common.h>
+#include <Events_Error.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultBody.h>
+
+#include <TCollection_AsciiString.hxx>
+#include <TDF_Label.hxx>
+#include <TopoDS_Shape.hxx>
+#include <OSD_Path.hxx>
+
+#include <algorithm>
+#include <string>
+#ifdef _DEBUG
+#include <iostream>
+#include <ostream>
+#endif
+
+#ifdef WIN32
+# define _separator_ '\\'
+#else
+# define _separator_ '/'
+#endif
+
+typedef TopoDS_Shape (*importFunctionPointer)(const TCollection_AsciiString&,
+                                              const TCollection_AsciiString&,
+                                              TCollection_AsciiString&,
+                                              const TDF_Label&);
+
+ExchangePlugin_ImportFeature::ExchangePlugin_ImportFeature()
+{
+}
+
+ExchangePlugin_ImportFeature::~ExchangePlugin_ImportFeature()
+{
+  // TODO Auto-generated destructor stub
+}
+
+/*
+ * Returns the unique kind of a feature
+ */
+const std::string& ExchangePlugin_ImportFeature::getKind()
+{
+  return ExchangePlugin_ImportFeature::ID();
+}
+
+/*
+ * Request for initialization of data model of the feature: adding all attributes
+ */
+void ExchangePlugin_ImportFeature::initAttributes()
+{
+  data()->addAttribute(ExchangePlugin_ImportFeature::FILE_PATH_ID(), ModelAPI_AttributeString::type());
+}
+
+/*
+ * Computes or recomputes the results
+ */
+void ExchangePlugin_ImportFeature::execute()
+{
+  AttributeStringPtr aFilePathAttr = boost::dynamic_pointer_cast<ModelAPI_AttributeString>(
+      data()->attribute(ExchangePlugin_ImportFeature::FILE_PATH_ID()));
+  std::string aFilePath = aFilePathAttr->value();
+  if(aFilePath.empty())
+    return;
+  importFile(aFilePath);
+}
+
+bool ExchangePlugin_ImportFeature::importFile(const std::string& theFileName)
+{
+  // retrieve the file and plugin library names
+  TCollection_AsciiString aFileName (theFileName.c_str());
+  OSD_Path aPath(aFileName);
+  TCollection_AsciiString aFormatName = aPath.Extension();
+  // ".brep" -> "BREP". TCollection_AsciiString are numbered from 1
+  aFormatName = aFormatName.SubString(2, aFormatName.Length());
+  aFormatName.UpperCase();
+
+  // Load plugin library and get the "Import" method
+  LibHandle anImportLib = loadImportPlugin(std::string(aFormatName.ToCString()));
+  if(!anImportLib)
+    return false;
+  importFunctionPointer fp = (importFunctionPointer) GetProc(anImportLib, "Import");
+   // Perform the import
+   TCollection_AsciiString anError;
+   TDF_Label anUnknownLabel = TDF_Label();
+   TopoDS_Shape aShape = fp(aFileName,
+                            aFormatName,
+                            anError,
+                            anUnknownLabel);
+   // Check if shape is valid
+   if ( aShape.IsNull() ) {
+     std::string aShapeError = "An error occurred while importing " + theFileName + ": ";
+     aShapeError = aShapeError + std::string(anError.ToCString());
+     Events_Error::send(aShapeError, this);
+ #ifdef _DEBUG
+     std::cerr << aShapeError << std::endl;
+ #endif
+     return false;
+   }
+   // Pass the results into the model
+   std::string anObjectName = aPath.Name().ToCString();
+   data()->setName(anObjectName);
+   boost::shared_ptr<ModelAPI_ResultBody> aResult = document()->createBody(data());
+   boost::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
+   aGeomShape->setImpl(new TopoDS_Shape(aShape));
+   aResult->store(aGeomShape);
+   setResult(aResult);
+
+   return true;
+}
+
+LibHandle ExchangePlugin_ImportFeature::loadImportPlugin(const std::string& theFormatName)
+{
+  std::string aLibName = library(theFormatName + ID());
+  LibHandle anImportLib = LoadLib(aLibName.c_str());
+  std::string anImportError = "Failed to load " + aLibName + ": ";
+  if(!anImportLib) {
+#ifdef WIN32
+    LPVOID lpMsgBuf;
+    ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                    FORMAT_MESSAGE_FROM_SYSTEM |
+                    FORMAT_MESSAGE_IGNORE_INSERTS,
+                    0, ::GetLastError(), 0, (LPTSTR) &lpMsgBuf, 0, 0);
+    anImportError = anImportError + std::string((char*) lpMsgBuf);
+    ::LocalFree(lpMsgBuf);
+#else
+    anImportError = anImportError + std::string(dlerror());
+#endif
+    Events_Error::send(anImportError, this);
+#ifdef _DEBUG
+    std::cerr << anImportError << std::endl;
+#endif
+    return false;
+  }
+  // Test loaded plugin for existence of valid "Import" function:
+  importFunctionPointer fp = (importFunctionPointer) GetProc(anImportLib, "Import");
+  if (!fp) {
+    std::string aFunctionError = "No valid \"Import\" function was found in the " + aLibName;
+    Events_Error::send(aFunctionError, this);
+#ifdef _DEBUG
+    std::cerr << aFunctionError << std::endl;
+#endif
+    UnLoadLib(anImportLib)
+    return NULL;
+  }
+  return anImportLib;
+}
diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.h b/src/ExchangePlugin/ExchangePlugin_ImportFeature.h
new file mode 100644 (file)
index 0000000..4b3b7a8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * ExchangePlugin_ImportFeature.h
+ *
+ *  Created on: Aug 28, 2014
+ *      Author: sbh
+ */
+
+#ifndef EXCHANGEPLUGIN_IMPORTFEATURE_H_
+#define EXCHANGEPLUGIN_IMPORTFEATURE_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Feature.h>
+
+#include <map>
+
+#ifdef WIN32
+#include <windows.h>
+#define LibHandle HMODULE
+#define LoadLib( name ) LoadLibrary( name )
+#define GetProc GetProcAddress
+#define UnLoadLib( handle ) FreeLibrary( handle );
+#else
+#include <dlfcn.h>
+#define LibHandle void*
+#define LoadLib( name ) dlopen( name, RTLD_LAZY | RTLD_GLOBAL)
+#define GetProc dlsym
+#define UnLoadLib( handle ) dlclose( handle );
+#endif
+
+class EXCHANGEPLUGIN_EXPORT ExchangePlugin_ImportFeature : public ModelAPI_Feature
+{
+ public:
+  /// Extrusion kind
+  inline static const std::string& ID()
+  {
+    static const std::string MY_IMPORT_ID("Import");
+    return MY_IMPORT_ID;
+  }
+  /// attribute name of referenced face
+  inline static const std::string& FILE_PATH_ID()
+  {
+    static const std::string MY_FILE_PATH_ID("import_file_selector");
+    return MY_FILE_PATH_ID;
+  }
+
+  ExchangePlugin_ImportFeature();
+  virtual ~ExchangePlugin_ImportFeature();
+
+  /// Returns the unique kind of a feature
+  virtual const std::string& getKind();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+  virtual void initAttributes();
+
+  /// Computes or recomputes the results
+  virtual void execute();
+
+  virtual bool isInHistory()
+  {
+    return false;
+  }
+
+ protected:
+  bool importFile(const std::string& theFileName);
+  LibHandle loadImportPlugin(const std::string& theFormatName);
+  
+};
+
+#endif /* IMPORT_IMPORTFEATURE_H_ */
diff --git a/src/ExchangePlugin/ExchangePlugin_Plugin.cpp b/src/ExchangePlugin/ExchangePlugin_Plugin.cpp
new file mode 100644 (file)
index 0000000..97d2b6e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *
+ */
+
+#include <ExchangePlugin_Plugin.h>
+#include <ExchangePlugin_ImportFeature.h>
+
+#include <ModelAPI_PluginManager.h>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+using namespace std;
+
+// the only created instance of this plugin
+static ExchangePlugin_Plugin* MY_INSTANCE = new ExchangePlugin_Plugin();
+
+ExchangePlugin_Plugin::ExchangePlugin_Plugin()
+{
+  // register this plugin
+  ModelAPI_PluginManager::get()->registerPlugin(this);
+}
+
+FeaturePtr ExchangePlugin_Plugin::createFeature(string theFeatureID)
+{
+  if (theFeatureID == ExchangePlugin_ImportFeature::ID()) {
+    return FeaturePtr(new ExchangePlugin_ImportFeature);
+  }
+  // feature of such kind is not found
+  return FeaturePtr();
+}
diff --git a/src/ExchangePlugin/ExchangePlugin_Plugin.h b/src/ExchangePlugin/ExchangePlugin_Plugin.h
new file mode 100644 (file)
index 0000000..5cb5f20
--- /dev/null
@@ -0,0 +1,23 @@
+// File:        ExchangePlugin_Plugin.hxx
+// Created:     07 July 2014
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef EXCHANGEPLUGIN_PLUGIN_H_
+#define EXCHANGEPLUGIN_PLUGIN_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Plugin.h>
+#include <ModelAPI_Feature.h>
+
+class EXCHANGEPLUGIN_EXPORT ExchangePlugin_Plugin : public ModelAPI_Plugin
+{
+ public:
+  /// Creates the feature object of this plugin by the feature string ID
+  virtual FeaturePtr createFeature(std::string theFeatureID);
+
+ public:
+  /// Is needed for python wrapping by swig
+  ExchangePlugin_Plugin();
+};
+
+#endif
diff --git a/src/ExchangePlugin/ExchangePlugin_Validators.cpp b/src/ExchangePlugin/ExchangePlugin_Validators.cpp
new file mode 100644 (file)
index 0000000..99e14be
--- /dev/null
@@ -0,0 +1,22 @@
+// File:        SketchPlugin_Validators.cpp
+// Created:     01 Aug 2014
+// Author:      Vitaly SMETANNIKOV
+
+#include <ExchangePlugin_Validators.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_PluginManager.h>
+
+#include <list>
+#include <string>
+
+
+bool ExchangePlugin_ImportFormatValidator::isValid(const FeaturePtr& theFeature,
+                                                 const std::list<std::string>& theArguments,
+                                                 const ObjectPtr& theObject) const
+{
+  PluginManagerPtr aMgr = ModelAPI_PluginManager::get();
+  ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+  return false;
+}
+
diff --git a/src/ExchangePlugin/ExchangePlugin_Validators.h b/src/ExchangePlugin/ExchangePlugin_Validators.h
new file mode 100644 (file)
index 0000000..c4400fc
--- /dev/null
@@ -0,0 +1,20 @@
+// File:        SketchPlugin_Validators.h
+// Created:     01 Aug 2014
+// Author:      Vitaly SMETANNIKOV
+
+#ifndef EXCHANGEPLUGIN_VALIDATORS_H
+#define EXCHANGEPLUGIN_VALIDATORS_H
+
+#include "ExchangePlugin.h"
+#include <ModelAPI_AttributeValidator.h>
+
+class ExchangePlugin_ImportFormatValidator : public ModelAPI_AttributeValidator
+{
+ public:
+  virtual bool isValid(const FeaturePtr& theFeature,
+                       const std::list<std::string>& theArguments,
+                       const ObjectPtr& theObject) const;
+
+};
+
+#endif
diff --git a/src/ExchangePlugin/plugin-Exchange.xml b/src/ExchangePlugin/plugin-Exchange.xml
new file mode 100644 (file)
index 0000000..48cedc4
--- /dev/null
@@ -0,0 +1,20 @@
+<plugin>
+  <workbench id="Features">
+    <group id="Exchange">
+      <feature
+        id="Import"
+        title="Import"
+        tooltip="Import a mesh"
+        icon=":icons/import.png">
+        <file_selector
+          id="import_file_selector"
+          title="Import file"
+          path="D:\NewGEOM\data\brep-step"
+          formats="BREP,STEP" />
+        <!-- TODO: pass formats as validator 
+        <validator id="Format" parameters="BREP:BREPImport,STEP:STEPImport" /> 
+        -->
+      </feature>
+    </group>
+  </workbench>
+</plugin>
\ No newline at end of file
index f311e54db1bab70f748df56728821378217889c7..b4b4fb8cc975a6e0a1ea0ee138d3e9a2f5b859e8 100644 (file)
@@ -11,9 +11,7 @@
 #include <list>
 #include <boost/shared_ptr.hpp>
 
-bool Model_FeatureValidator::isValid(const boost::shared_ptr<ModelAPI_Feature>& theFeature
-/*, const std::string theAttr*/
-/*, std::list<std::string> theArguments*/) const
+bool Model_FeatureValidator::isValid(const boost::shared_ptr<ModelAPI_Feature>& theFeature) const
 {
   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
   if (!aData->isValid())
index a0750645aee28d43653316451a40ed0df62dd1a3..35048c4258232c143738e8ede6157a5aa364db90 100644 (file)
@@ -16,6 +16,7 @@
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeString.h>
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeRefList.h>
index b21756a5c39ff3dc9c72c13d5cbfd6696a9308cc..f65d8c989d17dc212b2846d91d41ac77f274631e 100644 (file)
@@ -25,6 +25,7 @@ SET(PROJECT_HEADERS
        ModuleBase_SelectionValidator.h
        ModuleBase_ISelection.h
        ModuleBase_ViewerPrs.h
+       ModuleBase_WidgetFileSelector.h
 )
 
 SET(PROJECT_SOURCES
@@ -44,6 +45,7 @@ SET(PROJECT_SOURCES
        ModuleBase_WidgetPoint2dDistance.cpp
        ModuleBase_WidgetValue.cpp
        ModuleBase_WidgetValueFeature.cpp
+       ModuleBase_WidgetFileSelector.cpp
 )
 
 SET(PROJECT_LIBRARIES
index 305b810c6b008193818b51e20ffe364e99fbee37..91130350c2ef445d80497ab10a21c62afa667cd1 100644 (file)
@@ -86,8 +86,6 @@ void ModuleBase_Operation::abortOperation()
 
 void ModuleBase_Operation::commitOperation()
 {
-  if (myFeature)
-    myFeature->execute();
 }
 
 void ModuleBase_Operation::afterCommitOperation()
@@ -134,7 +132,8 @@ FeaturePtr ModuleBase_Operation::createFeature(const bool theFlushMessage)
   myFeature = aDoc->addFeature(getDescription()->operationId().toStdString());
   if (myFeature) {  // TODO: generate an error if feature was not created
     myIsModified = true;
-    myFeature->execute();
+    // Model update should call "execute" of a feature.
+    //myFeature->execute();
     // Init default values
     /*QList<ModuleBase_ModelWidget*> aWidgets = getDescription()->modelWidgets();
      QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
index d75479e746739fa580263ce4a12656d3d75e2cac..46b7e03d03229e7181c465be561c5fffa69deb49 100644 (file)
@@ -18,6 +18,7 @@
 #include <ModuleBase_WidgetDoubleValue.h>
 #include <ModuleBase_WidgetBoolValue.h>
 #include <ModuleBase_WidgetPoint2dDistance.h>
+#include <ModuleBase_WidgetFileSelector.h>
 #include <ModuleBase_IWorkshop.h>
 #include <ModuleBase_IModule.h>
 
@@ -143,7 +144,8 @@ QWidget* ModuleBase_WidgetFactory::createWidgetByType(const std::string& theType
 
   } else if (theType == WDG_POINT2D_DISTANCE) {
     result = point2dDistanceControl(theParent);
-
+  } else if (theType == WDG_FILE_SELECTOR) {
+    result = fileSelectorControl(theParent);
   } else if (myWidgetApi->isContainerWidget() || myWidgetApi->isPagedWidget()) {
     result = createContainer(theType, theParent);
   } else {
@@ -259,3 +261,12 @@ QWidget* ModuleBase_WidgetFactory::point2dDistanceControl(QWidget* theParent)
 
   return aDistWgt->getControl();
 }
+
+QWidget* ModuleBase_WidgetFactory::fileSelectorControl(QWidget* theParent)
+{
+  ModuleBase_WidgetFileSelector* aFileSelectorWgt =
+      new ModuleBase_WidgetFileSelector(theParent, myWidgetApi, myParentId);
+  myModelWidgets.append(aFileSelectorWgt);
+
+  return aFileSelectorWgt->getControl();
+}
index 81be16e7147393948d10d37798436a0342d03f50..643e85b67ddb69ae0b1f5711fdb633499749d751 100644 (file)
@@ -46,6 +46,7 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFactory
   QWidget* selectorControl(QWidget* theParent);
   QWidget* booleanControl(QWidget* theParent);
   QWidget* point2dDistanceControl(QWidget* theParent);
+  QWidget* fileSelectorControl(QWidget* theParent);
 
   /// Check whether the XML definition for the given type contains internal property
   /// \param theType the widget type
diff --git a/src/ModuleBase/ModuleBase_WidgetFileSelector.cpp b/src/ModuleBase/ModuleBase_WidgetFileSelector.cpp
new file mode 100644 (file)
index 0000000..7d834cc
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * ModuleBase_WidgetFileSelector.cpp
+ *
+ *  Created on: Aug 28, 2014
+ *      Author: sbh
+ */
+
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Object.h>
+#include <ModuleBase_WidgetFileSelector.h>
+
+#include <Config_WidgetAPI.h>
+
+#include <QGridLayout>
+#include <QFileDialog>
+#include <QLineEdit>
+#include <QList>
+#include <QObject>
+#include <QPushButton>
+#include <QString>
+#include <QLabel>
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <string>
+
+ModuleBase_WidgetFileSelector::ModuleBase_WidgetFileSelector(QWidget* theParent,
+                                                             const Config_WidgetAPI* theData,
+                                                             const std::string& theParentId)
+    : ModuleBase_ModelWidget(theParent, theData, theParentId)
+{
+  myHasDefaultValue = false;
+
+  myTitle = QString::fromStdString(theData->getProperty("title"));
+  //TODO(sbh): Get them from the feature
+  myFormats = getSupportedFormats(theData);
+  myDefaultPath = QString::fromStdString(theData->getProperty("path"));
+
+  myMainWidget = new QWidget(theParent);
+  QGridLayout* aMainLay = new QGridLayout(myMainWidget);
+  aMainLay->setContentsMargins(0, 0, 0, 0);
+  QLabel* aTitleLabel = new QLabel(myTitle, myMainWidget);
+  aTitleLabel->setIndent(1);
+  aMainLay->addWidget(aTitleLabel, 0, 0);
+  myPathField = new QLineEdit(myMainWidget);
+  aMainLay->addWidget(myPathField, 1, 0);
+  QPushButton* aSelectPathBtn = new QPushButton("...", myMainWidget);
+  aSelectPathBtn->setMaximumWidth(20);
+  aSelectPathBtn->setMaximumHeight(20);
+  aMainLay->addWidget(aSelectPathBtn, 1, 1);
+  aMainLay->setColumnStretch(0, 1);
+  myPathField->setMinimumHeight(20);
+  aMainLay->setHorizontalSpacing(1);
+  myMainWidget->setLayout(aMainLay);
+
+  connect(myPathField, SIGNAL(textChanged(const QString&)),
+          this,        SLOT(onPathChanged()));
+  connect(aSelectPathBtn, SIGNAL(clicked()),
+          this,        SLOT(onPathSelectionBtn()));
+}
+
+ModuleBase_WidgetFileSelector::~ModuleBase_WidgetFileSelector()
+{
+}
+
+bool ModuleBase_WidgetFileSelector::storeValue() const
+{
+  DataPtr aData = myFeature->data();
+  AttributeStringPtr aStringAttr = aData->string(attributeID());
+  QString aModelValue = QString::fromStdString(aStringAttr->value());
+  QString aWidgetValue = myPathField->text();
+  if(aModelValue != aWidgetValue) {
+    aStringAttr->setValue(aWidgetValue.toStdString());
+    updateObject(myFeature);
+  }
+  return true;
+}
+
+bool ModuleBase_WidgetFileSelector::restoreValue()
+{
+  DataPtr aData = myFeature->data();
+  AttributeStringPtr aStringAttr = aData->string(attributeID());
+
+  bool isBlocked = myPathField->blockSignals(true);
+  myPathField->setText(QString::fromStdString(aStringAttr->value()));
+  myPathField->blockSignals(isBlocked);
+
+  return true;
+}
+
+QWidget* ModuleBase_WidgetFileSelector::getControl() const
+{
+  return myMainWidget;
+}
+
+QList<QWidget*> ModuleBase_WidgetFileSelector::getControls() const
+{
+  QList<QWidget*> result;
+  QPushButton * aButton = myMainWidget->findChild<QPushButton *>();
+  result << aButton;
+  result << myPathField;
+  return result;
+}
+
+bool ModuleBase_WidgetFileSelector::isCurrentPathValid()
+{
+  QFileInfo aFile (myPathField->text());
+  return aFile.exists() && myFormats.contains(aFile.suffix(), Qt::CaseInsensitive);
+}
+
+
+void ModuleBase_WidgetFileSelector::onPathSelectionBtn()
+{
+  QString aFilter = formatsString(myFormats);
+  QString aFileName = QFileDialog::getOpenFileName(myMainWidget, myTitle, myDefaultPath, aFilter);
+  if (!aFileName.isEmpty()) {
+    myPathField->setText(aFileName);
+  }
+}
+
+void ModuleBase_WidgetFileSelector::onPathChanged()
+{
+  if(!isCurrentPathValid())
+    return;
+  storeValue();
+  emit valuesChanged();
+}
+
+QStringList ModuleBase_WidgetFileSelector::getSupportedFormats(const Config_WidgetAPI* theData) const
+{
+  QString aXMLFormat = QString::fromStdString(theData->getProperty("formats"));
+  aXMLFormat = aXMLFormat.toUpper();
+  const QChar kSep = ',';
+  return aXMLFormat.split(kSep, QString::SkipEmptyParts);
+}
+
+QString ModuleBase_WidgetFileSelector::formatsString(const QStringList theFormats) const
+{
+  QStringList aResult;
+  foreach(QString eachFormat, theFormats)  {
+    aResult << QString("%1 files (*.%1)").arg(eachFormat);
+  }
+  return aResult.join(";;");
+}
+
diff --git a/src/ModuleBase/ModuleBase_WidgetFileSelector.h b/src/ModuleBase/ModuleBase_WidgetFileSelector.h
new file mode 100644 (file)
index 0000000..2d48e43
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * ModuleBase_WidgetFileSelector.h
+ *
+ *  Created on: Aug 28, 2014
+ *      Author: sbh
+ */
+
+#ifndef MODULEBASE_WIDGETFILESELECTOR_H_
+#define MODULEBASE_WIDGETFILESELECTOR_H_
+
+#include <ModuleBase.h>
+#include <ModuleBase_ModelWidget.h>
+
+#include <QList>
+#include <QString>
+#include <QStringList>
+
+class QWidget;
+class QLineEdit;
+
+class MODULEBASE_EXPORT ModuleBase_WidgetFileSelector : public ModuleBase_ModelWidget
+{
+  Q_OBJECT
+ public:
+  ModuleBase_WidgetFileSelector(QWidget* theParent,
+                                const Config_WidgetAPI* theData,
+                                const std::string& theParentId);
+  virtual ~ModuleBase_WidgetFileSelector();
+
+  /// Saves the internal parameters to the given feature
+  /// \param theObject a model feature to be changed
+  virtual bool storeValue() const;
+
+  virtual bool restoreValue();
+
+  /// Returns the internal parent wiget control, that can be shown anywhere
+  /// \returns the widget
+  QWidget* getControl() const;
+
+  /// Returns list of widget controls
+  /// \return a control list
+  virtual QList<QWidget*> getControls() const;
+
+  /// Returns true if a file on the current path in the line edit
+  /// exists and has supported format
+  bool isCurrentPathValid();
+
+ public slots:
+  void onPathSelectionBtn();
+  void onPathChanged();
+
+ protected:
+  QStringList getSupportedFormats(const Config_WidgetAPI* theData) const;
+  QString formatsString(const QStringList theFormats) const;
+
+ private:
+  QLineEdit* myPathField;
+  QWidget* myMainWidget;
+  QStringList myFormats;
+
+  QString myTitle;
+  QString myDefaultPath;
+};
+
+#endif /* MODULEBASE_WIDGETFILESELECTOR_H_ */
index 2a6ba81ecfa2cb7fbe0712972387a54a9ea82c66..7786e85d73edc65e3aa8352278aad8f0f756727d 100644 (file)
Binary files a/src/PartSet/icons/import.png and b/src/PartSet/icons/import.png differ