Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/superv.git] / src / SUPERVGUI / SUPERVGUI.cxx
1 //  SUPERV SUPERVGUI : GUI for Supervisor component
2 //
3 //  Copyright (C) 2003  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 //
23 //
24 //  File   : SUPERVGUI.cxx
25 //  Author : Francis KLOSS
26 //  Module : SUPERV
27
28 #include "SUPERVGUI.h"
29 #include "SUPERVGUI_DataModel.h"
30 #include "SUPERVGUI_Selection.h"
31
32 #include "CAM_Application.h"
33 #include "OB_Browser.h"
34 #include "OB_ListItem.h"
35 #include "SalomeApp_Application.h"
36 #include "SalomeApp_ImportOperation.h"
37 #include "LightApp_SelectionMgr.h"
38 #include "SalomeApp_Study.h"
39 #include "SUIT_Desktop.h"
40 #include "SUIT_FileDlg.h"
41 #include "SUIT_MessageBox.h"
42 #include "SUIT_Operation.h"
43 #include "SUIT_ResourceMgr.h"
44 #include "SUIT_Session.h"
45 #include "SUIT_Study.h"
46
47 #include "SUPERVGraph_ViewManager.h"
48 #include "SUPERVGraph_ViewFrame.h"
49
50 #include "SALOME_ListIO.hxx"
51 #include "SALOME_ListIteratorOfListIO.hxx"
52 #include "SALOME_InteractiveObject.hxx"
53 #include "Utils_ORB_INIT.hxx"
54
55 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
56
57 #include <qinputdialog.h>
58 #include <qmenubar.h>
59
60 #include "SALOMEDSClient.hxx"
61 #include <boost/shared_ptr.hpp>
62 using namespace boost;
63
64 int SUPERVGUI::factory = 0;
65
66 extern "C" {
67   Standard_EXPORT CAM_Module* createModule() {
68     return new SUPERVGUI();
69   }
70 }
71
72
73 SUPERVGUI::SUPERVGUI()
74      : SalomeApp_Module( "SUPERV" ),
75        study(0),
76        browser(0),
77        myFirstActivation(true),
78        myAllGraphsClosed(false),
79        myInitialViewFrame(0),
80        myIVFBackgroundColor(QColor())
81   //info(0)
82 {
83     Trace("SUPERVGUI::SUPERVGUI")
84     if (factory==0) {
85         factory = 1;
86         MESSAGE("SUPERVGUI Info : factory build");
87     } else {
88         MESSAGE("SUPERVGUI Error : another call to factory constructor");
89     };
90 }
91
92 SUPERVGUI::~SUPERVGUI() {
93     Trace("SUPERVGUI::~SUPERVGUI")
94     if (factory==1) {
95         factory = 0;
96         //if (!engine->_is_nil()) CORBA::release(engine);
97         //info->close();
98         if (browser) {
99           if (browser->isVisible())
100             browser->close();
101           delete browser;
102         }
103         MESSAGE("SUPERVGUI Info : factory destroy");
104     } else {
105         MESSAGE("SUPERVGUI Error : another call to factory destructor");
106     };
107 }
108
109 SUPERVGUI* SUPERVGUI::Supervision() {
110   CAM_Application* anApp = dynamic_cast<CAM_Application*>( SUIT_Session::session()->activeApplication() );
111   if ( anApp ) {
112     SUPERVGUI* aSupervModule = dynamic_cast<SUPERVGUI*>( anApp->activeModule() );
113     return aSupervModule;
114   }
115   return NULL;
116 }
117
118 void SUPERVGUI::createSupervAction (const int id, const QString& po_id, const QString& icon_id,
119                                     const int key, const bool toggle)
120 {
121   QIconSet icon;
122   QWidget* parent = application()->desktop();
123   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
124   QPixmap pix;
125   if (!icon_id.isEmpty())
126     pix = resMgr->loadPixmap("SUPERV", tr(icon_id));
127   //else
128   //  pix = resMgr->loadPixmap("SUPERV", tr(QString("ICO_") + po_id));
129
130   if (!pix.isNull())
131     icon = QIconSet(pix);
132
133   QString tooltip    = tr(QString("TOP_") + po_id),
134           menu       = tr(QString("MEN_") + po_id),
135           status_bar = tr(QString("STB_") + po_id);
136
137   createAction(id, tooltip, icon, menu, status_bar, key, parent, toggle, this, SLOT(OnGUIEvent()));
138 }
139
140 void SUPERVGUI::initialize( CAM_Application* app )
141 {
142   SalomeApp_Module::initialize( app );
143
144   SALOME_NamingService* namingService = (( SalomeApp_Application* )application())->namingService();
145   loadEngine(namingService);
146
147   browser = new SUPERVGUI_Service(namingService);
148   //info    = new SUPERVGUI_Information();
149   cursor  = application()->desktop()->cursor();
150
151   fillInterfaceNameMap();
152
153   // ----- create actions --------------
154   createSupervAction( 301, "IMPORT"        , "ICO_IMPORT" );
155   createSupervAction( 302, "EXPORT"        , "ICO_EXPORT" );
156
157   createSupervAction( 303, "NEW"           , "ICO_NEW" );
158   createSupervAction( 304, "MODIFY"        , "ICO_MODIFY" );
159
160   createSupervAction( 305, "RELOAD"        , "ICO_RELOAD" );
161   createSupervAction( 306, "RUN"           , "ICO_RUN" );
162   createSupervAction( 307, "KILL"          , "ICO_KILL" );
163   createSupervAction( 308, "SUSPEND/RESUME", "ICO_SUSPEND/RESUME" );
164   createSupervAction( 309, "ADDNODE"       , "ICO_ADDNODE" );
165   createSupervAction( 310, "STEPBYSTEP"    , "ICO_STEPBYSTEP" );
166
167   createSupervAction( 311, "POP_RENAME", "", Key_F2 );
168   createSupervAction( 312, "POP_DISPLAY" );
169   createSupervAction( 313, "POP_DELETE", "", Key_Delete );
170
171   // ----- create menu -----------------
172   int fileId = createMenu( tr( "MEN_FILE" ), -1, -1 );
173   createMenu( 301, fileId, 10 );
174   createMenu( 302, fileId, 10 );
175   createMenu( separator(), fileId, 10 );
176
177   int editId = createMenu( tr( "MEN_EDIT" ), -1, -1 );
178   createMenu( separator(), fileId, 7 );
179   createMenu( 303, editId, -1 );
180   createMenu( 304, editId, -1 );
181
182   int supervId = createMenu( tr( "MEN_SUPERV" ), -1, -1, 10/*, 300*/ );
183   createMenu( 305, supervId, -1 );
184   createMenu( 309, supervId, -1 );
185   createMenu( separator(), fileId, 3 );
186   createMenu( 306, supervId, -1 );
187   createMenu( 310, supervId, -1 );
188   createMenu( 307, supervId, -1 );
189   createMenu( 308, supervId, -1 );
190
191   // ----- create toolbars -------------
192   int supervisorId = createTool( tr( "TOOL_SUPERVISOR" ) );
193   createTool( 301, supervisorId );
194   createTool( 302, supervisorId );
195   createTool( 303, supervisorId );
196   createTool( 304, supervisorId );
197   createTool( 305, supervisorId );
198   createTool( 309, supervisorId );
199
200   int executionId = createTool( tr( "TOOL_EXECUTION" ) );
201   createTool( 306, executionId );
202   createTool( 310, executionId );
203   createTool( 307, executionId );
204   createTool( 308, executionId );
205
206   // ----- create popup for object browser items -------------
207   QtxPopupMgr* mgr = popupMgr();
208   mgr->insert( action(  311 ), -1, -1 ); // rename dataflow
209   mgr->setRule( action( 311 ), "$type in {'Dataflow'} and selcount=1", true );
210   mgr->insert( action(  312 ), -1, -1 ); // display dataflow
211   mgr->setRule( action( 312 ), "$type in {'Dataflow'} and selcount=1", true );
212   mgr->insert( separator(), -1, -1 ); // -----------
213   mgr->insert( action(  313 ), -1, -1 ); // delete object
214   mgr->setRule( action( 313 ), "client='ObjectBrowser' and $type in {'Dataflow' 'SupervisorObject'} and selcount>0", true );
215 }
216
217 bool SUPERVGUI::activateModule( SUIT_Study* theStudy )
218 {
219   if ( CORBA::is_nil( engine ) )
220     return false;
221
222   if ( !SalomeApp_Module::activateModule( theStudy ) )
223     return false;
224
225
226
227   //---------------------------------------
228   setMenuShown( true );
229   setToolShown( true );
230
231   study = application()->activeStudy();
232
233   connect( application()->desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
234            this, SLOT( setMain( SUIT_ViewWindow* ) ) );
235
236   if ( myFirstActivation ) {
237     myAllGraphsClosed = false;
238     // create new empty dataflow
239     createDataflow( New, true );
240   }
241
242   return true;
243 }
244
245 QString SUPERVGUI::engineIOR() const
246 {
247  if ( !CORBA::is_nil( engine ) )
248     return QString( getApp()->orb()->object_to_string( engine));
249   return QString( "" );
250 }
251
252 bool SUPERVGUI::deactivateModule( SUIT_Study* theStudy )
253 {
254   setMenuShown( false );
255   setToolShown( false );
256
257   disconnect( application()->desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
258               this, SLOT( setMain( SUIT_ViewWindow* ) ) );
259   //---------------------------------------
260
261   if ( !myAllGraphsClosed )
262     myFirstActivation = false;
263
264   return SalomeApp_Module::deactivateModule( theStudy );
265 }
266
267 CAM_DataModel* SUPERVGUI::createDataModel()
268 {
269   return new SUPERVGUI_DataModel( this );
270 }
271
272 LightApp_Selection* SUPERVGUI::createSelection() const
273 {
274   return new SUPERVGUI_Selection();
275 }
276
277 SUIT_ViewWindow* SUPERVGUI::createGraph() {
278   SUPERVGraph_ViewManager* aVM = new SUPERVGraph_ViewManager( study, application()->desktop(), new SUPERVGraph_Viewer() );
279   (( SalomeApp_Application* )application())->addViewManager( aVM );
280   SUPERVGraph_ViewFrame* aVW = dynamic_cast<SUPERVGraph_ViewFrame*>( aVM->createViewWindow() );
281   if ( aVW ) {
282     QColor back = getApp()->resourceMgr()->colorValue( "SUPERVGraph", "Background", DEF_MAIN_COLOR );
283     qDebug( QString( "background: %1 %2 %3" ).arg( back.red() ).arg( back.green() ).arg( back.blue() ) );
284     aVW->setBackgroundColor( back );
285     connect( aVM,
286              SIGNAL( deleteView( SUIT_ViewWindow* ) ),
287              this,
288              SLOT( onGraphClosed( SUIT_ViewWindow* ) ) );
289   }
290   return aVW;
291 }
292
293
294
295 void SUPERVGUI::loadEngine(SALOME_NamingService* namingService) {
296     Trace("SUPERVGUI::loadEngine")
297     SALOME_LifeCycleCORBA LCC(namingService);
298     Engines::Component_var objComponent = LCC.FindOrLoad_Component("SuperVisionContainer", "SUPERV");
299     if (CORBA::is_nil(objComponent)) {
300         QMessageBox::warning(application()->desktop(), tr("ERROR"), tr("MSG_CANT_LOAD_SUPERV"));
301         return;
302     };
303
304     SUPERV::SuperG_var aSuperVisionComponent;
305     aSuperVisionComponent = SUPERV::SuperG::_narrow(objComponent);
306     if (CORBA::is_nil(aSuperVisionComponent)) {
307         QMessageBox::warning(application()->desktop(), tr("ERROR"), tr("MSG_CANT_NARROW_SUPERV"));
308         return;
309     };
310
311     //    engine  = new SUPERV::SuperG_var;
312     engine = aSuperVisionComponent;
313 }
314
315 /*
316 bool SUPERVGUI::information(SUPERV_CNode node, bool isReadOnly) {
317     Trace("SUPERVGUI::information")
318     return(info->run(node, isReadOnly));
319 }
320 */
321 void SUPERVGUI::putInfo(const char* mess) {
322     Trace("SUPERVGUI::putInfo")
323     application()->putInfo(mess);
324 }
325
326 SUPERV_Engine SUPERVGUI::getEngine() {
327     Trace("SUPERVGUI::getEngine")
328     return(engine);
329 }
330
331 SUPERVGUI_Service* SUPERVGUI::getBrowser() {
332     Trace("SUPERVGUI::getBrowser")
333     return(browser);
334 }
335
336 QCursor SUPERVGUI::getCursor() {
337     Trace("SUPERVGUI::getCursor")
338     return(cursor);
339 }
340
341 SUPERVGUI_Main* SUPERVGUI::getMain() {
342     Trace("SUPERVGUI::getMain")
343     return main;
344 }
345
346
347 void SUPERVGUI::registerGraph(QString theName, SUPERVGUI_Main* theGraph){
348   theGraph->setHashCode(theName);
349   myGraphList.append(theGraph);
350 }
351
352
353 void SUPERVGUI::unregisterGraph(SUPERVGUI_Main* theGraph) {
354   SUPERVGUI_Main* aMain;
355   for (aMain = myGraphList.first(); aMain; aMain = myGraphList.next()) {
356     if (aMain == theGraph)
357       myGraphList.remove(aMain);
358   }
359 }
360
361
362 bool SUPERVGUI::isContains(SUIT_Study* theStudy, const QString theKey) {
363   SUPERVGUI_Main* aMain;
364   for (aMain = myGraphList.first(); aMain; aMain = myGraphList.next()) {
365     if ((aMain->getStudy() == theStudy) && (aMain->getHashCode() == theKey))
366       return true;
367   }
368   return false;
369 }
370
371
372 void SUPERVGUI::onGraphClosed(SUIT_ViewWindow* theViewWindow) {
373   if( SUPERVGraph_ViewFrame* supervFrame = dynamic_cast<SUPERVGraph_ViewFrame*>(theViewWindow) ) {
374     disconnect(supervFrame->getViewManager(), 0 , this, 0);
375     SUPERVGraph_View* view = supervFrame->getViewWidget();
376     SUPERVGUI_Main* aGraph = dynamic_cast<SUPERVGUI_Main*>(view);
377     if ( aGraph ) {
378       // mkr: PAL12449 --->
379       if ( (( SalomeApp_Study* )(aGraph->getStudy()))->studyDS() && !aGraph->isDataflowInStudy() ) {
380         const int aWarnResult = QMessageBox::information(application()->desktop(), tr("MSG_INFO"),
381                                                          tr("MSG_GRAPH_UNSAVED"),
382                                                          QMessageBox::Yes, QMessageBox::No);
383         if ( aWarnResult == QMessageBox::Yes ) {
384           aGraph->addDataflowToStudy();
385           updateObjBrowser();
386         }
387       }
388       // mkr: PAL12449 <---
389       
390       unregisterGraph(aGraph);
391       SUPERV_Graph aDataFlow = aGraph->getDataflow();
392       if ( !SUPERV_isNull( aDataFlow ) ) {
393         if ( aDataFlow->IsExecuting() ) {
394           const int aMsgResult = QMessageBox::warning(application()->desktop(),
395                                                       tr("WARNING"),
396                                                       tr("MSG_DF_RUNNING"),
397                                                       tr("MSG_DF_EXECUTION"),
398                                                       tr("MSG_DF_KILL"));
399           if ( aMsgResult == 1 ) {
400             // KILL EXECUTION
401             if ( aDataFlow->Kill() ) {
402               // Kill() sends KillEvent and KillState to SUPERVGUI_Thread
403               // while sets myIsActive flag to false when it receives such event/state
404               // after myIsActive is false it calls QThread::exit() to terminate.
405               
406               // why while() { qApp->processEvents() } ?
407               // because: SUPERVGUI_Thread::run() receives events, and calls myMain->execute()
408               // method using SALOME_Event paradigm, ProcessVoidEvent() function -
409               // it puts this event to the main application event loop, in which we are being now.
410               // So if we block main GUI application thread (by calling aGraph->getMyThread()->wait() here)
411               // then we will have a deadlock of 2 threads waiting for one another
412               while (aGraph->getMyThread()->running())
413                 qApp->processEvents();
414             }
415           }
416           else { // BACKGROUND EXECUTION
417             emit KillMainThread(true); // set SUPERVGUI_Thread::myIsActive to false
418             while ( aGraph->getMyThread()->running() )
419               qApp->processEvents();
420           }
421         }
422         else { // EXECUTION IS FINISHED, JUST DESTROY THE SUPERVGUI_Thread object and return.
423           emit KillMainThread(true);
424           while ( aGraph->getMyThread()->running() )
425             qApp->processEvents();
426         }
427       }
428     }
429   }
430   if ( myGraphList.isEmpty() ) {
431     myAllGraphsClosed = true;
432     myFirstActivation = true;
433     myInitialViewFrame = 0;
434     myIVFBackgroundColor = QColor();
435     main = 0;
436   }
437 }
438
439 void SUPERVGUI::setMain( SUIT_ViewWindow* w) {
440   main = 0;
441   if ( !w ) return;
442
443   study = w->getViewManager()->study();
444   if (!study)
445     return;
446
447   if(SUPERVGraph_ViewFrame* supervFrame = dynamic_cast<SUPERVGraph_ViewFrame*>(w)){
448     SUPERVGraph_View* view = supervFrame->getViewWidget();
449     if (view) {
450       main = dynamic_cast<SUPERVGUI_Main*>(view);
451       connect(this, SIGNAL(KillMainThread(bool)), main->getMyThread(), SLOT(KillThread(bool)));
452     }
453   }
454   Trace("SUPERVGUI::setMain - main: "<<main);
455 }
456
457 void SUPERVGUI::displayDataflow() {
458   Trace("SUPERVGUI::displayDataflow");
459
460   OB_Browser* aBrowser = getApp()->objectBrowser();
461   OB_ListItem* item = (OB_ListItem*)(aBrowser->listView()->currentItem());
462
463   SalomeApp_Study* anAppStudy = (SalomeApp_Study*)(getApp()->activeStudy());
464   _PTR(SObject) aObj (anAppStudy->studyDS()->FindObjectID(item->text(2).latin1()));
465
466   SUPERV_Graph aDataFlow;
467   QString aIORName;
468
469   _PTR(GenericAttribute) anAttr;
470   if (aObj->FindAttribute(anAttr, "AttributeIOR")) {
471     _PTR(AttributeIOR) anIOR ( anAttr );
472     aIORName = QString(anIOR->Value().c_str());
473     if (isContains(study, aIORName)) {
474       if (QMessageBox::warning(application()->desktop(), tr("WARNING"),
475                                tr("MSG_GRAPH_DISPLAYED").arg(""),
476                                QMessageBox::Yes, QMessageBox::No) == QMessageBox::No)
477         return;
478     }
479
480     //SUPERV_Graph aDataFlow = engine->getStreamGraph(anIOR->Value().c_str());
481     aDataFlow = engine->getGraph(anIOR->Value().c_str());
482     if (SUPERV_isNull(aDataFlow)) {
483       QMessageBox::warning(0, tr("ERROR"), tr("MSG_ACCESS_BAD_IOR"));
484       return;
485     }
486
487     /* ASV: 20.10.04: fix for 6896
488     if (aDataFlow->IsStreamGraph()) {
489       SUPERV_StreamGraph aDataFlowStream = aDataFlow->ToStreamGraph();
490       if (SUPERV_isNull(aDataFlowStream)) {
491         QMessageBox::warning(0, tr("ERROR"), tr("MSG_ACCESS_BAD_IOR"));
492         return;
493       }
494       aDataFlow = aDataFlowStream;
495     }
496     */
497   }
498
499   SUPERVGraph_ViewFrame* aViewFrame;
500   if ( !myInitialViewFrame ) {
501     // first case : create a ViewFrame object
502     aViewFrame = dynamic_cast<SUPERVGraph_ViewFrame*>( createGraph() );
503   }
504   else {
505     // second case : get empty initial view frame as new ViewFrame object
506     aViewFrame = myInitialViewFrame;
507     // mkr : IPAL12991 -->
508     SUPERVGraph_View* view = myInitialViewFrame->getViewWidget();
509     if (view)
510       unregisterGraph(dynamic_cast<SUPERVGUI_Main*>(view));
511     // mkr : IPAL12991 <--
512     // mkr : PAL8237 : remove first "gag" Main from children
513     // srn: commented as it cases on application exit "X Windows error"
514     //aViewFrame->removeChild( aViewFrame->queryList("SUPERVGUI_Main")->first() );
515     delete view;
516   }
517
518   if ( aViewFrame ) {
519     main = new SUPERVGUI_Main( aViewFrame, application()->desktop(), aDataFlow );
520     registerGraph( aIORName, main );
521     aViewFrame->show();
522   }
523
524   if ( myInitialViewFrame ) {
525     myInitialViewFrame = 0;
526     myIVFBackgroundColor = QColor();
527   }
528 }
529
530
531 void SUPERVGUI::renameDataflow() {
532   SALOME_ListIO aList;
533   aList.Clear();
534   (( SalomeApp_Application* )application())->selectionMgr()->selectedObjects( aList );
535
536   SALOME_ListIteratorOfListIO It( aList );
537   for ( ; It.More(); It.Next() ) {
538     Handle(SALOME_InteractiveObject) IObject = It.Value();
539
540     _PTR(Study) aStudy = (( SalomeApp_Study* )study)->studyDS();
541     _PTR(SObject) obj ( aStudy->FindObjectID( IObject->getEntry() ) );
542     _PTR(GenericAttribute) anAttr;
543     if ( obj ) {
544       if ( obj->FindAttribute(anAttr, "AttributeName") ) {
545         _PTR(AttributeName) aName ( anAttr );
546         QString nm = QString( aName->Value().c_str() );
547         bool ok;
548         nm = QInputDialog::getText( tr( "Rename" ), tr( "Enter new name:" ), QLineEdit::Normal,
549                                     nm, &ok, application()->desktop() );
550         if ( ok && !nm.isEmpty() ) {
551           // sak : 24.11.04 : fix for PAL6898 : if rename fails (study locked),
552           // a message box is displayed, and cursor is "wait cursor".  We think that "wait cursor"
553           // is not neccessary here, because the rename operation is fast.
554           //QApplication::setOverrideCursor( Qt::waitCursor );
555           //study->renameIObject( IObject, nm );
556
557           //--->
558           aName->SetValue( nm.latin1() );
559           //rename Interactive object
560           IObject->setName( ( char* )nm.latin1() );
561           //<---
562
563           updateObjBrowser();
564           //QApplication::restoreOverrideCursor();
565
566           // mkr : PAL7037 => rename engine of the graph (i.e. corresponding SUPERV_Graph) -->
567           if ( obj->FindAttribute(anAttr, "AttributeIOR") ) {
568             _PTR(AttributeIOR) anIOR ( anAttr );
569             SUPERV_Graph aDataFlow = engine->getGraph(anIOR->Value().c_str());
570             if ( !SUPERV_isNull(aDataFlow) ) {
571               if ( aDataFlow->IsStreamGraph() ) {
572                 SUPERV_StreamGraph aStreamDataFlow = aDataFlow->ToStreamGraph();
573                 if ( !SUPERV_isNull(aStreamDataFlow) )
574                   aStreamDataFlow->SetName( nm.latin1() );
575               }
576               else {
577                 aDataFlow->SetName( nm.latin1() );
578               }
579
580               // update "Save" icon and menu state, if dataflow is published
581               SUPERVGUI_Main::setModifiedFlag();  
582             }
583           }
584           // mkr : PAL7037 <--
585         }
586       }
587     }
588   }
589 }
590
591 void SUPERVGUI::exportDataflow() {
592     Trace("SUPERVGUI::exportDataflow")
593     if ( main==0 ) {
594       QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_EXPORT"));
595     }
596     else if ( SUPERV_isNull( main->getDataflow() ) ) { // should not normally happen..
597       QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_EXPORT"));
598     }
599     else {
600       QString f = SUIT_FileDlg::getFileName(application()->desktop(),
601                                             "",
602                                             "*.xml",
603                                             tr("TTL_EXPORT_DATAFLOW"),
604                                             false);
605       if ( !f.isEmpty() ) {
606
607         // asv : bug [VSR Bugs and Improvements in Supervisor] 1.8 : when exporting a file,
608         // a backup copy of an existing file must be created (in case Export fails..)
609         QString aBackupFile = SUPERVGUI::createBackupFile( f );
610
611         if ( main->getDataflow()->Export(f.latin1()) ) {
612           // mkr : PAL8110 : if we re-register graph with its xml-file name the "Supervisor Warning"
613           //       after object browser popup "Display" item will not appear, it's an error,
614           //       because of this dataflow is already displayed.
615           //unregisterGraph(main);
616           //registerGraph(f, main);
617
618           // remove a backup file if export was successfull
619           if ( !aBackupFile.isNull() && !aBackupFile.isEmpty() )
620             QFile::remove( aBackupFile );
621         }
622         else {
623           QMessageBox::warning(application()->desktop(), tr("ERROR"), tr("MSG_BAD_WRITING").arg(aBackupFile));
624         }
625       }
626     }
627 }
628
629 /**
630  *If a file with theOriginalFileName exists, then the function tries to create
631  * its backup copy of it (the_name + ".bakX", X = 0,1,2,..,99).  Returns backup file's name
632  * If a file with theOriginalFileName does not exist, or creation fails - Return empty string.
633  */
634 QString SUPERVGUI::createBackupFile( const QString& theOriginalFileName ) {
635   QString theBackupFileName("");
636   if ( QFile::exists( theOriginalFileName ) ) {
637     // 1. construct a backup file name
638     int i = 0;
639     do {
640       theBackupFileName = theOriginalFileName;
641       theBackupFileName += ".bak";
642       theBackupFileName += QString::number(i++);
643     }
644     while ( QFile::exists( theBackupFileName ) && i < 100 ); // max 99 backup files
645     // if *.bak99 exists -- it will be overwritten
646
647     // 2. copy the original file to theBackupFileName
648     QString cmd( "cp \"");
649     cmd += theOriginalFileName;
650     cmd += "\" \"";
651     cmd += theBackupFileName;
652     cmd += "\"";
653     bool res = system( cmd.latin1() );
654     if ( res )
655       theBackupFileName = QString("");
656   }
657   return theBackupFileName;
658 }
659
660 void SUPERVGUI::windows( QMap<int, int>& mappa ) const
661 {
662   mappa.insert( SalomeApp_Application::WT_ObjectBrowser, Qt::DockLeft );
663   mappa.insert( SalomeApp_Application::WT_PyConsole, Qt::DockBottom );
664   mappa.insert( SalomeApp_Application::WT_LogWindow, Qt::DockBottom );
665 }
666
667 void SUPERVGUI::newDataflow() {
668   createDataflow( New );
669 }
670
671 void SUPERVGUI::importDataflow() {
672   createDataflow( Import );
673 }
674
675 void SUPERVGUI::modifyDataflow() {
676   createDataflow( Modify );
677 }
678
679 bool SUPERVGUI::createDataflow( const NEW_DF_MODE mode, bool theInitialDF ) {
680   Trace("SUPERVGUI::createDataflow, mode = " << mode );
681
682   // asv : 27.01.05 : fix for PAL7823 : if the study is locked - warn the user and return.
683   _PTR(Study) aStudy = (( SalomeApp_Study* )study)->studyDS();
684   if ( aStudy->GetProperties()->IsLocked() ) {
685     QMessageBox::warning(application()->desktop(), tr("WRN_WARNING"), tr("WRN_STUDY_LOCKED"));
686     return false;
687   }
688
689   SUPERV::Graph_var aGraph;
690
691   QString f; // file name.  declared here because may be used below in error msg construction..
692   if ( mode == Import || mode == Modify ) { // 0. import or modify existing dataflow - select XML file
693     QString title = QString( "TLT_CREATE_DF_%1" ).arg( mode );
694     f = SUIT_FileDlg::getFileName( application()->desktop(), "", "*.xml", tr( title ), true );
695     if ( f.isEmpty() ) // pressed Cancel in file select dialog
696       return false;
697
698     // check if study already contains a graph imported from the same file
699     if ( isContains( study, f ) ) {
700       if ( QMessageBox::warning( application()->desktop(), tr("WARNING"), tr("MSG_GRAPH_DISPLAYED").arg(f),
701                                  QMessageBox::Yes, QMessageBox::No) == QMessageBox::No )
702         return false;
703     }
704
705     // 1. create a graph
706     aGraph = ( mode == Import ) ? engine->StreamGraphE( f ) : engine->StreamGraph( f );
707   }
708   else
709     aGraph = engine->StreamGraph( MAIN_NEW );
710
711   if ( CORBA::is_nil( aGraph ) ) {
712     QString msg( mode == New ? tr("MSG_CANT_CREATE_DF") : tr("MSG_BAD_FILE").arg(f) );
713     SUIT_MessageBox::warn1( application()->desktop(), tr("ERROR"), tr(msg), tr("BUT_OK") );
714     return false;
715   }
716
717   SUPERVGraph_ViewFrame* aViewFrame;
718   if ( theInitialDF || !myInitialViewFrame ) {
719     // 2. create a ViewFrame object
720     aViewFrame = dynamic_cast<SUPERVGraph_ViewFrame*>( createGraph() );
721   }
722   else {
723     // 2. get empty initial view frame as new ViewFrame object
724     aViewFrame = myInitialViewFrame;
725     // mkr : IPAL12991 -->
726     if ( myInitialViewFrame ) {
727       SUPERVGraph_View* view = myInitialViewFrame->getViewWidget();
728       if (view)
729         unregisterGraph(dynamic_cast<SUPERVGUI_Main*>(view));
730     }
731     // mkr : IPAL12991 <--
732     // mkr : PAL8237 : remove first "gag" Main from children
733     // srn: commented as it cases on application exit "X Windows error"
734     //aViewFrame->removeChild( aViewFrame->queryList("SUPERVGUI_Main")->first() );
735   }
736
737   if ( aViewFrame ) {
738
739     // 3. bind Graph and ViewFrame == create SUPERVGUI_Main object
740     main = new SUPERVGUI_Main( aViewFrame, application()->desktop(), aGraph );
741     if ( mode == New ) {
742       if ( !theInitialDF )      
743         main->addNode();
744       else
745         myInitialViewFrame = aViewFrame;
746     }
747     // mkr : IPAL11550 : register graph not depend on creation mode
748     registerGraph( f, main );
749     main->resizeView( new QResizeEvent( aViewFrame->size(), aViewFrame->size() ) );
750     aViewFrame->show();
751     QFileInfo inf( f );
752     if( !f.isEmpty() )
753       aViewFrame->setCaption( inf.fileName() );
754   }
755
756   if ( !theInitialDF ) {
757     myInitialViewFrame = 0;
758     myIVFBackgroundColor = QColor();
759   }
760
761   return true;
762 }
763
764 void SUPERVGUI::reloadDataflow() {
765   Trace("SUPERVGUI::reloadDataflow");
766   if ( main )
767     main->sync();
768   else
769     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_RELOAD"));
770 }
771
772 void SUPERVGUI::runDataflow() {
773   Trace("SUPERVGUI::runDataflow");
774   if ( main )
775     main->run( /*andSuspend=*/false );
776   else
777     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_RUN"));
778 }
779
780 void SUPERVGUI::stepByStep() {
781   Trace("SUPERVGUI::stepByStep");
782   if ( main )
783     main->run( /*andSuspend=*/true );
784   else
785     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_RUN"));
786 }
787
788 void SUPERVGUI::killDataflow() {
789   Trace("SUPERVGUI::killDataflow");
790   if ( main )
791     main->kill();
792   else
793     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_KILL"));
794 }
795
796 void SUPERVGUI::suspendResumeDataflow() {
797   Trace("SUPERVGUI::suspendResumeDataflow");
798   if ( main )
799     main->suspendResume();
800   else
801     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_SUSPEND"));
802 }
803
804 void SUPERVGUI::showComponents() {
805   Trace("SUPERVGUI::showComponents");
806   if ( main ) {
807     if ( main->isEditable() )
808       main->addNode();
809     else
810       QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOTEDITABLE"));
811   }
812   else
813     QMessageBox::warning(application()->desktop(), tr("WARNING"), tr("MSG_NOWINDOW_TO_ADD"));
814
815 }
816
817
818 /*bool SUPERVGUI::CustomPopup(QPopupMenu* popup, const QString& theContext, const QString& theParent, const QString& theObject) {
819   Trace("SUPERVGUI::customPopup");
820   Supervision.init();
821   if(popup->count() > 3) {
822     // Temporary code: is to be deleted soon
823     popup->removeItem(QAD_Display_Popup_ID);
824     popup->removeItem(QAD_DisplayOnly_Popup_ID);
825     popup->removeItem(QAD_Erase_Popup_ID);
826     int id = popup->idAt(popup->count() - 1);
827     if (id < 0 && id != -1) popup->removeItem(id); // separator
828     // Temporary code end
829   }
830
831   SALOME_ListIO aList;
832   aList.Clear();
833   (( SalomeApp_Application* )application())->selectionMgr()->selectedObjects( aList );
834   if ( aList.Extent() == 0 ) return false;
835
836   if ( aList.Extent() == 1 ) {
837     Handle(SALOME_InteractiveObject) anIObj = aList.First();
838
839     // insert SUPERV-specific popup items here
840
841     bool isDataflow, ownObj;
842     whatIsSelected(anIObj, ownObj, isDataflow);
843
844     if (isDataflow) {
845       popup->insertItem(tr( "MSG_RENAME" ), this, SLOT(renameDataflow()));
846       popup->insertItem("Display", this, SLOT(displayDataflow()));
847       popup->insertSeparator();
848     }
849     if (ownObj)
850       popup->insertItem(tr("MSG_DELETE"), this, SLOT(deleteObject()));
851   }
852
853   if ( aList.Extent() > 1 ) {
854     int aIObjCount = 0;
855     SALOME_ListIteratorOfListIO It_forCheckOwner( aList );
856     for(;It_forCheckOwner.More();It_forCheckOwner.Next()) {
857       Handle(SALOME_InteractiveObject) anIObj = It_forCheckOwner.Value();
858       bool aIsOwner, aIsDataflow;
859       whatIsSelected(anIObj, aIsOwner, aIsDataflow);
860
861       if (aIsOwner) aIObjCount++;
862     }
863     if ( aIObjCount == aList.Extent() )  //all selected objects belong to Supervision
864       popup->insertItem(tr("MSG_DELETE"), this, SLOT(deleteObject()));
865   }
866
867   return(true);
868   }*/
869
870
871
872 /** Returns:
873     theIsOwner = true if Selected object belongs to Supervision.
874     theIsDataflow = true if Selected object is Dataflow
875 */
876 void SUPERVGUI::whatIsSelected(const _PTR(SObject)& theObj, bool& theIsOwner, bool& theIsDataflow) {
877   theIsOwner = false;
878   theIsDataflow = false;
879
880   if ( theObj ) {
881     _PTR(SComponent) comp ( theObj->GetFatherComponent() );
882     if ( comp ) {
883       _PTR(GenericAttribute) anAttr;
884       if (comp->FindAttribute(anAttr, "AttributeName")) {
885         _PTR(AttributeName) aName ( anAttr );
886         QString compName(aName->Value().c_str());
887         if ( compName.compare( moduleName() ) == 0 ) {
888           _PTR(GenericAttribute) anAttr;
889           if (theObj->FindAttribute(anAttr, "AttributeIOR")) {
890             _PTR(AttributeIOR) anIOR ( anAttr );
891             SUPERV_Graph aDataFlow = engine->getGraph(anIOR->Value().c_str());
892             if (!SUPERV_isNull(aDataFlow)) {
893               if (aDataFlow->IsStreamGraph()) {
894                 if (!SUPERV_isNull(aDataFlow->ToStreamGraph()))
895                   theIsDataflow = true;
896               }
897               else
898                 theIsDataflow = true;
899             }
900           }
901           CORBA::String_var anObjectID = theObj->GetID().c_str();
902           CORBA::String_var aComponentID = comp->GetID().c_str();
903           if (strcmp(anObjectID, aComponentID))
904             theIsOwner = true;
905         }
906       }
907     }
908   }
909 }
910
911 void SUPERVGUI::deleteObject() {
912   SALOME_ListIO aList;
913   aList.Clear();
914   (( SalomeApp_Application* )application())->selectionMgr()->selectedObjects( aList, QString::null, false );
915   if ( aList.Extent() == 0 ) return;
916
917   // sak : 24.11.04 : fix for PAL6899 : if the study is locked - warn the user and return.
918   _PTR(Study) aStudy = (( SalomeApp_Study* )study)->studyDS();
919   if ( aStudy->GetProperties()->IsLocked() ) {
920     QMessageBox::warning(application()->desktop(), tr("WRN_WARNING"), tr("WRN_STUDY_LOCKED"));
921     return;
922   }
923
924   // sak : 24.11.04 : fix for PAL6901 : Incorrect deletion of the objects : pressing ESC button
925   // emitted "YES" button click, now it is corrected, and treated as "NO" button click.
926   if (QMessageBox::warning(application()->desktop(),
927                            tr("WARNING"),
928                            tr("MSG_ASK_DELETE"),
929                            QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
930     return;
931
932   SALOME_ListIteratorOfListIO It( aList );
933   for(;It.More();It.Next()) {
934     Handle(SALOME_InteractiveObject) anIObj = It.Value();
935     //bool aIsOwner, aIsDataflow;
936     //whatIsSelected(anIObj, aIsOwner, aIsDataflow);
937
938     _PTR(SObject) aObj ( aStudy->FindObjectID( anIObj->getEntry() ) );
939     if ( aObj ) {
940       SUIT_Operation* op = new SalomeApp_ImportOperation( application() );
941       _PTR(StudyBuilder) aBuilder ( aStudy->NewBuilder() );
942       op->start();
943       aBuilder->RemoveObjectWithChildren( aObj );
944       op->commit();
945     }
946   }
947   (( SalomeApp_Application* )application())->selectionMgr()->clearSelected();
948   updateObjBrowser();
949 }
950
951 void SUPERVGUI::OnGUIEvent()
952 {
953   const QObject* obj = sender();
954   if ( !obj || !obj->inherits( "QAction" ) )
955     return;
956   int id = actionId((QAction*)obj);
957   if ( id != -1 )
958     OnGUIEvent( id );
959 }
960
961 bool SUPERVGUI::OnGUIEvent(int command) {
962   switch (command) {
963   case 301:
964     importDataflow();
965     return(false);
966
967   case 302:
968     exportDataflow();
969     return(false);
970
971   case 303:
972     newDataflow();
973     return(false);
974
975   case 304:
976     modifyDataflow();
977     return(false);
978
979   case 305:
980     reloadDataflow();
981     return(false);
982
983   case 306:
984     runDataflow();
985     return(false);
986
987   case 307:
988     killDataflow();
989     return(false);
990
991   case 308:
992     suspendResumeDataflow();
993     return(false);
994
995   case 309:
996     showComponents();
997     return(false);
998
999   case 310:
1000     stepByStep();
1001     return(false);
1002
1003   case 311:
1004     renameDataflow();
1005     return(false);
1006
1007   case 312:
1008     displayDataflow();
1009     return(false);
1010
1011   case 313:
1012     deleteObject();
1013     return(false);
1014
1015   default:
1016     QMessageBox::warning(application()->desktop(), "Supervision Error", "Unknown Command From Salome");
1017     return(false);
1018   }
1019 }
1020
1021 /*bool SUPERVGUI::SetSettings() {
1022   Trace("SUPERVGUI::SetSettings");
1023   Supervision.init();
1024   return(true);
1025   }*/
1026
1027 /*void SUPERVGUI::DefinePopup(QString& theContext, QString& theParent, QString& theObject) {
1028   theObject  = "";
1029   theContext = "";
1030   }*/
1031
1032 bool SUPERVGUI::ActiveStudyChanged() {
1033   Trace("SUPERVGUI::activeStudyChanged");
1034   study = application()->activeStudy();
1035   return true;
1036 }
1037
1038 /*void SUPERVGUI::SupportedViewType (int* buffer, int bufferSize)
1039 {
1040   if (!buffer || !bufferSize) return;
1041   buffer[0] = (int)VIEW_GRAPHSUPERV;
1042 }*/
1043
1044 void SUPERVGUI::fillInterfaceNameMap() {
1045   //fill map: interface_name <-> component_name for all
1046   //interfaces of all loaded components, it is necessary
1047   //for correct adding factory nodes from AddComponent,
1048   //SubComponent, MulComponent, etc. components.
1049   myInterfaceNameMap.clear();
1050
1051   //get naming service
1052   SALOME_NamingService* namingService = (( SalomeApp_Application* )application())->namingService();
1053   //get module catalog
1054   CORBA::Object_ptr obj  = namingService->Resolve("/Kernel/ModulCatalog");
1055   SALOME_ModuleCatalog::ModuleCatalog_var* aModuleCatalog = new SALOME_ModuleCatalog::ModuleCatalog_var;
1056   *aModuleCatalog = SALOME_ModuleCatalog::ModuleCatalog::_narrow(obj);
1057   if (!CORBA::is_nil(*aModuleCatalog)) {
1058     //get component list
1059     SALOME_ModuleCatalog::ListOfComponents_var aCompList = (*aModuleCatalog)->GetComponentList();
1060     for (int ind1 = 0; ind1 < aCompList->length(); ind1++) {
1061       //get component
1062       SALOME_ModuleCatalog::Acomponent_ptr aComponent = (*aModuleCatalog)->GetComponent(aCompList[ind1]);
1063       if ( aComponent != NULL ) {
1064         // mkr : PAL13135
1065         myInterfaceNameMap.insert(QString(aComponent->componentusername()), QString(aComponent->componentname()));
1066       }
1067     }
1068   }
1069 }
1070
1071 QMap<QString, QString> SUPERVGUI::getInterfaceNameMap() const {
1072   return myInterfaceNameMap;
1073 }
1074
1075 bool SUPERVGUI::updateDataFlowSOName( SUPERV::Graph_ptr theDataflow ) {
1076   if ( !SUPERV_isNull(theDataflow) ) {
1077     _PTR(Study) aStudy = (( SalomeApp_Study* )study)->studyDS();
1078     _PTR(SObject) aSO ( aStudy->FindObjectIOR( theDataflow->getIOR() ) );
1079
1080     _PTR(GenericAttribute) anAttr;
1081     if ( aSO ) // i.e. if theDataflow is in study
1082       if ( aSO->FindAttribute(anAttr, "AttributeName") ) {
1083         _PTR(AttributeName) aName ( anAttr );
1084         aName->SetValue( theDataflow->Name() );
1085         updateObjBrowser();
1086         return true;
1087       }    
1088   }
1089   return false;
1090 }