1 // SALOME SALOMEGUI : implementation of desktop and GUI kernel
3 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
24 // File : SALOMEGUI_Application.cxx
25 // Author : Nicolas REJNERI
29 #include "SALOMEGUI_Application.h"
30 #include "SALOMEGUI_Desktop.h"
31 #include "SALOMEGUI_ImportOperation.h"
32 #include "SALOMEGUI.h"
33 #include "SALOME_Selection.h"
34 #include "SALOME_ListIO.hxx"
35 #include "SALOME_ListIteratorOfListIO.hxx"
36 #include "SALOME_InteractiveObject.hxx"
38 #include "QAD_Desktop.h"
39 #include "QAD_RightFrame.h"
40 #include "QAD_LeftFrame.h"
41 #include "QAD_ObjectBrowser.h"
42 #include "QAD_Resource.h"
43 #include "QAD_Tools.h"
44 #include "QAD_WaitCursor.h"
45 #include "QAD_MessageBox.h"
48 #include <qapplication.h>
49 #include <qpopupmenu.h>
50 #include <qmessagebox.h>
52 // Open CASCADE Include
53 #include <Standard_Failure.hxx>
54 #include <TCollection_AsciiString.hxx>
60 SALOMEGUI_Application::SALOMEGUI_Application( const QString& format,
61 const QString& description,
62 const QString& filters) :
63 QAD_Application( format, description, filters )
67 QAD_ResourceMgr* resMgr = QAD_Desktop::getResourceManager();
68 if ( !resMgr ) resMgr = QAD_Desktop::createResourceManager();
69 if ( resMgr ) resMgr->loadResources( "SALOMEGUI", message );
71 QPalette* palette = QAD_Desktop::getPalette();
72 if ( !palette) palette = QAD_Desktop::createPalette();
73 // if ( !palette) palette->loadPalette();
75 //myViewActions.setAutoDelete( true );
77 /* We need to know that the desktop is created to have
78 some additional internal initialization */
79 QAD_ASSERT( connect( this, SIGNAL(desktopCreated()), SLOT(onDesktopCreated()) ));
85 SALOMEGUI_Application::~SALOMEGUI_Application()
90 Creates the actions provided by this application( internal )
92 void SALOMEGUI_Application::createActions()
95 /* this function must be called only once */
96 static bool created = false;
97 QAD_ASSERT_DEBUG_ONLY( !created );
101 /* Create 'View' actions
103 QToolBar* tbView = createToolBar( ViewToolBarId, tr("MEN_DESK_VIEWERTOOLBAR") );
105 QAD_ResourceMgr* rmgr = QAD_Desktop::getResourceManager();
106 #define CREATE_ACTION(ID,NAME) \
107 if(!myViewActions.at(ID)){ \
108 QActionP* action = new QActionP(tr("TOT_APP_VIEW_" #NAME), \
109 rmgr->loadPixmap("SALOMEGUI", tr("ICON_APP_VIEW_" #NAME)), \
110 tr("MEN_APP_VIEW_" #NAME), 0, QAD_Application::getDesktop()); \
111 action->setStatusTip(tr("PRP_APP_VIEW_" #NAME)); \
112 myViewActions.insert(ID,action); \
115 CREATE_ACTION(ViewDumpId,DUMP);
116 CREATE_ACTION(ViewTrihedronId,TRIHEDRON);
117 CREATE_ACTION(ViewFitAllId,FITALL);
118 CREATE_ACTION(ViewFitAreaId,FITAREA);
119 CREATE_ACTION(ViewZoomId,ZOOM);
120 CREATE_ACTION(ViewPanId,PAN);
121 CREATE_ACTION(ViewRotateId,ROTATE);
122 CREATE_ACTION(ViewGlobalPanId,GLOBALPAN);
123 CREATE_ACTION(ViewFrontId,FRONT);
124 CREATE_ACTION(ViewBackId,BACK);
125 CREATE_ACTION(ViewTopId,TOP);
126 CREATE_ACTION(ViewBottomId,BOTTOM);
127 CREATE_ACTION(ViewLeftId,LEFT);
128 CREATE_ACTION(ViewRightId,RIGHT);
129 CREATE_ACTION(ViewResetId,RESET);
135 Enables/disables the actions provided by this
136 application( internal )
138 void SALOMEGUI_Application::updateActions()
143 Creates CAF application
145 bool SALOMEGUI_Application::initApp(SALOME_NamingService* name_service)
147 if ( myStudyMgr->_is_nil() ) {
149 CORBA::Object_ptr obj = name_service->Resolve("/myStudyManager");
150 myStudyMgr = SALOMEDS::StudyManager::_narrow(obj);
152 catch ( Standard_Failure ) {
161 Creates the main desktop
163 bool SALOMEGUI_Application::createDesktop( SALOME_NamingService* name_service )
165 QAD_ASSERT_DEBUG_ONLY( !desktop );
166 desktop = new SALOMEGUI_Desktop(name_service);
167 return ( desktop != NULL );
171 Called when the main desktop is created ( internal )
173 void SALOMEGUI_Application::onDesktopCreated()
179 Called for customization when study is created
181 void SALOMEGUI_Application::onStudyCreated( QAD_Study* study )
186 Called for customization when study is opened
188 void SALOMEGUI_Application::onStudyOpened( QAD_Study* study )
193 Called for customization when study is activated (shown)
195 void SALOMEGUI_Application::onStudyShown( QAD_Study* study )
197 SALOMEDS::Study_var aStudy = study->getStudyDocument();
199 //srn: Forbid appending Interface Applicative and its children to UseCase
200 aStudy->EnableUseCaseAutoFilling(false);
202 /* mpv: study may be locked */
203 int aLocked = aStudy->GetProperties()->IsLocked();
204 if (aLocked) aStudy->GetProperties()->SetLocked(false);
206 /* update Object Browser */
207 SALOMEDS::StudyBuilder_var B = aStudy->NewBuilder();
208 SALOMEDS::SComponentIterator_var itcomp = aStudy->NewComponentIterator();
209 for (; itcomp->More(); itcomp->Next()) {
210 SALOMEDS::SComponent_var SC = itcomp->Value();
211 Standard_CString dataType = SC->ComponentDataType();
212 if ( QString(dataType).compare("Interface Applicative") == 0 ) {
213 SALOMEDS::ChildIterator_var it = aStudy->NewChildIterator(SC);
214 for (; it->More();it->Next()) {
215 SALOMEDS::SObject_var CSO = it->Value();
216 B->RemoveObject(CSO);
221 QAD_StudyFrame* sf = myActiveStudy->getActiveStudyFrame();
222 Standard_CString name = CORBA::string_dup(sf->title().latin1());
224 SALOMEDS::SComponent_var father = aStudy->FindComponent("Interface Applicative");
225 SALOMEDS::SObject_var newObj = B->NewObject(father);
226 SALOMEDS::GenericAttribute_var anAttr;
227 SALOMEDS::AttributeName_var aName;
228 SALOMEDS::AttributeComment_var aComment;
229 SALOMEDS::AttributeSelectable_var aSelAttr;
231 anAttr = B->FindOrCreateAttribute(newObj, "AttributeName");
232 aName = SALOMEDS::AttributeName::_narrow(anAttr);
233 aName->SetValue(name);
235 anAttr = B->FindOrCreateAttribute(newObj, "AttributeSelectable");
236 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
237 aSelAttr->SetSelectable(false);
239 if (sf->getTypeView() == VIEW_OCC) {
240 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
241 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
242 aComment->SetValue("OCC");
244 else if (sf->getTypeView() == VIEW_VTK) {
245 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
246 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
247 aComment->SetValue("VTK");
249 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
250 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
251 aComment->SetValue("GRAPH");
253 sf->setEntry(newObj->GetID());
255 if (aLocked) aStudy->GetProperties()->SetLocked(true);
257 study->updateObjBrowser( false );
259 aStudy->EnableUseCaseAutoFilling(true);
263 Called for customization when the active study is changed
265 void SALOMEGUI_Application::onActiveStudyChanged( QAD_Study* oldActiveStudy,
266 QAD_Study* newActiveStudy )
268 // MESSAGE ("SALOMEGUI_Application::onActiveStudyChanged init.");
269 /* superclass MUST be called */
270 QAD_Application::onActiveStudyChanged( oldActiveStudy, newActiveStudy );
272 if ( oldActiveStudy ) {
273 int count = oldActiveStudy->getStudyFramesCount();
274 for ( int i = 0; i < count; i++ ) {
275 disconnectFromViewer( oldActiveStudy->getStudyFrame(i)->getRightFrame()->getViewFrame() );
279 if ( newActiveStudy && newActiveStudy->getActiveStudyFrame() ) {
280 connectToViewer( newActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame() );
284 void SALOMEGUI_Application::connectToViewer( QAD_ViewFrame* vf )
286 #define CONNECT_ACTION(NAME) \
287 QAD_ASSERT(connect(myViewActions.at(View ##NAME ##Id), SIGNAL(activated()), vf, SLOT(onView ##NAME())))
290 QToolBar* tbView = getToolBar( ViewToolBarId );
291 for ( int cmd = ViewDumpId; cmd <= ViewResetId; cmd++ )
292 if ( myViewActions.at( cmd ) )
293 myViewActions.at( cmd )->removeFrom(tbView);
294 if( vf->getTypeView() == VIEW_GRAPHSUPERV ) {
295 //myViewActions.at(ViewDumpId)->addTo(tbView);
296 //myViewActions.at(ViewFitAllId)->addTo(tbView);
297 //myViewActions.at(ViewFitAreaId)->addTo(tbView);
298 //myViewActions.at(ViewZoomId)->addTo(tbView);
299 myViewActions.at(ViewPanId)->addTo(tbView);
300 //myViewActions.at(ViewGlobalPanId)->addTo(tbView);
301 myViewActions.at(ViewResetId)->addTo(tbView);
303 else if( vf->getTypeView() == VIEW_PLOT2D ) {
304 myViewActions.at(ViewDumpId)->addTo(tbView);
305 myViewActions.at(ViewFitAllId)->addTo(tbView);
306 myViewActions.at(ViewFitAreaId)->addTo(tbView);
307 myViewActions.at(ViewZoomId)->addTo(tbView);
308 myViewActions.at(ViewPanId)->addTo(tbView);
309 //myViewActions.at(ViewGlobalPanId)->addTo(tbView);
310 //myViewActions.at(ViewResetId)->addTo(tbView);
313 for ( int cmd = ViewDumpId; cmd <= ViewResetId; cmd++ )
314 if ( myViewActions.at( cmd ) )
315 myViewActions.at( cmd )->addTo(tbView);
317 //CONNECT_ACTION(Mu4Id)
318 CONNECT_ACTION(Dump);
319 CONNECT_ACTION(Trihedron);
320 CONNECT_ACTION(FitAll);
321 CONNECT_ACTION(FitArea);
322 CONNECT_ACTION(Zoom);
324 CONNECT_ACTION(Rotate);
325 CONNECT_ACTION(GlobalPan);
326 CONNECT_ACTION(Front);
327 CONNECT_ACTION(Back);
329 CONNECT_ACTION(Bottom);
330 CONNECT_ACTION(Left);
331 CONNECT_ACTION(Right);
332 CONNECT_ACTION(Reset);
335 #undef CONNECT_ACTION
338 void SALOMEGUI_Application::disconnectFromViewer( QAD_ViewFrame* vf )
340 #define DISCONNECT_ACTION(NAME) \
341 QAD_ASSERT(disconnect(myViewActions.at(View ##NAME ##Id), SIGNAL(activated()), vf, SLOT(onView ##NAME())));
343 if ( !vf || myViewActions.isEmpty() )
345 //DISCONNECT_ACTION(Mu4Id)
346 DISCONNECT_ACTION(Dump);
347 DISCONNECT_ACTION(Trihedron);
348 DISCONNECT_ACTION(FitAll);
349 DISCONNECT_ACTION(FitArea);
350 DISCONNECT_ACTION(Zoom);
351 DISCONNECT_ACTION(Pan);
352 DISCONNECT_ACTION(Rotate);
353 DISCONNECT_ACTION(GlobalPan);
354 DISCONNECT_ACTION(Front);
355 DISCONNECT_ACTION(Back);
356 DISCONNECT_ACTION(Top);
357 DISCONNECT_ACTION(Bottom);
358 DISCONNECT_ACTION(Left);
359 DISCONNECT_ACTION(Right);
360 DISCONNECT_ACTION(Reset);
362 #undef DISCONNECT_ACTION
366 Customizes 'View' menu of the desktop
368 int SALOMEGUI_Application::onUpdateViewActions ( QPopupMenu* popup, bool add, int index )
370 int nItemsAdded = QAD_Application::onUpdateViewActions( popup, add, index );
373 // index += nItemsAdded;
374 // QAD_ASSERT_DEBUG_ONLY( !myViewActions.isEmpty() );
375 // popup->insertSeparator( index++ );
376 // myViewActions.at( ViewTrihedronId )->addTo( popup );
378 // popup->insertSeparator( index++ );
379 // for ( int i = (int)ViewMu4Id; i <= (int)ViewRightId; i++ ) {
380 // myViewActions.at( i )->addTo( popup );
383 // popup->insertSeparator( index++ );
384 // myViewActions.at( ViewResetId )->addTo( popup );
387 // for ( int i = (int)ViewTrihedronId; i <= (int)ViewResetId; i++ ) {
388 // popup->removeItemAt(index);
391 // /* remove separators */
392 // popup->removeItemAt( index );
393 // popup->removeItemAt( index );
394 // popup->removeItemAt( index );
401 Adds the context popup items
403 void SALOMEGUI_Application::onCreatePopup()
405 // Here common menu items should be added (Display, Erase, etc.).
406 // They should be obtained through the standard XML-based mechanism,
407 // i.e. corresponding XML file should be loaded somewhere in advance
408 // and desktop->getOperatorsMenu() should return the default popup menu.
409 // These items are always added; if necessary any of them can be hidden
410 // during popup customization by means of the corresponding unique ID defined in QAD_Resource.h.
411 SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
413 if ( Sel->IObjectCount() > 0 ) {
414 myPopup->insertItem (tr ("MEN_APP_DISPLAY"), this, SLOT(onDisplay(int)), 0, QAD_Display_Popup_ID);
415 myPopup->insertItem (tr ("MEN_APP_DISPLAY_ONLY"), this, SLOT(onDisplay(int)), 0, QAD_DisplayOnly_Popup_ID);
416 myPopup->insertItem (tr ("MEN_APP_ERASE"), this, SLOT(onErase()), 0, QAD_Erase_Popup_ID);
422 void SALOMEGUI_Application::onDisplay(int id)
424 QAD_WaitCursor waitCursor;
426 // Obtain the component to deal with (according to selected object's parent component)
427 SALOME_Selection* Sel = SALOME_Selection::Selection(myActiveStudy->getSelection() );
429 QString parentComp = ((SALOMEGUI_Desktop*)desktop)->getComponentFromSelection();
430 if (parentComp.isNull()) { // objects from several components are selected -> do nothing
434 bool isViewTypeOK = true;
435 int viewTypes[VIEW_TYPE_MAX];
437 for (int i = 0; i < VIEW_TYPE_MAX; i++)
440 // Obtain the component's GUI
441 SALOMEGUI* aGUI = desktop->getComponentGUI( parentComp );
445 // Check if another view type is required (if viewToActivate < 0 then any type of view is acceptable)
446 aGUI->SupportedViewType(viewTypes, VIEW_TYPE_MAX);
447 if (viewTypes[0] >= 0) { // not all the view types are supported
448 for (int i = 0; i < VIEW_TYPE_MAX; i++) {
449 if (viewTypes[i] < 0) // no more types supported
451 isViewTypeOK = ((int)myActiveStudy->getActiveStudyFrame()->getTypeView() == viewTypes[i]);
452 if (isViewTypeOK) // one of supported views is already active
457 // Try to activate a view of one of supported types
459 MESSAGE("onDisplay(): view type is not acceptable")
460 unsigned frameCount = myActiveStudy->getStudyFramesCount();
461 for (unsigned i = 0; i < frameCount; i++) {
462 QAD_StudyFrame* frame = myActiveStudy->getStudyFrame(i);
463 for (int j = 0; j < VIEW_TYPE_MAX; j++) {
464 if (frame->getTypeView() == viewTypes[j]) {
465 MESSAGE("onDisplay(): activating other frame")
474 QMessageBox::warning( desktop,
476 tr("ERR_APP_WRONG_VIEW_TYPE"));
481 QAD_ViewFrame* viewFrame = myActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame();
483 // Ensure that parent component's data are loaded
484 QString compName = desktop->getComponentName( parentComp );
485 if ( compName.isEmpty() ) {
487 QAD_MessageBox::error1( desktop,
489 tr("ERR_EMPTY_COMP_NAME").arg( parentComp ),
494 desktop->loadComponentData( compName );
496 // Build the graphic presentation (it is stored in the corresponding viewer)
498 bool isComponent = false;
499 SALOMEDS::Study_var aStudy = myActiveStudy->getStudyDocument();
500 bool needRepaint = false;
502 // Copy the selection
503 SALOME_ListIteratorOfListIO itInit( Sel->StoredIObjects() );
504 SALOME_ListIO selList;
505 for (; itInit.More(); itInit.Next()) {
506 Handle(SALOME_InteractiveObject) IObject = itInit.Value();
507 if ( IObject->hasEntry() ) {
508 // check whether the component is selected
509 SALOMEDS::SObject_var obj = aStudy->FindObjectID(IObject->getEntry() );
510 if ( !obj->_is_nil() && strcmp( obj->GetFatherComponent()->GetID(), obj->GetID() ) == 0 ) {
513 selList.Append( IObject );
517 selList.Append( IObject );
520 if (id == QAD_DisplayOnly_Popup_ID)
521 viewFrame->EraseAll();
523 // For component -> display all children
525 SALOMEDS::SObject_var obj = aStudy->FindObjectID( selList.First()->getEntry() );
526 SALOMEDS::ChildIterator_ptr It = aStudy->NewChildIterator( obj );
528 for ( ; It->More(); It->Next() ) {
529 SALOMEDS::SObject_ptr child = It->Value();
530 SALOMEDS::SObject_ptr ref;
531 if ( !child->ReferencedObject( ref ) ) {
532 Handle(SALOME_InteractiveObject) childIObject = new SALOME_InteractiveObject();
533 childIObject->setEntry( child->GetID() );
534 // Ensure that proper 3D presentation exists for IObject
535 aGUI->BuildPresentation(childIObject);
536 viewFrame->Display(childIObject, false);
541 else { // for child object -> simply display it (no children are displayed)
542 SALOME_ListIteratorOfListIO It( selList );
543 for( ;It.More();It.Next() ) {
544 Handle(SALOME_InteractiveObject) IObject = It.Value();
545 // Ensure that proper 3D presentation exists for IObject
546 aGUI->BuildPresentation(IObject);
547 viewFrame->Display(IObject, false);
553 viewFrame->Repaint();
555 myActiveStudy->updateObjBrowser(true);
560 void SALOMEGUI_Application::onErase()
562 QAD_WaitCursor waitCursor;
564 SALOME_Selection* Sel = SALOME_Selection::Selection(myActiveStudy->getSelection() );
565 SALOMEDS::Study_var aStudy = myActiveStudy->getStudyDocument();
566 QAD_ViewFrame* viewFrame = myActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame();
567 bool needRepaint = false;
569 // Copy the selection
570 SALOME_ListIteratorOfListIO itInit( Sel->StoredIObjects() );
571 SALOME_ListIO selList;
572 for (; itInit.More(); itInit.Next()) {
573 selList.Append(itInit.Value());
576 SALOME_ListIteratorOfListIO It( selList );
577 for(;It.More();It.Next()) {
578 Handle(SALOME_InteractiveObject) IObject = It.Value();
580 // First check whether the object is a component or a child object
581 bool isComponent = false;
582 SALOMEDS::SObject_var obj;
584 if (IObject->hasEntry()) {
585 obj = aStudy->FindObjectID(IObject->getEntry());
586 if (!obj->_is_nil()) {
587 SALOMEDS::SComponent_var comp = obj->GetFatherComponent();
588 isComponent = (strcmp(comp->GetID(), obj->GetID()) == 0);
592 // For component -> erase all children
594 SALOMEDS::ChildIterator_ptr it = aStudy->NewChildIterator(obj);
596 for ( ; it->More(); it->Next()) {
597 SALOMEDS::SObject_ptr child = it->Value();
598 Handle(SALOME_InteractiveObject) childIObject = new SALOME_InteractiveObject();
599 childIObject->setEntry(child->GetID());
600 viewFrame->Erase(childIObject, false);
602 } else { // for child object -> simply erase it (no children are erased)
603 viewFrame->Erase(IObject, false);
609 viewFrame->Repaint();