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