Back to index

salome-smesh  6.5.0
SMESHGUI_SingleEditDlg.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File   : SMESHGUI_SingleEditDlg.cxx
00024 // Author : Sergey LITONIN, Open CASCADE S.A.S.
00025 // SMESH includes
00026 //
00027 #include "SMESHGUI_SingleEditDlg.h"
00028 
00029 #include "SMESHGUI.h"
00030 #include "SMESHGUI_Utils.h"
00031 #include "SMESHGUI_VTKUtils.h"
00032 #include "SMESHGUI_MeshUtils.h"
00033 
00034 #include <SMESH_Actor.h>
00035 #include <SMDS_Mesh.hxx>
00036 
00037 // SALOME GUI includes
00038 #include <LightApp_SelectionMgr.h>
00039 #include <LightApp_Application.h>
00040 #include <SUIT_ResourceMgr.h>
00041 #include <SUIT_MessageBox.h>
00042 #include <SUIT_Desktop.h>
00043 #include <SUIT_Session.h>
00044 
00045 #include <SVTK_Selector.h>
00046 #include <SVTK_ViewWindow.h>
00047 #include <SALOME_ListIO.hxx>
00048 
00049 // OCCT includes
00050 #include <TColStd_MapOfInteger.hxx>
00051 #include <TColStd_IndexedMapOfInteger.hxx>
00052 
00053 // Qt includes
00054 #include <QVBoxLayout>
00055 #include <QHBoxLayout>
00056 #include <QLineEdit>
00057 #include <QPushButton>
00058 #include <QGroupBox>
00059 #include <QLabel>
00060 #include <QValidator>
00061 #include <QKeyEvent>
00062 
00063 #define SPACING 6
00064 #define MARGIN  11
00065 
00072 class BusyLocker
00073 {
00074 public:
00076   BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; }
00078   ~BusyLocker() { myBusy = false; }
00079 private:
00080   bool& myBusy; 
00081 };
00082 
00089 //=======================================================================
00090 // name    : SMESHGUI_SingleEditDlg()
00091 // Purpose : Constructor
00092 //=======================================================================
00093 SMESHGUI_SingleEditDlg
00094 ::SMESHGUI_SingleEditDlg(SMESHGUI* theModule)
00095   : QDialog(SMESH::GetDesktop(theModule)),
00096     mySelector(SMESH::GetViewWindow(theModule)->GetSelector()),
00097     mySelectionMgr(SMESH::GetSelectionMgr(theModule)),
00098     mySMESHGUI(theModule)
00099 {
00100   setModal(false);
00101 
00102   QVBoxLayout* aDlgLay = new QVBoxLayout(this);
00103   aDlgLay->setMargin(MARGIN);
00104   aDlgLay->setSpacing(SPACING);
00105 
00106   QWidget* aMainFrame = createMainFrame  (this);
00107   QWidget* aBtnFrame  = createButtonFrame(this);
00108 
00109   aDlgLay->addWidget(aMainFrame);
00110   aDlgLay->addWidget(aBtnFrame);
00111 
00112   Init();
00113 }
00114 
00115 //=======================================================================
00116 // name    : createMainFrame()
00117 // Purpose : Create frame containing dialog's input fields
00118 //=======================================================================
00119 QWidget* SMESHGUI_SingleEditDlg::createMainFrame (QWidget* theParent)
00120 {
00121   QGroupBox* aMainGrp = new QGroupBox(tr("EDGE_BETWEEN"), theParent);
00122   QHBoxLayout* aLay = new QHBoxLayout(aMainGrp);
00123   aLay->setMargin(MARGIN);
00124   aLay->setSpacing(SPACING);
00125 
00126   QPixmap aPix (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
00127 
00128   QLabel* aLab = new QLabel(tr("SMESH_EDGE"), aMainGrp);
00129   QPushButton* aBtn = new QPushButton(aMainGrp);
00130   aBtn->setIcon(aPix);
00131   myEdge = new QLineEdit(aMainGrp);
00132   myEdge->setValidator(new QRegExpValidator(QRegExp("[\\d]*-[\\d]*"), this));
00133 
00134   aLay->addWidget(aLab);
00135   aLay->addWidget(aBtn);
00136   aLay->addWidget(myEdge);
00137 
00138   return aMainGrp;
00139 }
00140 
00141 //=======================================================================
00142 // name    : createButtonFrame()
00143 // Purpose : Create frame containing buttons
00144 //=======================================================================
00145 QWidget* SMESHGUI_SingleEditDlg::createButtonFrame (QWidget* theParent)
00146 {
00147   QGroupBox* aFrame = new QGroupBox(theParent);
00148 
00149   myOkBtn     = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), aFrame);
00150   myApplyBtn  = new QPushButton(tr("SMESH_BUT_APPLY"), aFrame);
00151   myCloseBtn  = new QPushButton(tr("SMESH_BUT_CLOSE"), aFrame);
00152   myHelpBtn   = new QPushButton(tr("SMESH_BUT_HELP"),  aFrame);
00153 
00154   QHBoxLayout* aLay = new QHBoxLayout(aFrame);
00155   aLay->setMargin(MARGIN);
00156   aLay->setSpacing(SPACING);
00157 
00158   aLay->addWidget(myOkBtn);
00159   aLay->addSpacing(10);
00160   aLay->addWidget(myApplyBtn);
00161   aLay->addSpacing(10);
00162   aLay->addStretch();
00163   aLay->addWidget(myCloseBtn);
00164   aLay->addWidget(myHelpBtn);
00165 
00166   return aFrame;
00167 }
00168 
00169 //=======================================================================
00170 // name    : isValid()
00171 // Purpose : Verify validity of input data
00172 //=======================================================================
00173 bool SMESHGUI_SingleEditDlg::isValid (const bool theMess) const
00174 {
00175   int id1, id2;
00176   return getNodeIds(myEdge->text(), id1, id2);
00177 }
00178 
00179 //=======================================================================
00180 // name    : getNodeIds()
00181 // Purpose : Retrieve node ids from string
00182 //=======================================================================
00183 bool SMESHGUI_SingleEditDlg::getNodeIds (const QString& theStr,
00184                                          int& theId1, int&  theId2) const
00185 {
00186   if (!theStr.contains('-'))
00187     return false;
00188 
00189   bool ok1, ok2;
00190   QString str1 = theStr.section('-', 0, 0, QString::SectionSkipEmpty);
00191   QString str2 = theStr.section('-', 1, 1, QString::SectionSkipEmpty);
00192   theId1 = str1.toInt(&ok1);
00193   theId2 = str2.toInt(&ok2);
00194 
00195   return ok1 & ok2;
00196 }
00197 
00198 //=======================================================================
00199 // name    : ~SMESHGUI_SingleEditDlg()
00200 // Purpose : Destructor
00201 //=======================================================================
00202 SMESHGUI_SingleEditDlg::~SMESHGUI_SingleEditDlg()
00203 {
00204 }
00205 
00206 //=======================================================================
00207 // name    : Init()
00208 // Purpose : Init dialog fields, connect signals and slots, show dialog
00209 //=======================================================================
00210 void SMESHGUI_SingleEditDlg::Init()
00211 {
00212   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
00213   myBusy = false;
00214   myActor = 0;
00215 
00216   // main buttons
00217   connect(myOkBtn,    SIGNAL(clicked()), SLOT(onOk()));
00218   connect(myCloseBtn, SIGNAL(clicked()), SLOT(onClose()));
00219   connect(myApplyBtn, SIGNAL(clicked()), SLOT(onApply()));
00220   connect(myHelpBtn,  SIGNAL(clicked()), SLOT(onHelp()));
00221 
00222   // selection and SMESHGUI
00223   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), SLOT(onSelectionDone()));
00224   connect(mySMESHGUI, SIGNAL(SignalDeactivateActiveDialog()), SLOT(onDeactivate()));
00225   connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), SLOT(onClose()));
00226   connect(myEdge, SIGNAL(textChanged(const QString&)), SLOT(onTextChange(const QString&)));
00227 
00228   myOkBtn->setEnabled(false);
00229   myApplyBtn->setEnabled(false);
00230   setEnabled(true);
00231 
00232   // set selection mode
00233   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
00234     aViewWindow->SetSelectionMode(EdgeOfCellSelection);
00235 
00236   onSelectionDone();
00237 }
00238 
00239 //=======================================================================
00240 // name    : onOk()
00241 // Purpose : SLOT called when "Ok" button pressed.
00242 //           Assign filters VTK viewer and close dialog
00243 //=======================================================================
00244 void SMESHGUI_SingleEditDlg::onOk()
00245 {
00246   if (onApply())
00247     onClose();
00248 }
00249 
00250 //=======================================================================
00251 // name    : onClose()
00252 // Purpose : SLOT called when "Close" button pressed. Close dialog
00253 //=======================================================================
00254 void SMESHGUI_SingleEditDlg::onClose()
00255 {
00256   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
00257     aViewWindow->SetSelectionMode(ActorSelection);
00258   //mySelectionMgr->clearSelected();
00259   disconnect(mySelectionMgr, 0, this, 0);
00260   disconnect(mySMESHGUI, 0, this, 0);
00261   mySMESHGUI->ResetState();
00262   reject();
00263 }
00264 
00265 //=================================================================================
00266 // function : onHelp()
00267 // purpose  :
00268 //=================================================================================
00269 void SMESHGUI_SingleEditDlg::onHelp()
00270 {
00271   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
00272   if (app) 
00273     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
00274   else {
00275     QString platform;
00276 #ifdef WIN32
00277     platform = "winapplication";
00278 #else
00279     platform = "application";
00280 #endif
00281     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
00282                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
00283                              arg(app->resourceMgr()->stringValue("ExternalBrowser", 
00284                                                                  platform)).
00285                              arg(myHelpFileName));
00286   }
00287 }
00288 
00289 //=======================================================================
00290 //function : findTriangles()
00291 //purpose  : find triangles sharing theNode1-theNode2 link
00292 //           THIS IS A PIECE OF SMESH_MeshEditor.cxx
00293 //           TO DO: make it available in SMDS for ex.
00294 //=======================================================================
00295 static bool findTriangles (const SMDS_MeshNode *    theNode1,
00296                            const SMDS_MeshNode *    theNode2,
00297                            const SMDS_MeshElement*& theTria1,
00298                            const SMDS_MeshElement*& theTria2)
00299 {
00300   if (!theNode1 || !theNode2) return false;
00301 
00302   theTria1 = theTria2 = 0;
00303 
00304   std::set< const SMDS_MeshElement* > emap;
00305   SMDS_ElemIteratorPtr it = theNode1->GetInverseElementIterator();
00306   while (it->more()) {
00307     const SMDS_MeshElement* elem = it->next();
00308     if (elem->GetType() == SMDSAbs_Face && elem->NbNodes() == 3)
00309       emap.insert(elem);
00310   }
00311   it = theNode2->GetInverseElementIterator();
00312   while (it->more()) {
00313     const SMDS_MeshElement* elem = it->next();
00314     if (elem->GetType() == SMDSAbs_Face &&
00315          emap.find(elem) != emap.end())
00316     {
00317       if (theTria1) {
00318         theTria2 = elem;
00319         break;
00320       } else {
00321         theTria1 = elem;
00322       }
00323     }
00324   }
00325   return (theTria1 && theTria2);
00326 }
00327 
00328 //=======================================================================
00329 //function : onTextChange()
00330 //purpose  :
00331 //=======================================================================
00332 void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
00333 {
00334   if (myBusy) return;
00335   BusyLocker lock(myBusy);
00336 
00337   myOkBtn->setEnabled(false);
00338   myApplyBtn->setEnabled(false);
00339 
00340   // hilight entered edge
00341   if(myActor){
00342     if(SMDS_Mesh* aMesh = myActor->GetObject()->GetMesh()){
00343       Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
00344       SALOME_ListIO aList;
00345       aList.Append(anIO);
00346       mySelectionMgr->setSelectedObjects(aList,false);
00347       
00348       TColStd_IndexedMapOfInteger selectedIndices;
00349       TColStd_MapOfInteger newIndices;
00350       mySelector->GetIndex(anIO,selectedIndices);
00351 
00352       int id1, id2;
00353       if ( !getNodeIds(myEdge->text(), id1, id2) )
00354         return;
00355 
00356       const SMDS_MeshNode* aNode1 = aMesh->FindNode( id1 );
00357       const SMDS_MeshNode* aNode2 = aMesh->FindNode( id2 );
00358 
00359       if ( !aNode1 || !aNode2 || aNode1 == aNode2 )
00360         return;
00361 
00362       // find a triangle and an edge index
00363       const SMDS_MeshElement* tria1;
00364       const SMDS_MeshElement* tria2;
00365 
00366       if ( findTriangles(aNode1,aNode2,tria1,tria2) )
00367       {
00368         newIndices.Add(tria1->GetID());
00369 
00370         const SMDS_MeshNode* a3Nodes[3];
00371         SMDS_ElemIteratorPtr it;
00372         int edgeInd = 2, i;
00373         for (i = 0, it = tria1->nodesIterator(); it->more(); i++) {
00374           a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
00375           if (i > 0 && ( (a3Nodes[ i ] == aNode1 && a3Nodes[ i - 1] == aNode2) ||
00376                          (a3Nodes[ i ] == aNode2 && a3Nodes[ i - 1] == aNode1) ) ) {
00377             edgeInd = i - 1;
00378             break;
00379           }
00380         }
00381         newIndices.Add(-edgeInd-1);
00382         
00383         myOkBtn->setEnabled(true);
00384         myApplyBtn->setEnabled(true);
00385       }
00386       mySelector->AddOrRemoveIndex(anIO,newIndices, false);
00387       SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
00388     }
00389   }
00390 }
00391 
00392 //=======================================================================
00393 // name    : onSelectionDone()
00394 // Purpose : SLOT called when selection changed
00395 //=======================================================================
00396 void SMESHGUI_SingleEditDlg::onSelectionDone()
00397 {
00398   if (myBusy) return;
00399   BusyLocker lock(myBusy);
00400 
00401   int anId1 = 0, anId2 = 0;
00402 
00403   myOkBtn->setEnabled(false);
00404   myApplyBtn->setEnabled(false);
00405 
00406   SALOME_ListIO aList;
00407   mySelectionMgr->selectedObjects(aList);
00408 
00409   if (aList.Extent() != 1) {
00410     myEdge->clear();
00411     return;
00412   }
00413 
00414   Handle(SALOME_InteractiveObject) anIO = aList.First();
00415   myActor = SMESH::FindActorByEntry(anIO->getEntry());
00416   if(myActor){
00417     TVisualObjPtr aVisualObj = myActor->GetObject();
00418     if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
00419     {
00420       const SMDS_MeshElement* tria[2];
00421       if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
00422           findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
00423       {
00424         QString aText = QString("%1-%2").arg(anId1).arg(anId2);
00425         myEdge->setText(aText);
00426         
00427         myOkBtn->setEnabled(true);
00428         myApplyBtn->setEnabled(true);
00429       }
00430       else
00431       {
00432         myEdge->clear();
00433       }
00434     }
00435   }
00436 }
00437 
00438 //=======================================================================
00439 // name    : onDeactivate()
00440 // Purpose : SLOT called when dialog must be deativated
00441 //=======================================================================
00442 void SMESHGUI_SingleEditDlg::onDeactivate()
00443 {
00444   setEnabled(false);
00445 }
00446 
00447 //=======================================================================
00448 // name    : enterEvent()
00449 // Purpose : Event filter
00450 //=======================================================================
00451 void SMESHGUI_SingleEditDlg::enterEvent (QEvent*)
00452 {
00453   if (!isEnabled()) {
00454     mySMESHGUI->EmitSignalDeactivateDialog();
00455     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
00456       aViewWindow->SetSelectionMode(EdgeOfCellSelection);
00457     setEnabled(true);
00458   }
00459 }
00460 
00461 //=================================================================================
00462 // function : closeEvent()
00463 // purpose  :
00464 //=================================================================================
00465 void SMESHGUI_SingleEditDlg::closeEvent (QCloseEvent*)
00466 {
00467   onClose();
00468 }
00469 
00470 //=======================================================================
00471 //function : hideEvent()
00472 //purpose  : caused by ESC key
00473 //=======================================================================
00474 void SMESHGUI_SingleEditDlg::hideEvent (QHideEvent*)
00475 {
00476   if (!isMinimized())
00477     onClose();
00478 }
00479 
00480 //=================================================================================
00481 // function : onApply()
00482 // purpose  : SLOT. Called when apply button is pressed
00483 //=================================================================================
00484 bool SMESHGUI_SingleEditDlg::onApply()
00485 {
00486   if (mySMESHGUI->isActiveStudyLocked())
00487     return false;
00488   // verify validity of input data
00489   if (!isValid(true))
00490     return false;
00491 
00492   // get mesh, actor and nodes
00493   SALOME_ListIO aList;
00494   mySelectionMgr->selectedObjects(aList);
00495 
00496   SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(aList.First());
00497 
00498   if (aMesh->_is_nil()) {
00499     SUIT_MessageBox::information(SMESH::GetDesktop(mySMESHGUI), 
00500                                  tr("SMESH_ERROR"),
00501                                  tr("SMESHG_NO_MESH"));
00502     return false;
00503   }
00504 
00505   SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
00506   int anId1= 0, anId2 = 0;
00507   if (aMeshEditor->_is_nil() || !getNodeIds(myEdge->text(), anId1, anId2))
00508     return false;
00509 
00510   // perform operation
00511   bool aResult = process(aMeshEditor.in(), anId1, anId2);
00512 
00513   // update actor
00514   if (aResult) {
00515     mySelector->ClearIndex();
00516     mySelectionMgr->setSelectedObjects(aList, false);
00517     onSelectionDone();
00518     SMESH::UpdateView();
00519     SMESHGUI::Modified();
00520   }
00521 
00522   return aResult;
00523 }
00524 
00525 //=================================================================================
00526 // function : keyPressEvent()
00527 // purpose  :
00528 //=================================================================================
00529 void SMESHGUI_SingleEditDlg::keyPressEvent( QKeyEvent* e )
00530 {
00531   QDialog::keyPressEvent( e );
00532   if ( e->isAccepted() )
00533     return;
00534 
00535   if ( e->key() == Qt::Key_F1 ) {
00536     e->accept();
00537     onHelp();
00538   }
00539 }
00540 
00547 SMESHGUI_TrianglesInversionDlg
00548 ::SMESHGUI_TrianglesInversionDlg(SMESHGUI* theModule)
00549 : SMESHGUI_SingleEditDlg(theModule)
00550 {
00551   setWindowTitle(tr("CAPTION"));
00552   myHelpFileName = "diagonal_inversion_of_elements_page.html";
00553 }
00554 
00555 SMESHGUI_TrianglesInversionDlg::~SMESHGUI_TrianglesInversionDlg()
00556 {
00557 }
00558 
00559 bool SMESHGUI_TrianglesInversionDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
00560                                               const int theId1, const int theId2)
00561 {
00562   return theMeshEditor->InverseDiag(theId1, theId2);
00563 }
00564 
00571 SMESHGUI_UnionOfTwoTrianglesDlg
00572 ::SMESHGUI_UnionOfTwoTrianglesDlg(SMESHGUI* theModule)
00573 : SMESHGUI_SingleEditDlg(theModule)
00574 {
00575   setWindowTitle(tr("CAPTION"));
00576   myHelpFileName = "uniting_two_triangles_page.html";
00577 }
00578 
00579 SMESHGUI_UnionOfTwoTrianglesDlg::~SMESHGUI_UnionOfTwoTrianglesDlg()
00580 {
00581 }
00582 
00583 bool SMESHGUI_UnionOfTwoTrianglesDlg::process (SMESH::SMESH_MeshEditor_ptr theMeshEditor,
00584                                                const int theId1, const int theId2)
00585 {
00586   return theMeshEditor->DeleteDiag(theId1, theId2);
00587 }