Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_WhatIsDlg.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // SMESH SMESHGUI : GUI for SMESH component
23 // File   : SMESHGUI_WhatIsDlg.cxx
24 // Author : Vladimir TURIN, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_WhatIsDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_Utils.h"
31 #include "SMESHGUI_VTKUtils.h"
32 #include "SMESHGUI_MeshUtils.h"
33 #include "SMESHGUI_IdValidator.h"
34
35 #include "SMESH_Actor.h"
36 #include "SMESH_TypeFilter.hxx"
37 #include "SMESH_LogicalFilter.hxx"
38 #include "SMDS_Mesh.hxx"
39 #include "SMDS_VolumeTool.hxx"
40
41 // SALOME GUI includes
42 #include <SUIT_Desktop.h>
43 #include <SUIT_ResourceMgr.h>
44 #include <SUIT_Session.h>
45 #include <SUIT_MessageBox.h>
46
47 #include <LightApp_Application.h>
48 #include <LightApp_SelectionMgr.h>
49
50 #include <SVTK_ViewModel.h>
51 #include <SVTK_Selection.h>
52 #include <SVTK_ViewWindow.h>
53 #include <SALOME_ListIO.hxx>
54
55 // OCCT includes
56 #include <TColStd_MapOfInteger.hxx>
57 #include <gp_XYZ.hxx>
58
59 // Qt includes
60 #include <QButtonGroup>
61 #include <QGroupBox>
62 #include <QLabel>
63 #include <QLineEdit>
64 #include <QPushButton>
65 #include <QRadioButton>
66 #include <QTextBrowser>
67 #include <QHBoxLayout>
68 #include <QVBoxLayout>
69 #include <QGridLayout>
70 #include <QKeyEvent>
71
72 // IDL includes
73 #include <SALOMEconfig.h>
74 #include CORBA_SERVER_HEADER(SMESH_Group)
75
76 #define SPACING 6
77 #define MARGIN  11
78
79 //=================================================================================
80 // class    : SMESHGUI_WhatIsDlg()
81 // purpose  :
82 //=================================================================================
83 SMESHGUI_WhatIsDlg::SMESHGUI_WhatIsDlg( SMESHGUI* theModule )
84   : QDialog( SMESH::GetDesktop( theModule ) ),
85     mySMESHGUI( theModule ),
86     mySelectionMgr( SMESH::GetSelectionMgr( theModule ) )
87 {
88   setModal( false );
89   setAttribute( Qt::WA_DeleteOnClose, true );
90   setWindowTitle(tr("SMESH_WHAT_IS_TITLE"));
91   setSizeGripEnabled(true);
92   QVBoxLayout* SMESHGUI_WhatIsDlgLayout = new QVBoxLayout(this);
93   SMESHGUI_WhatIsDlgLayout->setSpacing(SPACING);
94   SMESHGUI_WhatIsDlgLayout->setMargin(MARGIN);
95   
96   /***************************************************************/
97   GroupMesh = new QGroupBox(this);
98   QHBoxLayout* GroupMeshLayout = new QHBoxLayout(GroupMesh);
99   GroupMeshLayout->setSpacing(SPACING);
100   GroupMeshLayout->setMargin(MARGIN);
101
102   MeshLabel = new QLabel(tr("SMESH_NAME"), GroupMesh);
103   GroupMeshLayout->addWidget(MeshLabel);
104   MeshName = new QLineEdit(GroupMesh);
105   MeshName->setReadOnly(true);
106   GroupMeshLayout->addWidget(MeshName);
107
108   /***************************************************************/
109   GroupSelections = new QGroupBox(tr("ENTITY_TYPE"), this);
110   QButtonGroup* GroupSel = new QButtonGroup(this);
111   QHBoxLayout* GroupSelectionsLayout = new QHBoxLayout(GroupSelections);
112   GroupSelectionsLayout->setSpacing(SPACING);
113   GroupSelectionsLayout->setMargin(MARGIN);
114
115   RadioButtonNodes = new QRadioButton(tr("SMESH_NODES"), GroupSelections);
116   GroupSelectionsLayout->addWidget(RadioButtonNodes);
117   GroupSel->addButton(RadioButtonNodes, 0);
118   RadioButtonElements = new QRadioButton(tr("SMESH_ELEMENTS"), GroupSelections);
119   GroupSelectionsLayout->addWidget(RadioButtonElements);
120   GroupSel->addButton(RadioButtonElements, 1);
121
122   /***************************************************************/
123   GroupArguments = new QGroupBox(tr("SMESH_INFORMATION"), this);
124   QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments);
125   GroupArgumentsLayout->setSpacing(SPACING);
126   GroupArgumentsLayout->setMargin(MARGIN);
127
128   // Controls for elements selection
129   TextLabelElements  = new QLabel(tr("SMESH_ID_ELEMENTS"), GroupArguments);
130   GroupArgumentsLayout->addWidget(TextLabelElements, 0, 0);
131
132   LineEditElements  = new QLineEdit(GroupArguments);
133   LineEditElements->setValidator(new SMESHGUI_IdValidator(this));
134   GroupArgumentsLayout->addWidget(LineEditElements, 0, 1);
135
136   // information text browser
137   Info = new QTextBrowser(GroupArguments);
138   Info->setMinimumSize(200, 150);
139   GroupArgumentsLayout->addWidget(Info, 1, 0, 1, 2);
140
141   /***************************************************************/
142   GroupButtons = new QGroupBox(this);
143   QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
144   GroupButtonsLayout->setSpacing(SPACING);
145   GroupButtonsLayout->setMargin(MARGIN);
146
147   buttonOk = new QPushButton(tr("SMESH_BUT_OK"), GroupButtons);
148   buttonOk->setAutoDefault(true);
149   buttonOk->setDefault(true);
150   buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
151   buttonHelp->setAutoDefault(true);
152
153   GroupButtonsLayout->addWidget(buttonOk);
154   GroupButtonsLayout->addSpacing(10);
155   GroupButtonsLayout->addStretch();
156   GroupButtonsLayout->addWidget(buttonHelp);
157
158   SMESHGUI_WhatIsDlgLayout->addWidget(GroupMesh);
159   SMESHGUI_WhatIsDlgLayout->addWidget(GroupSelections);
160   SMESHGUI_WhatIsDlgLayout->addWidget(GroupArguments);
161   SMESHGUI_WhatIsDlgLayout->addWidget(GroupButtons);
162
163   RadioButtonNodes->setChecked(true);
164
165   mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
166
167   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
168
169   // Costruction of the logical filter
170   SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (MESHorSUBMESH);
171   SMESH_TypeFilter* aSmeshGroupFilter    = new SMESH_TypeFilter (GROUP);
172
173   QList<SUIT_SelectionFilter*> aListOfFilters;
174   if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
175   if (aSmeshGroupFilter)    aListOfFilters.append(aSmeshGroupFilter);
176
177   myMeshOrSubMeshOrGroupFilter =
178     new SMESH_LogicalFilter(aListOfFilters, SMESH_LogicalFilter::LO_OR);
179
180   myHelpFileName = "mesh_infos_page.html#mesh_element_info_anchor";
181
182   Init();
183
184   /* signals and slots connections */
185   connect(buttonOk,         SIGNAL(clicked()),     this, SLOT(ClickOnOk()));
186   connect(buttonHelp,       SIGNAL(clicked()),     this, SLOT(ClickOnHelp()));
187   connect(GroupSel,         SIGNAL(buttonClicked(int)), SLOT(SelectionsClicked(int)));
188
189   connect(mySMESHGUI,       SIGNAL(SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
190   connect(mySelectionMgr,   SIGNAL(currentSelectionChanged()),      this, SLOT(SelectionIntoArgument()));
191   /* to close dialog if study change */
192   connect(mySMESHGUI,       SIGNAL(SignalCloseAllDialogs()),  this, SLOT(ClickOnCancel()));
193   connect(LineEditElements, SIGNAL(textChanged(const QString&)),    SLOT(onTextChange(const QString&)));
194
195   SelectionsClicked(0);
196   SelectionIntoArgument();
197 }
198
199 //=================================================================================
200 // function : ~SMESHGUI_WhatIsDlg()
201 // purpose  : Destroys the object and frees any allocated resources
202 //=================================================================================
203 SMESHGUI_WhatIsDlg::~SMESHGUI_WhatIsDlg()
204 {
205 }
206
207 //=================================================================================
208 // function : Init()
209 // purpose  :
210 //=================================================================================
211 void SMESHGUI_WhatIsDlg::Init (bool ResetControls)
212 {
213   myBusy = false;
214
215   LineEditElements->clear();
216
217   myActor = 0;
218   myMesh = SMESH::SMESH_Mesh::_nil();
219
220   if (ResetControls) {
221     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
222       aViewWindow->SetSelectionMode( CellSelection );
223     onTextChange(LineEditElements->text());
224     
225     SelectionIntoArgument();
226   }
227 }
228
229 //=================================================================================
230 // function : SelectionsClicked()
231 // purpose  : Radio button management
232 //=================================================================================
233 void SMESHGUI_WhatIsDlg::SelectionsClicked (int selectionId)
234 {
235   disconnect(mySelectionMgr, 0, this, 0);
236
237   mySelectionMgr->clearFilters();
238
239   switch (selectionId) {
240   case 0:
241     {
242       SMESH::SetPointRepresentation(true);
243       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
244         aViewWindow->SetSelectionMode( NodeSelection );
245       break;
246     }    
247   case 1:
248     {
249       SMESH::SetPointRepresentation(false);
250       if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
251         aViewWindow->SetSelectionMode( CellSelection );
252       break;
253     }
254   }
255
256   connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
257   SelectionIntoArgument();
258 }
259
260 //=================================================================================
261 // function : ClickOnOk()
262 // purpose  :
263 //=================================================================================
264 void SMESHGUI_WhatIsDlg::ClickOnOk()
265 {
266   if (mySMESHGUI->isActiveStudyLocked())
267     return;
268
269   SMESH::UpdateView();
270   Init(false);
271   SelectionIntoArgument();
272   ClickOnCancel();
273 }
274
275 //=================================================================================
276 // function : ClickOnCancel()
277 // purpose  :
278 //=================================================================================
279 void SMESHGUI_WhatIsDlg::ClickOnCancel()
280 {
281   disconnect(mySelectionMgr, 0, this, 0);
282   mySelectionMgr->clearFilters();
283   SMESH::SetPointRepresentation(false);
284   if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
285     aViewWindow->SetSelectionMode( ActorSelection );
286   mySMESHGUI->ResetState();
287   reject();
288 }
289
290 //=================================================================================
291 // function : ClickOnHelp()
292 // purpose  :
293 //=================================================================================
294 void SMESHGUI_WhatIsDlg::ClickOnHelp()
295 {
296   LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
297   if (app) 
298     app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
299   else {
300     SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
301                              tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
302                              arg(app->resourceMgr()->stringValue("ExternalBrowser",
303                                                                  "application")).
304                              arg(myHelpFileName));
305   }
306 }
307
308 //=======================================================================
309 // function : onTextChange()
310 // purpose  :
311 //=======================================================================
312 void SMESHGUI_WhatIsDlg::onTextChange (const QString& theNewText)
313 {
314   if (myBusy) return;
315   myBusy = true;
316
317   // hilight entered elements
318   SMDS_Mesh* aMesh = 0;
319   if (myActor)
320     aMesh = myActor->GetObject()->GetMesh();
321
322   if (aMesh) {
323     Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
324     
325     TColStd_MapOfInteger newIndices;
326
327     QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
328
329     for (int i = 0; i < aListId.count(); i++) {
330       const SMDS_MeshElement * e = RadioButtonNodes->isChecked()?
331         aMesh->FindNode(aListId[ i ].toInt()):
332         aMesh->FindElement(aListId[ i ].toInt());
333       if (e)
334         newIndices.Add(e->GetID());
335     }
336
337     mySelector->AddOrRemoveIndex( anIO, newIndices, false );
338     if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
339       aViewWindow->highlight( anIO, true, true );
340   }
341
342   SelectionIntoArgument();
343
344   myBusy = false;
345 }
346
347 //=================================================================================
348 // function : SelectionIntoArgument()
349 // purpose  : Called when selection as changed or other case
350 //=================================================================================
351 void SMESHGUI_WhatIsDlg::SelectionIntoArgument()
352 {
353   int curBusy = myBusy;
354
355   // clear
356   myActor = 0;
357   QString aString = "";
358
359   myBusy = true;
360   if(!curBusy)
361     LineEditElements->setText(aString);
362   MeshName->setText(aString);
363   GroupMesh->setTitle(tr(""));
364   Info->clear();
365   myBusy = curBusy;
366
367   if (!GroupButtons->isEnabled()) // inactive
368     return;
369
370   // get selected mesh
371   SALOME_ListIO aList;
372   mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type());
373
374   int nbSel = aList.Extent();
375
376   if (nbSel != 1)
377     return;
378
379   Handle(SALOME_InteractiveObject) IO = aList.First();
380   myMesh = SMESH::GetMeshByIO(IO);
381   if (myMesh->_is_nil())
382     return;
383
384   myActor = SMESH::FindActorByObject(myMesh);
385   if (!myActor)
386     myActor = SMESH::FindActorByEntry(IO->getEntry());
387   if (!myActor)
388     return;
389
390   QString aName;
391   SMESH::GetNameOfSelectedIObjects(mySelectionMgr, aName);
392   MeshName->setText(aName);
393   if(!SMESH::IObjectToInterface<SMESH::SMESH_Mesh>(IO)->_is_nil()) {
394     GroupMesh->setTitle(tr("SMESH_MESH"));
395   } else if(!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil()) {
396     GroupMesh->setTitle(tr("SMESH_SUBMESH"));
397   } else if(!SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO)->_is_nil()) {
398     GroupMesh->setTitle(tr("SMESH_GROUP"));
399   }
400
401   int aNbUnits = 0;
402   
403   aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
404   
405   if (aNbUnits < 1)
406     return;
407
408   const SMDS_MeshElement * e = RadioButtonNodes->isChecked()?
409     myActor->GetObject()->GetMesh()->FindNode(aString.toInt()):
410     myActor->GetObject()->GetMesh()->FindElement(aString.toInt());
411   if (e) {
412     QString anInfo;
413     anInfo=tr("ENTITY_TYPE") + ": ";
414     if(e->GetType() == SMDSAbs_Node) {
415       anInfo+=tr("MESH_NODE")+"\n";
416       //const SMDS_MeshNode *en = (SMDS_MeshNode*) e; // VSR: not used!
417     } else if(e->GetType() == SMDSAbs_Edge) {
418       anInfo+=tr("SMESH_EDGE")+"\n";
419       anInfo+=tr("SMESH_MESHINFO_TYPE")+": ";
420       const SMDS_MeshEdge *ee = (SMDS_MeshEdge*) e;
421       anInfo+=(ee->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+"\n";
422     } else if(e->GetType() == SMDSAbs_Face) {
423       const SMDS_MeshFace *ef = (SMDS_MeshFace*) e;
424       anInfo+=tr("SMESH_FACE")+"\n";
425       anInfo+=tr("SMESH_MESHINFO_TYPE")+": ";
426       if(!ef->IsPoly())
427         anInfo+=(ef->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+" ";
428       switch(ef->NbNodes()) {
429       case 3:
430       case 6:
431         {
432           anInfo+=tr("SMESH_TRIANGLE");
433           break;
434         }
435       case 4:
436       case 8:
437         {
438           anInfo+=tr("SMESH_QUADRANGLE");
439           break;
440         }
441       default:
442         break;
443       }
444       anInfo+="\n";
445     } else if(e->GetType() == SMDSAbs_Volume) {
446       anInfo+=tr("SMESH_VOLUME")+"\n";
447       anInfo+=tr("SMESH_MESHINFO_TYPE")+": ";
448       const SMDS_MeshVolume *ev = (SMDS_MeshVolume*) e;
449       SMDS_VolumeTool vt(ev);
450       if(vt.GetVolumeType() != SMDS_VolumeTool::POLYHEDA)
451         anInfo+=(ev->IsQuadratic()?tr("SMESH_MESHINFO_ORDER2"):tr("SMESH_MESHINFO_ORDER1"))+" ";
452       switch(vt.GetVolumeType()) {
453       case SMDS_VolumeTool::TETRA:
454       case SMDS_VolumeTool::QUAD_TETRA:
455         {
456           anInfo+=tr("SMESH_TETRAS");
457           break;
458         }
459       case SMDS_VolumeTool::PYRAM:
460       case SMDS_VolumeTool::QUAD_PYRAM:
461         {
462           anInfo+=tr("SMESH_PYRAMID");
463           break;
464         }
465       case SMDS_VolumeTool::PENTA:
466       case SMDS_VolumeTool::QUAD_PENTA:
467         {
468           anInfo+=tr("SMESH_PRISM");
469           break;
470         }
471       case SMDS_VolumeTool::HEXA:
472       case SMDS_VolumeTool::QUAD_HEXA:
473         {
474           anInfo+=tr("SMESH_HEXAS");
475           break;
476         }
477       case SMDS_VolumeTool::POLYHEDA:
478         {
479           anInfo+=tr("SMESH_POLYEDRON");
480           break;
481         }
482       default:
483         break;
484       }
485       anInfo+="\n";
486     }
487     if(e->GetType() != SMDSAbs_Node)
488       anInfo+=tr("GRAVITY_CENTER") + ":\n";
489     gp_XYZ anXYZ(0.,0.,0.);
490     SMDS_ElemIteratorPtr nodeIt = e->nodesIterator();
491     int nbNodes = 0;
492     for( ; nodeIt->more(); nbNodes++) {
493       const SMDS_MeshNode* node = static_cast<const SMDS_MeshNode*>( nodeIt->next() );
494       anXYZ.Add( gp_XYZ( node->X(), node->Y(), node->Z() ) );
495     }
496     anXYZ.Divide(e->NbNodes());
497     anInfo+=QString("X=%1\nY=%2\nZ=%3\n").arg(anXYZ.X()).arg(anXYZ.Y()).arg(anXYZ.Z());
498     Info->setText(anInfo);
499   }
500
501   if(!curBusy) {
502     myBusy = true;
503     LineEditElements->setText(aString);
504     myBusy = false;
505   }
506 }
507
508 //=================================================================================
509 // function : DeactivateActiveDialog()
510 // purpose  :
511 //=================================================================================
512 void SMESHGUI_WhatIsDlg::DeactivateActiveDialog()
513 {
514   if (GroupArguments->isEnabled()) {
515     GroupSelections->setEnabled(false);
516     GroupMesh->setEnabled(false);
517     GroupArguments->setEnabled(false);
518     GroupButtons->setEnabled(false);
519     mySMESHGUI->ResetState();
520     mySMESHGUI->SetActiveDialogBox(0);
521   }
522 }
523
524 //=================================================================================
525 // function : ActivateThisDialog()
526 // purpose  :
527 //=================================================================================
528 void SMESHGUI_WhatIsDlg::ActivateThisDialog()
529 {
530   /* Emit a signal to deactivate the active dialog */
531   mySMESHGUI->EmitSignalDeactivateDialog();
532   GroupArguments->setEnabled(true);
533   GroupButtons->setEnabled(true);
534   GroupSelections->setEnabled(true);
535   GroupMesh->setEnabled(true);
536
537   mySMESHGUI->SetActiveDialogBox((QDialog*)this);
538
539   if ( SMESH::GetViewWindow( mySMESHGUI ))
540     SelectionsClicked(RadioButtonNodes->isChecked()?0:1);
541
542   SelectionIntoArgument();
543 }
544
545 //=================================================================================
546 // function : enterEvent()
547 // purpose  :
548 //=================================================================================
549 void SMESHGUI_WhatIsDlg::enterEvent (QEvent*)
550 {
551   if (!GroupArguments->isEnabled())
552     ActivateThisDialog();
553 }
554
555 //=================================================================================
556 // function : closeEvent()
557 // purpose  :
558 //=================================================================================
559 void SMESHGUI_WhatIsDlg::closeEvent (QCloseEvent*)
560 {
561   /* same than click on cancel button */
562   ClickOnCancel();
563 }
564
565 //=======================================================================
566 //function : hideEvent
567 //purpose  : caused by ESC key
568 //=======================================================================
569 void SMESHGUI_WhatIsDlg::hideEvent (QHideEvent*)
570 {
571   if (!isMinimized())
572     ClickOnCancel();
573 }
574
575 //=================================================================================
576 // function : keyPressEvent()
577 // purpose  :
578 //=================================================================================
579 void SMESHGUI_WhatIsDlg::keyPressEvent( QKeyEvent* e )
580 {
581   QDialog::keyPressEvent( e );
582   if ( e->isAccepted() )
583     return;
584
585   if ( e->key() == Qt::Key_F1 ) {
586     e->accept();
587     ClickOnHelp();
588   }
589 }