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