From: sbh Date: Tue, 2 Sep 2014 15:44:44 +0000 (+0400) Subject: Implementation of "Import" BREP and STEP functionality X-Git-Tag: V_0.4.4~94 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b97f4d67421685f99412ee79484c7a8482da1d2e;p=modules%2Fshaper.git Implementation of "Import" BREP and STEP functionality --- diff --git a/CMakeLists.txt b/CMakeLists.txt index de2256284..ae2ee1eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/msvc10_env.bat b/msvc10_env.bat index 03a087af4..a684f5e8b 100644 --- a/msvc10_env.bat +++ b/msvc10_env.bat @@ -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 diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index 434857827..f1e5e0122 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -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"; diff --git a/src/Config/Config_WidgetAPI.h b/src/Config/Config_WidgetAPI.h index d7c12e957..ad084049f 100644 --- a/src/Config/Config_WidgetAPI.h +++ b/src/Config/Config_WidgetAPI.h @@ -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(); diff --git a/src/Config/plugins.xml b/src/Config/plugins.xml index a4d1dbdae..7d6b81b6f 100644 --- a/src/Config/plugins.xml +++ b/src/Config/plugins.xml @@ -3,6 +3,7 @@ + diff --git a/src/ExchangePlugin/CMakeLists.txt b/src/ExchangePlugin/CMakeLists.txt new file mode 100644 index 000000000..1a5299ad6 --- /dev/null +++ b/src/ExchangePlugin/CMakeLists.txt @@ -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 index 000000000..183563e34 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin.h @@ -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 index 000000000..a0c659805 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp @@ -0,0 +1,159 @@ +/* + * ExchangePlugin_ImportFeature.cpp + * + * Created on: Aug 28, 2014 + * Author: sbh + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#ifdef _DEBUG +#include +#include +#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( + 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 aResult = document()->createBody(data()); + boost::shared_ptr 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 index 000000000..4b3b7a803 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.h @@ -0,0 +1,69 @@ +/* + * ExchangePlugin_ImportFeature.h + * + * Created on: Aug 28, 2014 + * Author: sbh + */ + +#ifndef EXCHANGEPLUGIN_IMPORTFEATURE_H_ +#define EXCHANGEPLUGIN_IMPORTFEATURE_H_ + +#include +#include + +#include + +#ifdef WIN32 +#include +#define LibHandle HMODULE +#define LoadLib( name ) LoadLibrary( name ) +#define GetProc GetProcAddress +#define UnLoadLib( handle ) FreeLibrary( handle ); +#else +#include +#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 index 000000000..97d2b6e58 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_Plugin.cpp @@ -0,0 +1,30 @@ +/* + * + */ + +#include +#include + +#include + +#include + +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 index 000000000..5cb5f20f0 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_Plugin.h @@ -0,0 +1,23 @@ +// File: ExchangePlugin_Plugin.hxx +// Created: 07 July 2014 +// Author: Vitaly SMETANNIKOV + +#ifndef EXCHANGEPLUGIN_PLUGIN_H_ +#define EXCHANGEPLUGIN_PLUGIN_H_ + +#include +#include +#include + +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 index 000000000..99e14bea9 --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_Validators.cpp @@ -0,0 +1,22 @@ +// File: SketchPlugin_Validators.cpp +// Created: 01 Aug 2014 +// Author: Vitaly SMETANNIKOV + +#include +#include +#include +#include + +#include +#include + + +bool ExchangePlugin_ImportFormatValidator::isValid(const FeaturePtr& theFeature, + const std::list& 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 index 000000000..c4400fc9f --- /dev/null +++ b/src/ExchangePlugin/ExchangePlugin_Validators.h @@ -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 + +class ExchangePlugin_ImportFormatValidator : public ModelAPI_AttributeValidator +{ + public: + virtual bool isValid(const FeaturePtr& theFeature, + const std::list& theArguments, + const ObjectPtr& theObject) const; + +}; + +#endif diff --git a/src/ExchangePlugin/plugin-Exchange.xml b/src/ExchangePlugin/plugin-Exchange.xml new file mode 100644 index 000000000..48cedc48f --- /dev/null +++ b/src/ExchangePlugin/plugin-Exchange.xml @@ -0,0 +1,20 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/Model/Model_FeatureValidator.cpp b/src/Model/Model_FeatureValidator.cpp index f311e54db..b4b4fb8cc 100644 --- a/src/Model/Model_FeatureValidator.cpp +++ b/src/Model/Model_FeatureValidator.cpp @@ -11,9 +11,7 @@ #include #include -bool Model_FeatureValidator::isValid(const boost::shared_ptr& theFeature -/*, const std::string theAttr*/ -/*, std::list theArguments*/) const +bool Model_FeatureValidator::isValid(const boost::shared_ptr& theFeature) const { boost::shared_ptr aData = theFeature->data(); if (!aData->isValid()) diff --git a/src/ModelAPI/ModelAPI_PluginManager.cpp b/src/ModelAPI/ModelAPI_PluginManager.cpp index a0750645a..35048c425 100644 --- a/src/ModelAPI/ModelAPI_PluginManager.cpp +++ b/src/ModelAPI/ModelAPI_PluginManager.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index b21756a5c..f65d8c989 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -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 diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index 305b810c6..91130350c 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -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 aWidgets = getDescription()->modelWidgets(); QList::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end(); diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index d75479e74..46b7e03d0 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -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(); +} diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.h b/src/ModuleBase/ModuleBase_WidgetFactory.h index 81be16e71..643e85b67 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetFactory.h @@ -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 index 000000000..7d834cca4 --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetFileSelector.cpp @@ -0,0 +1,145 @@ +/* + * ModuleBase_WidgetFileSelector.cpp + * + * Created on: Aug 28, 2014 + * Author: sbh + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 ModuleBase_WidgetFileSelector::getControls() const +{ + QList result; + QPushButton * aButton = myMainWidget->findChild(); + 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 index 000000000..2d48e430b --- /dev/null +++ b/src/ModuleBase/ModuleBase_WidgetFileSelector.h @@ -0,0 +1,65 @@ +/* + * ModuleBase_WidgetFileSelector.h + * + * Created on: Aug 28, 2014 + * Author: sbh + */ + +#ifndef MODULEBASE_WIDGETFILESELECTOR_H_ +#define MODULEBASE_WIDGETFILESELECTOR_H_ + +#include +#include + +#include +#include +#include + +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 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_ */ diff --git a/src/PartSet/icons/import.png b/src/PartSet/icons/import.png index 2a6ba81ec..7786e85d7 100644 Binary files a/src/PartSet/icons/import.png and b/src/PartSet/icons/import.png differ