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"
47 #include <qapplication.h>
48 #include <qpopupmenu.h>
49 #include <qmessagebox.h>
51 // Open CASCADE Include
52 #include <Standard_Failure.hxx>
53 #include <TCollection_AsciiString.hxx>
59 SALOMEGUI_Application::SALOMEGUI_Application( const QString& format,
60 const QString& description,
61 const QString& filters) :
62 QAD_Application( format, description, filters )
66 QAD_ResourceMgr* resMgr = QAD_Desktop::getResourceManager();
67 if ( !resMgr ) resMgr = QAD_Desktop::createResourceManager();
68 if ( resMgr ) resMgr->loadResources( "SALOMEGUI", message );
70 QPalette* palette = QAD_Desktop::getPalette();
71 if ( !palette) palette = QAD_Desktop::createPalette();
72 // if ( !palette) palette->loadPalette();
74 //myViewActions.setAutoDelete( true );
76 /* We need to know that the desktop is created to have
77 some additional internal initialization */
78 QAD_ASSERT( connect( this, SIGNAL(desktopCreated()), SLOT(onDesktopCreated()) ));
84 SALOMEGUI_Application::~SALOMEGUI_Application()
89 Creates the actions provided by this application( internal )
91 void SALOMEGUI_Application::createActions()
94 /* this function must be called only once */
95 static bool created = false;
96 QAD_ASSERT_DEBUG_ONLY( !created );
100 /* Create 'View' actions
102 QToolBar* tbView = createToolBar( ViewToolBarId, tr("MEN_DESK_VIEWERTOOLBAR") );
104 QAD_ResourceMgr* rmgr = QAD_Desktop::getResourceManager();
105 #define CREATE_ACTION(ID,NAME) \
106 if(!myViewActions.at(ID)){ \
107 QActionP* action = new QActionP(tr("TOT_APP_VIEW_" #NAME), \
108 rmgr->loadPixmap("SALOMEGUI", tr("ICON_APP_VIEW_" #NAME)), \
109 tr("MEN_APP_VIEW_" #NAME), 0, QAD_Application::getDesktop()); \
110 action->setStatusTip(tr("PRP_APP_VIEW_" #NAME)); \
111 myViewActions.insert(ID,action); \
114 CREATE_ACTION(ViewDumpId,DUMP);
115 CREATE_ACTION(ViewTrihedronId,TRIHEDRON);
116 CREATE_ACTION(ViewFitAllId,FITALL);
117 CREATE_ACTION(ViewFitAreaId,FITAREA);
118 CREATE_ACTION(ViewZoomId,ZOOM);
119 CREATE_ACTION(ViewPanId,PAN);
120 CREATE_ACTION(ViewRotateId,ROTATE);
121 CREATE_ACTION(ViewGlobalPanId,GLOBALPAN);
122 CREATE_ACTION(ViewFrontId,FRONT);
123 CREATE_ACTION(ViewBackId,BACK);
124 CREATE_ACTION(ViewTopId,TOP);
125 CREATE_ACTION(ViewBottomId,BOTTOM);
126 CREATE_ACTION(ViewLeftId,LEFT);
127 CREATE_ACTION(ViewRightId,RIGHT);
128 CREATE_ACTION(ViewResetId,RESET);
134 Enables/disables the actions provided by this
135 application( internal )
137 void SALOMEGUI_Application::updateActions()
142 Creates CAF application
144 bool SALOMEGUI_Application::initApp(SALOME_NamingService* name_service)
146 if ( myStudyMgr->_is_nil() ) {
148 CORBA::Object_ptr obj = name_service->Resolve("/myStudyManager");
149 myStudyMgr = SALOMEDS::StudyManager::_narrow(obj);
151 catch ( Standard_Failure ) {
160 Creates the main desktop
162 bool SALOMEGUI_Application::createDesktop( SALOME_NamingService* name_service )
164 QAD_ASSERT_DEBUG_ONLY( !desktop );
165 desktop = new SALOMEGUI_Desktop(name_service);
166 return ( desktop != NULL );
170 Called when the main desktop is created ( internal )
172 void SALOMEGUI_Application::onDesktopCreated()
178 Called for customization when study is created
180 void SALOMEGUI_Application::onStudyCreated( QAD_Study* study )
185 Called for customization when study is opened
187 void SALOMEGUI_Application::onStudyOpened( QAD_Study* study )
192 Called for customization when study is activated (shown)
194 void SALOMEGUI_Application::onStudyShown( QAD_Study* study )
196 SALOMEDS::Study_var aStudy = study->getStudyDocument();
198 //srn: Forbid appending Interface Applicative and its children to UseCase
199 aStudy->EnableUseCaseAutoFilling(false);
201 /* mpv: study may be locked */
202 int aLocked = aStudy->GetProperties()->IsLocked();
203 if (aLocked) aStudy->GetProperties()->SetLocked(false);
205 /* update Object Browser */
206 SALOMEDS::StudyBuilder_var B = aStudy->NewBuilder();
207 SALOMEDS::SComponentIterator_var itcomp = aStudy->NewComponentIterator();
208 for (; itcomp->More(); itcomp->Next()) {
209 SALOMEDS::SComponent_var SC = itcomp->Value();
210 Standard_CString dataType = SC->ComponentDataType();
211 if ( QString(dataType).compare("Interface Applicative") == 0 ) {
212 SALOMEDS::ChildIterator_var it = aStudy->NewChildIterator(SC);
213 for (; it->More();it->Next()) {
214 SALOMEDS::SObject_var CSO = it->Value();
215 B->RemoveObject(CSO);
220 QAD_StudyFrame* sf = myActiveStudy->getActiveStudyFrame();
221 Standard_CString name = strdup(sf->title().latin1());
223 SALOMEDS::SComponent_var father = aStudy->FindComponent("Interface Applicative");
224 SALOMEDS::SObject_var newObj = B->NewObject(father);
225 SALOMEDS::GenericAttribute_var anAttr;
226 SALOMEDS::AttributeName_var aName;
227 SALOMEDS::AttributeComment_var aComment;
228 SALOMEDS::AttributeSelectable_var aSelAttr;
230 anAttr = B->FindOrCreateAttribute(newObj, "AttributeName");
231 aName = SALOMEDS::AttributeName::_narrow(anAttr);
232 aName->SetValue(name);
234 anAttr = B->FindOrCreateAttribute(newObj, "AttributeSelectable");
235 aSelAttr = SALOMEDS::AttributeSelectable::_narrow(anAttr);
236 aSelAttr->SetSelectable(false);
238 if (sf->getTypeView() == VIEW_OCC) {
239 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
240 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
241 aComment->SetValue("OCC");
243 else if (sf->getTypeView() == VIEW_VTK) {
244 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
245 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
246 aComment->SetValue("VTK");
248 anAttr = B->FindOrCreateAttribute(newObj, "AttributeComment");
249 aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
250 aComment->SetValue("GRAPH");
252 sf->setEntry(newObj->GetID());
254 if (aLocked) aStudy->GetProperties()->SetLocked(true);
256 study->updateObjBrowser( false );
258 aStudy->EnableUseCaseAutoFilling(true);
262 Called for customization when the active study is changed
264 void SALOMEGUI_Application::onActiveStudyChanged( QAD_Study* oldActiveStudy,
265 QAD_Study* newActiveStudy )
267 // MESSAGE ("SALOMEGUI_Application::onActiveStudyChanged init.");
268 /* superclass MUST be called */
269 QAD_Application::onActiveStudyChanged( oldActiveStudy, newActiveStudy );
271 if ( oldActiveStudy ) {
272 int count = oldActiveStudy->getStudyFramesCount();
273 for ( int i = 0; i < count; i++ ) {
274 disconnectFromViewer( oldActiveStudy->getStudyFrame(i)->getRightFrame()->getViewFrame() );
278 if ( newActiveStudy && newActiveStudy->getActiveStudyFrame() ) {
279 connectToViewer( newActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame() );
283 void SALOMEGUI_Application::connectToViewer( QAD_ViewFrame* vf )
285 #define CONNECT_ACTION(NAME) \
286 QAD_ASSERT(connect(myViewActions.at(View ##NAME ##Id), SIGNAL(activated()), vf, SLOT(onView ##NAME())))
289 QToolBar* tbView = getToolBar( ViewToolBarId );
290 for ( int cmd = ViewDumpId; cmd <= ViewResetId; cmd++ )
291 if ( myViewActions.at( cmd ) )
292 myViewActions.at( cmd )->removeFrom(tbView);
293 if( vf->getTypeView() == VIEW_GRAPHSUPERV ) {
294 //myViewActions.at(ViewDumpId)->addTo(tbView);
295 //myViewActions.at(ViewFitAllId)->addTo(tbView);
296 //myViewActions.at(ViewFitAreaId)->addTo(tbView);
297 //myViewActions.at(ViewZoomId)->addTo(tbView);
298 myViewActions.at(ViewPanId)->addTo(tbView);
299 //myViewActions.at(ViewGlobalPanId)->addTo(tbView);
300 myViewActions.at(ViewResetId)->addTo(tbView);
302 else if( vf->getTypeView() == VIEW_PLOT2D ) {
303 myViewActions.at(ViewDumpId)->addTo(tbView);
304 myViewActions.at(ViewFitAllId)->addTo(tbView);
305 myViewActions.at(ViewFitAreaId)->addTo(tbView);
306 myViewActions.at(ViewZoomId)->addTo(tbView);
307 myViewActions.at(ViewPanId)->addTo(tbView);
308 //myViewActions.at(ViewGlobalPanId)->addTo(tbView);
309 //myViewActions.at(ViewResetId)->addTo(tbView);
312 for ( int cmd = ViewDumpId; cmd <= ViewResetId; cmd++ )
313 if ( myViewActions.at( cmd ) )
314 myViewActions.at( cmd )->addTo(tbView);
316 //CONNECT_ACTION(Mu4Id)
317 CONNECT_ACTION(Dump);
318 CONNECT_ACTION(Trihedron);
319 CONNECT_ACTION(FitAll);
320 CONNECT_ACTION(FitArea);
321 CONNECT_ACTION(Zoom);
323 CONNECT_ACTION(Rotate);
324 CONNECT_ACTION(GlobalPan);
325 CONNECT_ACTION(Front);
326 CONNECT_ACTION(Back);
328 CONNECT_ACTION(Bottom);
329 CONNECT_ACTION(Left);
330 CONNECT_ACTION(Right);
331 CONNECT_ACTION(Reset);
334 #undef CONNECT_ACTION
337 void SALOMEGUI_Application::disconnectFromViewer( QAD_ViewFrame* vf )
339 #define DISCONNECT_ACTION(NAME) \
340 QAD_ASSERT(disconnect(myViewActions.at(View ##NAME ##Id), SIGNAL(activated()), vf, SLOT(onView ##NAME())));
342 if ( !vf || myViewActions.isEmpty() )
344 //DISCONNECT_ACTION(Mu4Id)
345 DISCONNECT_ACTION(Dump);
346 DISCONNECT_ACTION(Trihedron);
347 DISCONNECT_ACTION(FitAll);
348 DISCONNECT_ACTION(FitArea);
349 DISCONNECT_ACTION(Zoom);
350 DISCONNECT_ACTION(Pan);
351 DISCONNECT_ACTION(Rotate);
352 DISCONNECT_ACTION(GlobalPan);
353 DISCONNECT_ACTION(Front);
354 DISCONNECT_ACTION(Back);
355 DISCONNECT_ACTION(Top);
356 DISCONNECT_ACTION(Bottom);
357 DISCONNECT_ACTION(Left);
358 DISCONNECT_ACTION(Right);
359 DISCONNECT_ACTION(Reset);
361 #undef DISCONNECT_ACTION
365 Customizes 'View' menu of the desktop
367 int SALOMEGUI_Application::onUpdateViewActions ( QPopupMenu* popup, bool add, int index )
369 int nItemsAdded = QAD_Application::onUpdateViewActions( popup, add, index );
372 // index += nItemsAdded;
373 // QAD_ASSERT_DEBUG_ONLY( !myViewActions.isEmpty() );
374 // popup->insertSeparator( index++ );
375 // myViewActions.at( ViewTrihedronId )->addTo( popup );
377 // popup->insertSeparator( index++ );
378 // for ( int i = (int)ViewMu4Id; i <= (int)ViewRightId; i++ ) {
379 // myViewActions.at( i )->addTo( popup );
382 // popup->insertSeparator( index++ );
383 // myViewActions.at( ViewResetId )->addTo( popup );
386 // for ( int i = (int)ViewTrihedronId; i <= (int)ViewResetId; i++ ) {
387 // popup->removeItemAt(index);
390 // /* remove separators */
391 // popup->removeItemAt( index );
392 // popup->removeItemAt( index );
393 // popup->removeItemAt( index );
400 Adds the context popup items
402 void SALOMEGUI_Application::onCreatePopup()
404 // Here common menu items should be added (Display, Erase, etc.).
405 // They should be obtained through the standard XML-based mechanism,
406 // i.e. corresponding XML file should be loaded somewhere in advance
407 // and desktop->getOperatorsMenu() should return the default popup menu.
408 // These items are always added; if necessary any of them can be hidden
409 // during popup customization by means of the corresponding unique ID defined in QAD_Resource.h.
410 SALOME_Selection* Sel = SALOME_Selection::Selection( myActiveStudy->getSelection() );
412 if ( Sel->IObjectCount() > 0 ) {
413 myPopup->insertItem (tr ("MEN_APP_DISPLAY"), this, SLOT(onDisplay(int)), 0, QAD_Display_Popup_ID);
414 myPopup->insertItem (tr ("MEN_APP_DISPLAY_ONLY"), this, SLOT(onDisplay(int)), 0, QAD_DisplayOnly_Popup_ID);
415 myPopup->insertItem (tr ("MEN_APP_ERASE"), this, SLOT(onErase()), 0, QAD_Erase_Popup_ID);
421 void SALOMEGUI_Application::onDisplay(int id)
423 QAD_WaitCursor waitCursor;
425 // Obtain the component to deal with (according to selected object's parent component)
426 SALOME_Selection* Sel = SALOME_Selection::Selection(myActiveStudy->getSelection() );
428 QString parentComp = ((SALOMEGUI_Desktop*)desktop)->getComponentFromSelection();
429 if (parentComp.isNull()) { // objects from several components are selected -> do nothing
433 bool isViewTypeOK = true;
434 int viewTypes[VIEW_TYPE_MAX];
436 for (int i = 0; i < VIEW_TYPE_MAX; i++)
439 // Obtain the component's GUI
440 SALOMEGUI* aGUI = desktop->getComponentGUI( parentComp );
444 // Check if another view type is required (if viewToActivate < 0 then any type of view is acceptable)
445 aGUI->SupportedViewType(viewTypes, VIEW_TYPE_MAX);
446 if (viewTypes[0] >= 0) { // not all the view types are supported
447 for (int i = 0; i < VIEW_TYPE_MAX; i++) {
448 if (viewTypes[i] < 0) // no more types supported
450 isViewTypeOK = ((int)myActiveStudy->getActiveStudyFrame()->getTypeView() == viewTypes[i]);
451 if (isViewTypeOK) // one of supported views is already active
456 // Try to activate a view of one of supported types
458 MESSAGE("onDisplay(): view type is not acceptable")
459 unsigned frameCount = myActiveStudy->getStudyFramesCount();
460 for (unsigned i = 0; i < frameCount; i++) {
461 QAD_StudyFrame* frame = myActiveStudy->getStudyFrame(i);
462 for (int j = 0; j < VIEW_TYPE_MAX; j++) {
463 if (frame->getTypeView() == viewTypes[j]) {
464 MESSAGE("onDisplay(): activating other frame")
473 QMessageBox::warning( desktop,
475 tr("ERR_APP_WRONG_VIEW_TYPE"));
480 QAD_ViewFrame* viewFrame = myActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame();
482 // Build the graphic presentation (it is stored in the corresponding viewer)
484 // Copy the selection
485 SALOME_ListIteratorOfListIO itInit( Sel->StoredIObjects() );
486 SALOME_ListIO selList;
487 for (; itInit.More(); itInit.Next()) {
488 selList.Append(itInit.Value());
491 SALOMEDS::Study_var aStudy = myActiveStudy->getStudyDocument();
493 bool needRepaint = false;
495 if (id == QAD_DisplayOnly_Popup_ID)
496 viewFrame->EraseAll();
498 SALOME_ListIteratorOfListIO It( selList );
499 for(;It.More();It.Next()) {
500 Handle(SALOME_InteractiveObject) IObject = It.Value();
502 // First check whether the object is a component or a child object
503 bool isComponent = false;
505 if (!IObject->hasEntry()) continue;
507 SALOMEDS::SObject_var obj = aStudy->FindObjectID(IObject->getEntry());
508 if (!obj->_is_nil()) {
509 SALOMEDS::SComponent_var comp = obj->GetFatherComponent();
510 isComponent = (strcmp(comp->GetID(), obj->GetID()) == 0);
513 // For component -> display all children
515 SALOMEDS::ChildIterator_ptr it = aStudy->NewChildIterator(obj);
517 for ( ; it->More(); it->Next()) {
518 SALOMEDS::SObject_ptr child = it->Value();
519 Handle(SALOME_InteractiveObject) childIObject = new SALOME_InteractiveObject();
520 childIObject->setEntry(child->GetID());
522 // Ensure that proper 3D presentation exists for IObject
523 aGUI->BuildPresentation(childIObject);
524 viewFrame->Display(childIObject, false);
527 } else { // for child object -> simply display it (no children are displayed)
528 // Ensure that proper 3D presentation exists for IObject
529 aGUI->BuildPresentation(IObject);
530 viewFrame->Display(IObject, false);
537 viewFrame->Repaint();
539 myActiveStudy->updateObjBrowser(true);
544 void SALOMEGUI_Application::onErase()
546 QAD_WaitCursor waitCursor;
548 SALOME_Selection* Sel = SALOME_Selection::Selection(myActiveStudy->getSelection() );
549 SALOMEDS::Study_var aStudy = myActiveStudy->getStudyDocument();
550 QAD_ViewFrame* viewFrame = myActiveStudy->getActiveStudyFrame()->getRightFrame()->getViewFrame();
551 bool needRepaint = false;
553 // Copy the selection
554 SALOME_ListIteratorOfListIO itInit( Sel->StoredIObjects() );
555 SALOME_ListIO selList;
556 for (; itInit.More(); itInit.Next()) {
557 selList.Append(itInit.Value());
560 SALOME_ListIteratorOfListIO It( selList );
561 for(;It.More();It.Next()) {
562 Handle(SALOME_InteractiveObject) IObject = It.Value();
564 // First check whether the object is a component or a child object
565 bool isComponent = false;
566 SALOMEDS::SObject_var obj;
568 if (IObject->hasEntry()) {
569 obj = aStudy->FindObjectID(IObject->getEntry());
570 if (!obj->_is_nil()) {
571 SALOMEDS::SComponent_var comp = obj->GetFatherComponent();
572 isComponent = (strcmp(comp->GetID(), obj->GetID()) == 0);
576 // For component -> erase all children
578 SALOMEDS::ChildIterator_ptr it = aStudy->NewChildIterator(obj);
580 for ( ; it->More(); it->Next()) {
581 SALOMEDS::SObject_ptr child = it->Value();
582 Handle(SALOME_InteractiveObject) childIObject = new SALOME_InteractiveObject();
583 childIObject->setEntry(child->GetID());
584 viewFrame->Erase(childIObject, false);
586 } else { // for child object -> simply erase it (no children are erased)
587 viewFrame->Erase(IObject, false);
593 viewFrame->Repaint();