From b97f4d67421685f99412ee79484c7a8482da1d2e Mon Sep 17 00:00:00 2001 From: sbh Date: Tue, 2 Sep 2014 19:44:44 +0400 Subject: [PATCH] Implementation of "Import" BREP and STEP functionality --- CMakeLists.txt | 1 + msvc10_env.bat | 6 + src/Config/Config_Keywords.h | 5 +- src/Config/Config_WidgetAPI.h | 1 + src/Config/plugins.xml | 1 + src/ExchangePlugin/CMakeLists.txt | 42 +++++ src/ExchangePlugin/ExchangePlugin.h | 18 ++ .../ExchangePlugin_ImportFeature.cpp | 159 ++++++++++++++++++ .../ExchangePlugin_ImportFeature.h | 69 ++++++++ src/ExchangePlugin/ExchangePlugin_Plugin.cpp | 30 ++++ src/ExchangePlugin/ExchangePlugin_Plugin.h | 23 +++ .../ExchangePlugin_Validators.cpp | 22 +++ .../ExchangePlugin_Validators.h | 20 +++ src/ExchangePlugin/plugin-Exchange.xml | 20 +++ src/Model/Model_FeatureValidator.cpp | 4 +- src/ModelAPI/ModelAPI_PluginManager.cpp | 1 + src/ModuleBase/CMakeLists.txt | 2 + src/ModuleBase/ModuleBase_Operation.cpp | 5 +- src/ModuleBase/ModuleBase_WidgetFactory.cpp | 13 +- src/ModuleBase/ModuleBase_WidgetFactory.h | 1 + .../ModuleBase_WidgetFileSelector.cpp | 145 ++++++++++++++++ .../ModuleBase_WidgetFileSelector.h | 65 +++++++ src/PartSet/icons/import.png | Bin 598 -> 1441 bytes 23 files changed, 644 insertions(+), 9 deletions(-) create mode 100644 src/ExchangePlugin/CMakeLists.txt create mode 100644 src/ExchangePlugin/ExchangePlugin.h create mode 100644 src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp create mode 100644 src/ExchangePlugin/ExchangePlugin_ImportFeature.h create mode 100644 src/ExchangePlugin/ExchangePlugin_Plugin.cpp create mode 100644 src/ExchangePlugin/ExchangePlugin_Plugin.h create mode 100644 src/ExchangePlugin/ExchangePlugin_Validators.cpp create mode 100644 src/ExchangePlugin/ExchangePlugin_Validators.h create mode 100644 src/ExchangePlugin/plugin-Exchange.xml create mode 100644 src/ModuleBase/ModuleBase_WidgetFileSelector.cpp create mode 100644 src/ModuleBase/ModuleBase_WidgetFileSelector.h 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 2a6ba81ecfa2cb7fbe0712972387a54a9ea82c66..7786e85d73edc65e3aa8352278aad8f0f756727d 100644 GIT binary patch literal 1441 zcmV;S1z!4zP)z zZHQb~8OML;<=%POiJ2su7t^gPtu&1qZJKD>sO^_U3c3)*LO{fR5DMD*K?SJLC-nVW4i4!L(-D@_4K&9H&2X=19L|Y5+ z&#KoUtaaJ?5J2F}Op8pLEd|&G`1Jt6cP?DIFhvqnpJ8uY90$63Jpk_m?;efY(ezZ@ zXk}Xp@XitI{04yFdH;bz`uJlXiQi~J?>$M9P_NgiR;!$Qd9v+;UkBhl-uq2byuMhT zndj;=FLCXO7ii8c;(eesf0Ojh<=D+v?*g7$1rS(o%j*dd;mT7l^0&vnPyOmFyH%SV z%?3j{!kZXnBI+{>rsDi>e>`;jtn>ckpGp3@V7>Q*@V_~b)EYehsjrYcf0p+wT%sH@ zQd1x`1u|VEGZtUWvAwj7TZf8ox>{>|@XA!>#t#ekeA9a8@h-4_fA*WQYFwbQQ1kQk0OeIhtCeQE&Warm^(%$FuW)p+#z)_qf*paL#e#@-^yLX1V1Z79A81NQH@y zevWch;{(~hKxwG`L^+EXi`aznn2pky;1{%0i1Iz&n=S6M~K#ljZikCoX;RwFcyplW6*o|^2c-^Lu1D|{MCmE zA<%3#Ns@%%!v>w61J1dD0BNm(jSLu#L=n=CUgE5G;9T#lJg-){!hh=uv=6K@J$(0jueXfm%o(|p<28j1s)<$cMXp2}2 z>mhPE7%K9By3EOKGfW)$#G3IT1iD&lYaj%C7<>?g5OA%Og6%kfjgUBx(i+L-P}{cw z0@fgLOx5Qpt&9_q-V$`R))isLmO%jCdz3YJrJ!7fp&}>&4OtK>iwW0mG?|`hF+aUT z`Ho#2``xLYu!tZceV4#?9vZw0LI{wLNJZ1wwTHQD^IV@^WOizi<(mykciu|=y@%Ox z=yu+A^dQAzktmKgRDbB>bO*o((lp&f9@_0TrDF%V{)ZPi{i`$N559%?=-U~7=r(S< zbCf8Gu-0OX!5Gs!xt^=OhI7~!B<9pxz)&ZaiB;8~?fzn-vkBmC!A_OIfk|0_n zXz2=y^n|6;SKZ(B6IV(}=P}VDVg!^{%3r+r$`xP{r~%b3Kn&!89AH+a)t#F3X{%l6 vcVB?8s^5j|esp*`f5qAAM0%5?TOR)bIYypPOGk|200000NkvXXu0mjfPxQ~M literal 598 zcmV-c0;&CpP)N2b zPDNB8b~7$DE-^7j^FlWO00EjwL_t(IPoWmxfr#yunib| z0ZkXI5-(_*B8nFf6a*D)Vj);4h6FJwL=8csh^4PE{{LoovsX;az_;hj%+9|v=d8eD zKw*3gO<-^sTphv|zz=AH6HqbZGiHoV1w_nv!Hlsc=Mn@_b7gS^P{1e#EQmQoO7sB( z%#WFSYS;;`Z5BBSDQM-L)PeO;!gr(I4!wdoU<+DtFEAbxJEr66&>ES3(8x=s0MC|i zOuoZBv1)rAz?_%DuUZHF*QJnx5#z%P%<9nSY7lyx?#MiBI)oh>op_nsmU4QFTYt_M z=!e9H=dY;-8O{|N?!+^kKQ8a%lx_2Ym=d>WC(*;E=s_c#{YMBrh?eW!^}4kjEEvzr8AVe# zpD>af8zZk?LHtGZ@;Pf911@jeCkPv5q90NazG%&B(j(>)9E6D#Db3=y@rn_b(=V`* kATc8s6dZ=Y;Qvwi1w`vVev38$@c;k-07*qoM6N<$f@kCKQ2+n{ -- 2.39.2