From: nds Date: Fri, 1 Apr 2016 16:05:20 +0000 (+0300) Subject: Issue #1368: Creation of a Qt panel. Persistent mechanism. X-Git-Tag: V_2.3.0~346 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=ab9d4995b9893f1aa2a48d6189df6477f8f5bb41;p=modules%2Fshaper.git Issue #1368: Creation of a Qt panel. Persistent mechanism. --- diff --git a/src/ModuleBase/ModuleBase_IWidgetCreator.cpp b/src/ModuleBase/ModuleBase_IWidgetCreator.cpp index 1ea485604..10e495f7b 100755 --- a/src/ModuleBase/ModuleBase_IWidgetCreator.cpp +++ b/src/ModuleBase/ModuleBase_IWidgetCreator.cpp @@ -11,7 +11,8 @@ ModuleBase_IWidgetCreator::~ModuleBase_IWidgetCreator() } QWidget* ModuleBase_IWidgetCreator::createPanelByType(const std::string& theType, - QWidget* theParent) + QWidget* theParent, + const FeaturePtr& theFeature) { return 0; } diff --git a/src/ModuleBase/ModuleBase_IWidgetCreator.h b/src/ModuleBase/ModuleBase_IWidgetCreator.h index cbab144be..eac988263 100755 --- a/src/ModuleBase/ModuleBase_IWidgetCreator.h +++ b/src/ModuleBase/ModuleBase_IWidgetCreator.h @@ -5,6 +5,8 @@ #include "ModuleBase.h" +#include "ModelAPI_Feature.h" + #include #include #include @@ -48,9 +50,11 @@ public: /// The default implementation is empty /// \param theType a panel type /// \param theParent a parent widget + /// \param theFeature a feature modified in the panel /// \return created widget or null virtual QWidget* createPanelByType(const std::string& theType, - QWidget* theParent); + QWidget* theParent, + const FeaturePtr& theFeature); /// Create page by its type /// The default implementation is empty diff --git a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp index 2c5d6772b..13c7bf571 100755 --- a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.cpp @@ -80,12 +80,14 @@ bool ModuleBase_WidgetCreatorFactory::hasPanelWidget(const std::string& theType) return myPanelToCreator.contains(theType); } -QWidget* ModuleBase_WidgetCreatorFactory::createPanel(const std::string& theType, QWidget* theParent) +QWidget* ModuleBase_WidgetCreatorFactory::createPanelByType(const std::string& theType, + QWidget* theParent, + const FeaturePtr& theFeature) { QWidget* aPanel = 0; if (myPanelToCreator.contains(theType)) { WidgetCreatorPtr aCreator = myPanelToCreator[theType]; - aPanel = aCreator->createPanelByType(theType, theParent); + aPanel = aCreator->createPanelByType(theType, theParent, theFeature); } return aPanel; } diff --git a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h index 6373eebba..5cbc34c06 100755 --- a/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetCreatorFactory.h @@ -16,6 +16,8 @@ #include +#include + class ModuleBase_ModelWidget; class ModuleBase_PageBase; class ModuleBase_IWorkshop; @@ -48,8 +50,10 @@ class MODULEBASE_EXPORT ModuleBase_WidgetCreatorFactory /// Create panel by its type /// \param theType a type /// \param theParent a parent widget + /// \param theFeature a feature to fill the panel /// \return a created panel or null - QWidget* createPanel(const std::string& theType, QWidget* theParent); + QWidget* createPanelByType(const std::string& theType, QWidget* theParent, + const FeaturePtr& theFeature); /// Returns true if there is a creator, which can make a page by the type /// \param theType a type diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.cpp b/src/ModuleBase/ModuleBase_WidgetFactory.cpp index e8ae59b50..70eef3959 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.cpp +++ b/src/ModuleBase/ModuleBase_WidgetFactory.cpp @@ -73,12 +73,14 @@ void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage) { std::string aWType = myWidgetApi->widgetType(); if (aWType == NODE_FEATURE) { - QWidget* aPanel = createPanel(thePage->pageWidget()); - if (aPanel) { - thePage->addWidget(aPanel); - thePage->alignToTop(); + // if XML definition of the feature contains the next key, the widgets should not be created, + // but a specific panel should be made. However, to provide persistent of the panel values, + // we need to get into the panel the feature of the operation. As a result this panel should + // be created after the feature creating(create operation). The method setPanel() of this + // class is used for this. Here, we just return to avoid the widgets creation. + std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); + if (!aPanelName.empty()) return; - } } if (!myWidgetApi->toChildWidget()) @@ -130,6 +132,18 @@ void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage) thePage->alignToTop(); } +void ModuleBase_WidgetFactory::createPanel(ModuleBase_PageBase* thePage, + const FeaturePtr& theFeature) +{ + std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); + if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) { + QWidget* aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanelByType(aPanelName, + thePage->pageWidget(), theFeature); + thePage->addWidget(aPanel); + thePage->alignToTop(); + } +} + void ModuleBase_WidgetFactory::createWidget(ModuleBase_PageBase* thePage, const std::string& theWidgetId) { @@ -227,15 +241,6 @@ void ModuleBase_WidgetFactory::moveToWidgetId(const std::string& theWidgetId, bo } while (!theFound && myWidgetApi->toNextWidget()); } -QWidget* ModuleBase_WidgetFactory::createPanel(QWidget* theParent) -{ - QWidget* aPanel = 0; - std::string aPanelName = myWidgetApi->getProperty(PROPERTY_PANEL_ID); - if (!aPanelName.empty() && ModuleBase_WidgetCreatorFactory::get()->hasPanelWidget(aPanelName)) - aPanel = ModuleBase_WidgetCreatorFactory::get()->createPanel(aPanelName, theParent); - return aPanel; -} - ModuleBase_PageBase* ModuleBase_WidgetFactory::createPageByType(const std::string& theType, QWidget* theParent) { diff --git a/src/ModuleBase/ModuleBase_WidgetFactory.h b/src/ModuleBase/ModuleBase_WidgetFactory.h index 180c265b8..96489ce8e 100644 --- a/src/ModuleBase/ModuleBase_WidgetFactory.h +++ b/src/ModuleBase/ModuleBase_WidgetFactory.h @@ -41,6 +41,11 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFactory /// \param thePage a parent page void createWidget(ModuleBase_PageBase* thePage); + /// Creates property panel content for the feature + /// \param thePage a parent page + /// \param theFeature a feature to fill the panel + void createPanel(ModuleBase_PageBase* thePage, const FeaturePtr& theFeature); + /// Creates one widget for property panel for the widget with given index /// \param theParent a parent widget /// \param theWidgetId a widget index @@ -67,11 +72,6 @@ protected: /// check if ModuleBase_Widget has expandable widgets in getControls bool hasExpandingControls(QWidget* theParent); - /// creates panel control, if the corresponded parameter is provided by feature - /// \param theParent a parent widget - /// \return true if the panel is created - QWidget* createPanel(QWidget* theParent); - /// Create page by its type /// \param theType a type /// \param theParent a parent widget diff --git a/src/SamplePanelPlugin/CMakeLists.txt b/src/SamplePanelPlugin/CMakeLists.txt index afb6f0482..ab48f6073 100755 --- a/src/SamplePanelPlugin/CMakeLists.txt +++ b/src/SamplePanelPlugin/CMakeLists.txt @@ -1,7 +1,7 @@ ## Copyright (C) 2014-20xx CEA/DEN, EDF R&D INCLUDE(Common) -INCLUDE(UnitTest) +SET(CMAKE_AUTOMOC ON) SET(PROJECT_HEADERS SamplePanelPlugin.h diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_Feature.cpp b/src/SamplePanelPlugin/SamplePanelPlugin_Feature.cpp index 3beab1b74..e2959314a 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_Feature.cpp +++ b/src/SamplePanelPlugin/SamplePanelPlugin_Feature.cpp @@ -6,7 +6,14 @@ #include "SamplePanelPlugin_Feature.h" +#include "ModelAPI_AttributeInteger.h" + SamplePanelPlugin_Feature::SamplePanelPlugin_Feature() : ModelAPI_Feature() { } + +void SamplePanelPlugin_Feature::initAttributes() +{ + data()->addAttribute(VALUE_ID(), ModelAPI_AttributeInteger::typeId()); +} diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_Feature.h b/src/SamplePanelPlugin/SamplePanelPlugin_Feature.h index 3353b906d..c17483624 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_Feature.h +++ b/src/SamplePanelPlugin/SamplePanelPlugin_Feature.h @@ -25,8 +25,15 @@ class SamplePanelPlugin_Feature : public ModelAPI_Feature return MY_SAMPLE_PANEL_FEATURE_ID; } + /// Total number of objects, initial and translated objects + inline static const std::string& VALUE_ID() + { + static const std::string MY_VALUE_ID("Value"); + return MY_VALUE_ID; + } + /// Request for initialization of data model of the object: adding all attributes - virtual void initAttributes() {}; + virtual void initAttributes(); /// Returns the unique kind of a feature virtual const std::string& getKind() { diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_Panel.cpp b/src/SamplePanelPlugin/SamplePanelPlugin_Panel.cpp index baaecd720..36225355f 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_Panel.cpp +++ b/src/SamplePanelPlugin/SamplePanelPlugin_Panel.cpp @@ -5,21 +5,62 @@ // Author: Natalia ERMOLAEVA #include +#include + +#include +#include + +#include #include #include #include SamplePanelPlugin_Panel::SamplePanelPlugin_Panel(QWidget* theParent) - : QWidget(theParent) +: QWidget(theParent), myDefaultValue(0) { QGridLayout* aLayout = new QGridLayout(this); aLayout->addWidget(new QLabel("Values:"), 0, 0); - QComboBox* aComboBox = new QComboBox(this); - aComboBox->addItem("Value_1"); - aComboBox->addItem("Value_2"); - aComboBox->addItem("Value_3"); + myComboBox = new QComboBox(this); + myComboBox->addItem("Value_1"); + myComboBox->addItem("Value_2"); + myComboBox->addItem("Value_3"); + + connect(myComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); + aLayout->addWidget(myComboBox, 0, 1); +} + +void SamplePanelPlugin_Panel::setFeature(const FeaturePtr& theFeature) +{ + myFeature = theFeature; + + AttributePtr anAttribute = myFeature->attribute(SamplePanelPlugin_Feature::VALUE_ID()); + AttributeIntegerPtr aValueAttribute = + std::dynamic_pointer_cast(anAttribute); + /// the attribute should be filled with some value, because Apply button of the Property + /// panel is enabled only if all attributes of the feature are initialized + /// It is possible to make it in the initializeAttribute method of the feature after + /// attribute creation + if (!aValueAttribute->isInitialized()) { + aValueAttribute->setValue(myDefaultValue); + /// to update error state of the feature: previous value was that this attribute is not + /// initialized yet. Apply of Property panel was disabled. + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); + } + + int aValueId = aValueAttribute->value(); + myComboBox->setCurrentIndex(aValueId); +} + +void SamplePanelPlugin_Panel::onCurrentIndexChanged(int theIndex) +{ + if (!myFeature.get()) + return; - aLayout->addWidget(aComboBox, 0, 1); + AttributePtr anAttribute = myFeature->attribute(SamplePanelPlugin_Feature::VALUE_ID()); + AttributeIntegerPtr aValueAttribute = + std::dynamic_pointer_cast(anAttribute); + aValueAttribute->setValue(theIndex); + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); } diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_Panel.h b/src/SamplePanelPlugin/SamplePanelPlugin_Panel.h index 29c2859d8..1855e093f 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_Panel.h +++ b/src/SamplePanelPlugin/SamplePanelPlugin_Panel.h @@ -9,17 +9,36 @@ #include +#include + +class QComboBox; + /*! * \ingroup GUI - * Represent a property panel's list of ModuleBase_ModelWidgets. + * Represent a content of the property panel to show/modify parameters of some feature. */ class SamplePanelPlugin_Panel : public QWidget { + Q_OBJECT public: /// Constructs a panel page SamplePanelPlugin_Panel(QWidget* theParent); /// Destructs the page virtual ~SamplePanelPlugin_Panel() {} + + /// Fill the panel by the feature + /// \param theFeature a feature to fill the panel controls + void setFeature(const FeaturePtr& theFeature); + +protected slots: + /// Update feature attribute by the current value of combo box + /// \param theIndex a combo box modified value + void onCurrentIndexChanged(int theIndex); + +private: + FeaturePtr myFeature; // the feature which corresponds to the current panel + QComboBox* myComboBox; // control for value attribute of the current feature + int myDefaultValue; /// the default combo box value }; #endif /* SAMPLEPANELPLUGIN_PANEL_H_ */ diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.cpp b/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.cpp index 9389905ce..90c9249de 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.cpp +++ b/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.cpp @@ -20,14 +20,17 @@ void SamplePanelPlugin_WidgetCreator::panelTypes(std::set& theTypes } QWidget* SamplePanelPlugin_WidgetCreator::createPanelByType(const std::string& theType, - QWidget* theParent) + QWidget* theParent, + const FeaturePtr& theFeature) { QWidget* aWidget = 0; if (myPanelTypes.find(theType) == myPanelTypes.end()) return aWidget; if (theType == "QtPanel") { - aWidget = new SamplePanelPlugin_Panel(theParent); + SamplePanelPlugin_Panel* aPanel = new SamplePanelPlugin_Panel(theParent); + aPanel->setFeature(theFeature); + aWidget = aPanel; } return aWidget; diff --git a/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.h b/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.h index 315742fa6..548cbba1a 100755 --- a/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.h +++ b/src/SamplePanelPlugin/SamplePanelPlugin_WidgetCreator.h @@ -36,9 +36,11 @@ public: /// Create panel control by its type. /// \param theType a panel type /// \param theParent a parent widget + /// \param theFeature a feature to fill the panel /// \return created widget or null virtual QWidget* createPanelByType(const std::string& theType, - QWidget* theParent); + QWidget* theParent, + const FeaturePtr& theFeature); private: std::set myPanelTypes; /// types of panels }; diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index 949d9f9f3..ad8596ab3 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -8,7 +8,8 @@ #include "XGUI_ModuleConnector.h" #include "XGUI_Workshop.h" #include "XGUI_ErrorMgr.h" -#include +#include "XGUI_Tools.h" +#include "XGUI_ObjectsBrowser.h" #include #include @@ -233,7 +234,7 @@ bool XGUI_OperationMgr::commitAllOperations() bool isCompositeCommitted = false; while (hasOperation()) { ModuleBase_Operation* anOperation = currentOperation(); - if (workshop()->errorMgr()->isApplyEnabled()) { + if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled()) { onCommitOperation(); } else { abortOperation(anOperation); @@ -259,12 +260,12 @@ void XGUI_OperationMgr::onValidateOperation() ModuleBase_OperationFeature* aFOperation = dynamic_cast (currentOperation()); if(aFOperation && aFOperation->feature().get()) - workshop()->errorMgr()->updateActions(aFOperation->feature()); + XGUI_Tools::workshop(myWorkshop)->errorMgr()->updateActions(aFOperation->feature()); } void XGUI_OperationMgr::updateApplyOfOperations(ModuleBase_Operation* theOperation) { - XGUI_ErrorMgr* anErrorMgr = workshop()->errorMgr(); + XGUI_ErrorMgr* anErrorMgr = XGUI_Tools::workshop(myWorkshop)->errorMgr(); if (theOperation) { ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); if (aFOperation) @@ -356,7 +357,7 @@ bool XGUI_OperationMgr::canStartOperation(const QString& theId) else if (canStopOperation(aCurrentOp)) { // the started operation is granted in the parrent operation, // e.g. current - Line in Sketch, started Circle - if (workshop()->errorMgr()->isApplyEnabled() && aCurrentOp->isModified()) + if (XGUI_Tools::workshop(myWorkshop)->errorMgr()->isApplyEnabled() && aCurrentOp->isModified()) aCurrentOp->commit(); else abortOperation(aCurrentOp); @@ -661,25 +662,19 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) // after widget, object browser and viewer should process delete /// other widgets such as line edit controls should not lead to /// processing delete by workshop - XGUI_ObjectsBrowser* aBrowser = workshop()->objectBrowser(); + XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser(); QWidget* aViewPort = myWorkshop->viewer()->activeViewPort(); // property panel child object is processed to process delete performed on Apply button of PP if (theObject == aBrowser->treeView() || isChildObject(theObject, aViewPort) || isPPChildObject) - workshop()->deleteObjects(); + XGUI_Tools::workshop(myWorkshop)->deleteObjects(); isAccepted = true; } return isAccepted; } -XGUI_Workshop* XGUI_OperationMgr::workshop() const -{ - XGUI_ModuleConnector* aConnector = dynamic_cast(myWorkshop); - return aConnector->workshop(); -} - bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* theParent) { bool isPPChild = false; diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index 3b08ba8b9..bbc07a9a4 100755 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -53,6 +53,9 @@ Q_OBJECT void setWorkshop(ModuleBase_IWorkshop* theWorkshop) { myWorkshop = theWorkshop; }; + /// Current workshop + ModuleBase_IWorkshop* workshop() const { return myWorkshop; } + /// Returns the current operation or NULL /// \return the current operation ModuleBase_Operation* currentOperation() const; @@ -208,8 +211,6 @@ protected: // TEMPORARY void onOperationResumed(); private: - XGUI_Workshop* workshop() const; - /// Checks if the object is a parent or a child under /// \param theObject an investivated object /// \param theParent a candidate to be a parent diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index 8b1ab4f03..a3abb42d2 100755 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -155,6 +157,25 @@ void XGUI_PropertyPanel::updateContentWidget(FeaturePtr theFeature) repaint(); } +void XGUI_PropertyPanel::createContentPanel(FeaturePtr theFeature) +{ + // Invalid feature case on abort of the operation + if (theFeature.get() == NULL) + return; + if (theFeature->isAction() || !theFeature->data()) + return; + + if (myWidgets.empty()) { + ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + QString aXmlRepr = anOperation->getDescription()->xmlRepresentation(); + + ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myOperationMgr->workshop()); + aFactory.createPanel(contentWidget(), theFeature); + /// Apply button should be update if the feature was modified by the panel + myOperationMgr->onValidateOperation(); + } +} + void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget) { // it is possible that the property panel widgets have not been visualized diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index a4df2a072..a1ee29db6 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -106,11 +106,15 @@ Q_OBJECT XGUI_OperationMgr* operationMgr() const { return myOperationMgr; } public slots: - - /// \brief Update all widgets in property panel with values from the given feature - /// \param theFeature a Feature to update values in widgets + /// \brief Update all widgets in property panel with values from the given feature + /// \param theFeature a Feature to update values in widgets void updateContentWidget(FeaturePtr theFeature); + /// \brief If the XML definition of the feature contains information about specific + /// content of the property panel, it creates the panel and allow filling it by the given feature + /// \param theFeature a Feature to fill property panel + void createContentPanel(FeaturePtr theFeature); + /** * Makes the given widget active, highlights it and removes * highlighting from the previous active widget diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index 5a4b943f7..d418c1ba3 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -167,8 +167,10 @@ void XGUI_WorkshopListener::processEvent(const std::shared_ptr& if (anOperationMgr->startOperation(anOperation)) { ModuleBase_OperationFeature* aFOperation = dynamic_cast(anOperation); - if (aFOperation) + if (aFOperation) { workshop()->propertyPanel()->updateContentWidget(aFOperation->feature()); + workshop()->propertyPanel()->createContentPanel(aFOperation->feature()); + } if (!anOperation->getDescription()->hasXmlRepresentation()) { if (anOperation->commit()) workshop()->updateCommandStatus();