From f78afe4d9b7611ab7f4d42df1329b481fb2265ce Mon Sep 17 00:00:00 2001 From: Artem Zhidkov Date: Mon, 18 May 2020 17:02:52 +0300 Subject: [PATCH] Issue #19094: Non-translation of filters on groups in SHAPER --- src/FiltersPlugin/CMakeLists.txt | 9 +- src/FiltersPlugin/FiltersPlugin_msg_en.ts | 310 +++++++++++++++++ src/FiltersPlugin/FiltersPlugin_msg_fr.ts | 311 ++++++++++++++++++ src/Model/Model_FeatureValidator.cpp | 7 +- src/ModuleBase/ModuleBase_ModelWidget.cpp | 3 +- src/ModuleBase/ModuleBase_ModelWidget.h | 13 +- .../ModuleBase_WidgetSelectionFilter.cpp | 56 ++-- .../ModuleBase_WidgetSelectionFilter.h | 11 + 8 files changed, 694 insertions(+), 26 deletions(-) create mode 100644 src/FiltersPlugin/FiltersPlugin_msg_en.ts create mode 100644 src/FiltersPlugin/FiltersPlugin_msg_fr.ts diff --git a/src/FiltersPlugin/CMakeLists.txt b/src/FiltersPlugin/CMakeLists.txt index 7c294c82f..bcec89ff8 100644 --- a/src/FiltersPlugin/CMakeLists.txt +++ b/src/FiltersPlugin/CMakeLists.txt @@ -78,10 +78,16 @@ SET(XML_RESOURCES filter-TopoConnectedFaces.xml ) +SET(TEXT_RESOURCES + FiltersPlugin_msg_en.ts + FiltersPlugin_msg_fr.ts +) + SOURCE_GROUP ("XML Files" FILES ${XML_RESOURCES}) +SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES}) ADD_DEFINITIONS(-DFILTERS_EXPORTS ${OpenCASCADE_DEFINITIONS}) -ADD_LIBRARY(FiltersPlugin SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES}) +ADD_LIBRARY(FiltersPlugin SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES}) TARGET_LINK_LIBRARIES(FiltersPlugin ${PROJECT_LIBRARIES}) INCLUDE_DIRECTORIES( @@ -99,6 +105,7 @@ INCLUDE_DIRECTORIES( INSTALL(TARGETS FiltersPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES}) INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}) INSTALL(FILES ${PROJECT_PYFILES} DESTINATION ${SHAPER_INSTALL_ADDONS}) +INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}) ADD_UNIT_TESTS( diff --git a/src/FiltersPlugin/FiltersPlugin_msg_en.ts b/src/FiltersPlugin/FiltersPlugin_msg_en.ts new file mode 100644 index 000000000..e20f87ad1 --- /dev/null +++ b/src/FiltersPlugin/FiltersPlugin_msg_en.ts @@ -0,0 +1,310 @@ + + + + + + + workshop + + Selection filters + Selection filters + + + + + + FiltersSelection + + + + + + Selection filters + Selection filters + + + Filters + Filters + + + Add new filter... + Add new filter... + + + Delete the filter + Delete the filter + + + Reverse the filter + Reverse the filter + + + Selection by filters + Selection by filters + + + Number of selected objects: + Number of selected objects: + + + Select + Select + + + Selection is empty + Selection is empty + + + Show only + Show only + + + Belongs to + Belongs to + + + External faces + External faces + + + Horizontal faces + Horizontal faces + + + On geometry + On geometry + + + On line + On line + + + On plane + On plane + + + On plane side + On plane side + + + On/In/Out a solid + On/In/Out a solid + + + Opposite to an edge + Opposite to an edge + + + Topologically connected faces + Topologically connected faces + + + Vertical faces + Vertical faces + + + Attribute "%1" is not initialized. + Select a shape. + + + + FiltersSelection:FiltersPlugin_ShapeType + + Unknown error. + Unknown error. + + + + FiltersSelection:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + It does not contain element with acceptable shape type. The type should be one of the next: %1 + + + The object is empty + The object is empty + + + + + + BelongsTo + + Objects: + Objects: + + + Select objects to limit selection. + Select objects to limit selection. + + + + + + OnGeometry + + Select objects to limit selection. + Select objects to limit selection. + + + Shapes: + Shapes: + + + + OnGeometry:FiltersPlugin_ShapeType + + Unknown error. + Unknown error. + + + + + + OnLine + + Lines: + Lines: + + + Select vertices or segments. + Select vertices or segments. + + + + OnLine:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + It does not contain element with acceptable shape type. The type should be one of the next: %1 + + + + + + OnPlane + + Planes: + Planes: + + + Select planes or planar faces. + Select planes or planar faces. + + + + OnPlane:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + It does not contain element with acceptable shape type. The type should be one of the next: %1 + + + + + + OnPlaneSide + + Plane: + Plane: + + + Select plane or planar face. + Select plane or planar face. + + + + OnPlaneSide:GeomValidators_ShapeType + + The object is empty + The object is empty + + + + + + OppositeToEdge + + Edge: + Edge: + + + Select edge. + Select edge. + + + + OppositeToEdge:GeomValidators_ShapeType + + The object is empty + The object is empty + + + + + + RelativeToSolid + + In + In + + + In & On + In & On + + + Not On + Not On + + + On + On + + + On & Out + On & Out + + + Out + Out + + + Select a solid. + Select a solid. + + + Solid: + Solid: + + + + RelativeToSolid:GeomValidators_ShapeType + + The object is empty + The object is empty + + + + + + TopoConnectedFaces + + Propagation + Propagation + + + Select vertex, edge or face. + Select vertex, edge or face. + + + Shape: + Shape: + + + + TopoConnectedFaces:GeomValidators_ShapeType + + The object is empty + The object is empty + + + + diff --git a/src/FiltersPlugin/FiltersPlugin_msg_fr.ts b/src/FiltersPlugin/FiltersPlugin_msg_fr.ts new file mode 100644 index 000000000..16b245820 --- /dev/null +++ b/src/FiltersPlugin/FiltersPlugin_msg_fr.ts @@ -0,0 +1,311 @@ + + + + + + + + workshop + + Selection filters + Filtres de sélection + + + + + + FiltersSelection + + + + + + Selection filters + Filtres de sélection + + + Filters + Filtres + + + Add new filter... + Ajouter un nouveau filtre ... + + + Delete the filter + Supprimer le filtre + + + Reverse the filter + Inversez le filtre + + + Selection by filters + Sélection par filtres + + + Number of selected objects: + Nombre d'objets sélectionnés: + + + Select + Sélectionner + + + Selection is empty + La sélection est vide + + + Show only + Montrer seulement + + + Belongs to + Appartient à + + + External faces + Externe faces + + + Horizontal faces + Faces horizontales + + + On geometry + Sur la géométrie + + + On line + En ligne + + + On plane + En plan + + + On plane side + En côté plan + + + On/In/Out a solid + Sur/Dans/Dehors un solide + + + Opposite to an edge + En face d'un bord + + + Topologically connected faces + Faces topologiquement connectés + + + Vertical faces + Faces verticales + + + Attribute "%1" is not initialized. + Sélectionnez un objet. + + + + FiltersSelection:FiltersPlugin_ShapeType + + Unknown error. + Erreur inconnue. + + + + FiltersSelection:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + Il ne contient pas d'élément avec un type de forme acceptable. Le type doit être l'un des prochains: %1 + + + The object is empty + L'objet est vide. + + + + + + BelongsTo + + Objects: + Objets: + + + Select objects to limit selection. + Sélectionner des objets pour limiter la sélection + + + + + + OnGeometry + + Select objects to limit selection. + Sélectionner des objets pour limiter la sélection + + + Shapes: + Objets: + + + + OnGeometry:FiltersPlugin_ShapeType + + Unknown error. + Erreur inconnue. + + + + + + OnLine + + Lines: + Lignes: + + + Select vertices or segments. + AZV Select vertices or segments. + + + + OnLine:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + Il ne contient pas d'élément avec un type de forme acceptable. Le type doit être l'un des prochains: %1 + + + + + + OnPlane + + Planes: + Plans: + + + Select planes or planar faces. + Sélectionnez des plans ou des faces planes. + + + + OnPlane:GeomValidators_ShapeType + + It does not contain element with acceptable shape type. The type should be one of the next: %1 + Il ne contient pas d'élément avec un type de forme acceptable. Le type doit être l'un des prochains: %1 + + + + + + OnPlaneSide + + Plane: + Plan: + + + Select plane or planar face. + Sélectionnez un plan ou une face plane. + + + + OnPlaneSide:GeomValidators_ShapeType + + The object is empty + L'objet est vide. + + + + + + OppositeToEdge + + Edge: + Arête: + + + Select edge. + Sélectionnez le arête. + + + + OppositeToEdge:GeomValidators_ShapeType + + The object is empty + L'objet est vide. + + + + + + RelativeToSolid + + In + Dans + + + In & On + Dans et Sur + + + Not On + Pas Sur + + + On + Sur + + + On & Out + Sur et Dehors + + + Out + Dehors + + + Select a solid. + Sélectionnez un solide. + + + Solid: + Solide: + + + + RelativeToSolid:GeomValidators_ShapeType + + The object is empty + L'objet est vide. + + + + + + TopoConnectedFaces + + Propagation + Propagation + + + Select vertex, edge or face. + Sélectionnez le sommet, l'arête ou la face. + + + Shape: + Objet: + + + + TopoConnectedFaces:GeomValidators_ShapeType + + The object is empty + L'objet est vide. + + + + diff --git a/src/Model/Model_FeatureValidator.cpp b/src/Model/Model_FeatureValidator.cpp index 794fc048f..1241f3ce6 100644 --- a/src/Model/Model_FeatureValidator.cpp +++ b/src/Model/Model_FeatureValidator.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,11 @@ bool Model_FeatureValidator::isValid(const std::shared_ptr& th aFeatureFind->second.find(*it) == aFeatureFind->second.end()) { theError = "Attribute \"%1\" is not initialized."; theError.addParameter(anAttr->id()); - theError.setContext(theFeature->getKind() + ":" + anAttr->id()); + // workaround for the filters selection feature: do not append the attribute id + if (std::dynamic_pointer_cast(theFeature)) + theError.setContext(theFeature->getKind()); + else + theError.setContext(theFeature->getKind() + ":" + anAttr->id()); return false; } } diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index b3bc3a100..e232d1d89 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -191,7 +191,6 @@ QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const if (!feature().get()) return anError; - std::string aFeatureID = feature()->getKind(); std::string anAttributeID = attributeID(); AttributePtr anAttribute = feature()->attribute(anAttributeID); if (!anAttribute.get()) @@ -206,7 +205,7 @@ QString ModuleBase_ModelWidget::getError(const bool theValueStateChecked) const anErrorMsg = "Unknown error."; if (anErrorMsg.context().empty()) { - anErrorMsg.setContext(aFeatureID + ":" + anAttributeID + ":" + aValidatorID); + anErrorMsg.setContext(context() + ":" + aValidatorID); } } diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index cea25f232..73de512dd 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -245,12 +245,19 @@ Q_OBJECT /// \return Context for translation virtual std::string context() const { - + bool isAppendAttr = true; std::string aContext = myFeatureId; if(!aContext.empty() && !myAttributeID.empty()) { - aContext += ":"; + // workaround for ModelAPI_Filter's attributes: + // do not keep attribute name, because it may be changed + // if the same filter is selected twice or more. + if (myAttributeID.find(aContext + "__") != std::string::npos) + isAppendAttr = false; + else + aContext += ":"; } - aContext += myAttributeID; + if (isAppendAttr) + aContext += myAttributeID; return aContext; } diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp index 94f2f54c4..3e3d407d3 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp @@ -93,7 +93,8 @@ ModuleBase_FilterStarter::ModuleBase_FilterStarter(const std::string& theFeature ModuleBase_Tools::adjustMargins(aMainLayout); aMainLayout->addStretch(1); - QPushButton* aLaunchBtn = new QPushButton(tr("Selection by filters"), this); + QPushButton* aLaunchBtn = new QPushButton( + ModuleBase_Tools::translate("FiltersSelection", "Selection by filters"), this); connect(aLaunchBtn, SIGNAL(clicked()), SLOT(onFiltersLaunch())); aMainLayout->addWidget(aLaunchBtn); } @@ -184,6 +185,7 @@ ModuleBase_FilterItem::ModuleBase_FilterItem( void ModuleBase_FilterItem::addItemRow(QWidget* theParent) { + std::string aContext = mySelection->getKind(); QHBoxLayout* aLayout = new QHBoxLayout(theParent); ModuleBase_Tools::zeroMargins(aLayout); @@ -197,17 +199,17 @@ void ModuleBase_FilterItem::addItemRow(QWidget* theParent) myRevBtn->setIcon(QIcon(":pictures/reverce.png")); else myRevBtn->setIcon(QIcon(":pictures/add.png")); - myRevBtn->setToolTip(tr("Reverse the filter")); + myRevBtn->setToolTip(ModuleBase_Tools::translate(aContext, "Reverse the filter")); connect(myRevBtn, SIGNAL(toggled(bool)), SLOT(onReverse(bool))); aLayout->addWidget(myRevBtn); const std::string& aFilterName = ModelAPI_Session::get()->filters()->filter(myFilterID)->name(); - aLayout->addWidget(new QLabel(aFilterName.c_str(), theParent), 1); + aLayout->addWidget(new QLabel(ModuleBase_Tools::translate(aContext, aFilterName), theParent), 1); QToolButton* aDelBtn = new QToolButton(theParent); aDelBtn->setIcon(QIcon(":pictures/delete.png")); aDelBtn->setAutoRaise(true); - aDelBtn->setToolTip(tr("Delete the filter")); + aDelBtn->setToolTip(ModuleBase_Tools::translate(aContext, "Delete the filter")); connect(aDelBtn, SIGNAL(clicked(bool)), SLOT(onDelete())); aLayout->addWidget(aDelBtn); } @@ -249,7 +251,7 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP QVBoxLayout* aMainLayout = new QVBoxLayout(this); ModuleBase_Tools::adjustMargins(aMainLayout); - QGroupBox* aFiltersGroup = new QGroupBox(tr("Filters"), this); + QGroupBox* aFiltersGroup = new QGroupBox(translate("Filters"), this); QVBoxLayout* aGroupLayout = new QVBoxLayout(aFiltersGroup); aGroupLayout->setContentsMargins(0, 0, 0, 0); aGroupLayout->setSpacing(0); @@ -260,14 +262,15 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP aGroupLayout->addWidget(myFiltersWgt); myFiltersCombo = new QComboBox(aFiltersGroup); - myFiltersCombo->addItem(tr("Add new filter...")); + myFiltersCombo->addItem(translate("Add new filter...")); SessionPtr aSession = ModelAPI_Session::get(); std::list allFilters = aSession->filters()->filters((GeomAPI_Shape::ShapeType) mySelectionType); + storeFilters(allFilters); QStringList aItems; std::list::const_iterator aIt; for (aIt = allFilters.cbegin(); aIt != allFilters.cend(); aIt++) { - aItems.push_back((*aIt)->name().c_str()); + aItems.push_back(translate((*aIt)->name().c_str())); } myFiltersCombo->addItems(aItems); connect(myFiltersCombo, SIGNAL(currentIndexChanged(int)), SLOT(onAddFilter(int))); @@ -282,7 +285,7 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP aBtnLayout->addStretch(1); - mySelectBtn = new QPushButton(tr("Select"), aBtnWgt); + mySelectBtn = new QPushButton(translate("Select"), aBtnWgt); connect(mySelectBtn, SIGNAL(clicked()), SLOT(onSelect())); aBtnLayout->addWidget(mySelectBtn); @@ -293,13 +296,13 @@ ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theP QHBoxLayout* aLblLayout = new QHBoxLayout(aLblWgt); ModuleBase_Tools::zeroMargins(aLblLayout); - aLblLayout->addWidget(new QLabel(tr("Number of selected objects:"), aLblWgt)); + aLblLayout->addWidget(new QLabel(translate("Number of selected objects:"), aLblWgt)); myNbLbl = new QLabel("0", aLblWgt); aLblLayout->addWidget(myNbLbl); // Show only button - myShowBtn = new QCheckBox(tr("Show only"), this); + myShowBtn = new QCheckBox(translate("Show only"), this); connect(myShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool))); aLblLayout->addWidget(myShowBtn); @@ -351,7 +354,6 @@ void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex) return; ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters(); - std::list aFilters = aFactory->filters((GeomAPI_Shape::ShapeType) mySelectionType); FiltersFeaturePtr aFiltersFeature = std::dynamic_pointer_cast(myFeature); @@ -360,12 +362,15 @@ void ModuleBase_WidgetSelectionFilter::onAddFilter(int theIndex) std::list::iterator aIt; int i; std::string aFilter; - for (aIt = aFilters.begin(), i = 0; aIt != aFilters.cend(); i++, aIt++) { - if (aText == (*aIt)->name()) { - aFilter = aFactory->id(*aIt); - break; - } + std::map::const_iterator aFound = myFilters.find(aText); + if (aFound == myFilters.end()) { + std::list aFilters = aFactory->filters((GeomAPI_Shape::ShapeType) mySelectionType); + storeFilters(aFilters); + aFound = myFilters.find(aText); } + if (aFound != myFilters.end()) + aFilter = aFactory->id(aFound->second); + aFiltersFeature->addFilter(aFilter); updateObject(myFeature); @@ -555,9 +560,8 @@ void ModuleBase_WidgetSelectionFilter::updateNumberSelected() { int aNb = myValues.size(); myNbLbl->setText(QString::number(aNb)); - //QString aErr = () ? tr("Selection is empty") : ""; if (aNb == 0) - myFeature->setError(tr("Selection is empty").toStdString(), false, false); + myFeature->setError(translate("Selection is empty").toStdString(), false, false); else { myFeature->setError("", false, false); myFeature->data()->execState(ModelAPI_StateDone); @@ -701,7 +705,7 @@ QString ModuleBase_WidgetSelectionFilter::getError(const bool theValueStateCheck QString aErrorMsg = ModuleBase_ModelWidget::getError(theValueStateChecked); if (aErrorMsg.isEmpty()) { if (myValues.size() == 0) - aErrorMsg = tr("Selection is empty"); + aErrorMsg = translate("Selection is empty"); } return aErrorMsg; } @@ -728,3 +732,17 @@ void ModuleBase_WidgetSelectionFilter::onObjectUpdated() ModelAPI_EventCreator::get()->sendUpdated(myFeature, EVENT_DISP); Events_Loop::loop()->flush(EVENT_DISP); } + +void ModuleBase_WidgetSelectionFilter::storeFilters(const std::list& theFilters) +{ + for (std::list::const_iterator anIt = theFilters.begin(); + anIt != theFilters.end(); ++anIt) { + std::string aName = translate((*anIt)->name()).toStdString(); + myFilters[aName] = *anIt; + } +} + +QString ModuleBase_WidgetSelectionFilter::translate(const std::string& theString) const +{ + return ModuleBase_Tools::translate(myFeatureId, theString); +} diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h index 7ecc0e4ed..1fd4de6b5 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.h @@ -41,6 +41,8 @@ class QVBoxLayout; class QPushButton; class QCheckBox; +class ModelAPI_Filter; + class ModuleBase_IWorkshop; /** @@ -220,6 +222,12 @@ private: /// Return currently created filter items QList itemsList() const; + /// Translate a string + QString translate(const std::string& theString) const; + + /// Store translated names of filters and their instances + void storeFilters(const std::list >& theFilters); + private: ModuleBase_IWorkshop* myWorkshop; @@ -248,6 +256,9 @@ private: /// Attribute name which will get result of filtering std::string mySelectorAttribute; + + /// Translated name and the corresponding filter + std::map > myFilters; }; -- 2.30.2