Salome HOME
Merge from BR_V5_DEV 17Feb09
[samples/light.git] / src / LIGHTGUI / LIGHTGUI.cxx
1 //  Copyright (C) 2005-2008  OPEN CASCADE
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // LIGHT : sample (no-corba-engine) SALOME module
20 // File   : LIGHTGUI.cxx
21 // Author : Julia DOROVSKIKH
22 //
23 #include "LIGHTGUI.h"
24
25 #include "LIGHTGUI_Selection.h"
26 #include "LIGHTGUI_DataModel.h"
27 #include "LightApp_DataOwner.h"
28 #include "LIGHTGUI_TextPrs.hxx"
29
30 #include <SUIT_MessageBox.h>
31 #include <SUIT_Desktop.h>
32 #include <LightApp_Application.h>
33 #include <LightApp_SelectionMgr.h>
34 #include <LightApp_Selection.h>
35 #include <OCCViewer_ViewManager.h>
36 #include <SOCC_ViewModel.h>
37 #include <SOCC_Prs.h>
38
39 #include <QInputDialog>
40 #include <QStringList>
41 #include <QMenu>
42 #include <QIcon>
43 #include <QString>
44
45 /*!
46   \class LIGHTGUI
47   \brief Implementation of the sample light (no-CORBA-engine) 
48          SALOME module.
49 */
50
51 /*!
52   \brief Constructor. Sets the default name for the module.
53 */
54 LIGHTGUI::LIGHTGUI()
55 : LightApp_Module( "LIGHTGUI" )
56 {
57 }
58
59 /*!
60   \brief Destructor.
61 */
62 LIGHTGUI::~LIGHTGUI()
63 {
64 }
65
66 /*!
67   \brief Initialize module. Creates menus, prepares context menu, etc.
68   \param app application instance
69 */
70 void LIGHTGUI::initialize( CAM_Application* app )
71 {
72   LightApp_Module::initialize( app );
73
74   SUIT_Desktop* desk = application()->desktop();
75
76   createAction( lgLoadFile, tr( "TOP_LOAD_FILE" ), QIcon(), tr( "MEN_LOAD_FILE" ),
77                 tr( "STB_LOAD_FILE" ), 0, desk, false, this, SLOT( onLoadFile() ) );
78   createAction( lgDisplayLine, tr( "TOP_DISPLAY_LINE" ), QIcon(), tr( "MEN_DISPLAY_LINE" ),
79                 tr( "STB_DISPLAY_LINE" ), 0, desk, false, this, SLOT( onDisplayLine() ) );
80   createAction( lgEraseLine, tr( "TOP_ERASE_LINE" ), QIcon(), tr( "MEN_ERASE_LINE" ),
81                 tr( "STB_ERASE_LINE" ), 0, desk, false, this, SLOT( onEraseLine() ) );
82   createAction( lgSaveFile, tr( "TOP_SAVE_FILE" ), QIcon(), tr( "MEN_SAVE_FILE" ),
83                 tr( "STB_SAVE_FILE" ), 0, desk, false, this, SLOT( onSaveFile() ) );
84   createAction( lgEditLine, tr( "TOP_EDIT_LINE" ), QIcon(), tr( "MEN_EDIT_LINE" ),
85                 tr( "STB_EDIT_LINE" ), 0, desk, false, this, SLOT( onEditLine() ) );
86   createAction( lgAddLine,  tr( "TOP_ADD_LINE" ),  QIcon(), tr( "MEN_ADD_LINE" ),
87                 tr( "STB_ADD_LINE" ),  0, desk, false, this, SLOT( onAddLine() ) );
88   createAction( lgDelLine,  tr( "TOP_DEL_LINE" ),  QIcon(), tr( "MEN_DEL_LINE" ),
89                 tr( "STB_DEL_LINE" ),  0, desk, false, this, SLOT( onDelLine() ) );
90   createAction( lgClear,    tr( "TOP_CLEAR_ALL" ), QIcon(), tr( "MEN_CLEAR_ALL" ),
91                 tr( "STB_CLEAR_ALL" ), 0, desk, false, this, SLOT( onClear() ) );
92
93   int aFileMnu = createMenu( tr( "MEN_FILE" ), -1, -1 );
94   createMenu( separator(), aFileMnu, -1, 10 );
95   createMenu( lgLoadFile,  aFileMnu, 10 );
96   createMenu( lgSaveFile,  aFileMnu, 10 );
97
98   int aLightMnu = createMenu( tr( "MEN_LIGHT" ), -1, -1, 50 );
99   createMenu( lgAddLine,      aLightMnu, 10 );
100   createMenu( lgEditLine,     aLightMnu, 10 );
101   createMenu( lgDelLine,      aLightMnu, 10 );
102   createMenu( separator(),    aLightMnu, -1, 10 );
103   createMenu( lgClear,        aLightMnu, 10 );
104
105   QString rule = "(client='ObjectBrowser' or client='OCCViewer') and selcount=1 and type='TextLine' and !empty";
106
107   popupMgr()->insert ( action( lgDisplayLine ), -1, 0 );
108   popupMgr()->setRule( action( lgDisplayLine ), rule + " and !visible"  );
109
110   popupMgr()->insert ( action( lgEraseLine ), -1, 0 );
111   popupMgr()->setRule( action( lgEraseLine ), rule + " and activeView='OCCViewer' and visible"  );
112
113   rule = "client='ObjectBrowser' and selcount=1 and type='TextLine'";
114
115   popupMgr()->insert ( action( lgEditLine ), -1, 0 );
116   popupMgr()->setRule( action( lgEditLine ), rule  );
117
118   popupMgr()->insert ( action( lgAddLine ),  -1, 0 );
119   popupMgr()->setRule( action( lgAddLine ),  rule );
120
121   popupMgr()->insert ( separator(),          -1, 0 );
122
123   popupMgr()->insert ( action( lgDelLine ),  -1, 0 );
124   popupMgr()->setRule( action( lgDelLine ),  rule );
125
126   rule = "client='ObjectBrowser'";
127
128   popupMgr()->insert ( action( lgClear ),    -1, 0 );
129   popupMgr()->setRule( action( lgClear ),    rule );
130 }
131
132 /*!
133   \brief Get list of compliant dockable GUI elements
134   \param m map to be filled in ("type":"default_position")
135 */
136 void LIGHTGUI::windows( QMap<int, int>& m ) const
137 {
138   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
139   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
140 }
141
142 /*!
143   \brief Create custom popup menu selection object.
144   \return new selected object
145 */
146 LightApp_Selection* LIGHTGUI::createSelection() const
147 {
148   return new LIGHTGUI_Selection();
149 }
150
151 /*!
152   \brief Create data model.
153   \return module specific data model
154 */
155 CAM_DataModel* LIGHTGUI::createDataModel()
156 {
157   return new LIGHTGUI_DataModel( this );
158 }
159
160 /*!
161   \brief Get the identifier of the currently selected object.
162   \return ID of the currently selected line or -1 if not appropriate
163   object (or multiple objects) is selected.
164 */
165 int LIGHTGUI::selectedLine()
166 {
167   int id = -1; // bad value
168   
169   // Look for selected lines
170   LightApp_Application* app = getApp();
171   LightApp_SelectionMgr* mgr = app ? app->selectionMgr() : 0;
172   if ( mgr ) {
173     SUIT_DataOwnerPtrList anOwnersList;
174     mgr->selected( anOwnersList );
175     
176     // Get index of the single selected line
177     if ( anOwnersList.size() == 1 ) {
178       const LightApp_DataOwner* owner =
179         dynamic_cast<const LightApp_DataOwner*>( anOwnersList[0].get() );
180       QString anEntry = owner->entry();
181       id = LIGHTGUI_DataModel::id( anEntry );
182     }
183   }
184   return id;
185 }
186
187 /*!
188   \brief Display the object with the specified identifier.
189   \param id object ID
190   \param allViewers if \c true the object is displayed in all existing viewers
191   (OCC viewers are supported only)
192   \param upd if \c true, update the viewer(s)
193 */
194 void LIGHTGUI::displayLine( const int id, const bool allViewers, const bool upd )
195 {
196   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
197   if ( dm && id > 0 ) {
198     ViewManagerList viewers;
199     if ( allViewers )
200       getApp()->viewManagers( "OCCViewer", viewers );
201     else
202       viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
203     
204     for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
205       OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
206       if ( !aMgr ) continue;
207       SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();  
208       if ( !aViewer ) continue;
209       QString aLine = dm->getLineText( id );
210       QString entry = LIGHTGUI_DataModel::entry( id );
211       SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
212       if ( prs ) {
213         double aX = 0, aY = dm->lineNb( id ) * LIGHTGUI_TextPrs::TextSize(), aZ = 0;
214         aViewer->Erase( prs, true );
215         Handle(LIGHTGUI_TextPrs) aPrs = new LIGHTGUI_TextPrs( aLine.toLatin1(), gp_Pnt( aX, aY, aZ ) );
216         aPrs->SetOwner( new SALOME_InteractiveObject( entry.toLatin1(), "" ) );
217         prs->Clear();
218         prs->AddObject( aPrs );
219         aViewer->Display( prs );
220         if ( upd )
221           aViewer->Repaint();
222       }
223     }
224   }
225 }
226
227 /*!
228   \brief Erase the object with the specified identifier.
229   \param id object ID
230   \param allViewers if \c true the object is erased in all existing viewers
231   (OCC viewers are supported only)
232   \param upd if \c true, update the viewer(s)
233 */
234 void LIGHTGUI::eraseLine( const int id, const bool allViewers, const bool upd )
235 {
236   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
237   if ( dm && id > 0 ) {
238     ViewManagerList viewers;
239     if ( allViewers )
240       getApp()->viewManagers( "OCCViewer", viewers );
241     else
242       viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
243     
244     for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
245       OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
246       if ( !aMgr ) continue;
247       SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();  
248       if ( !aViewer ) continue;
249       QString entry = LIGHTGUI_DataModel::entry( id );
250       SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
251       if ( prs ) {
252         aViewer->Erase( prs, false );
253         if ( upd )
254           aViewer->Repaint();
255       }
256     }
257   }
258 }
259
260 /*!
261   \brief Update the object presentation.
262   \param id object ID
263   \param allViewers if \c true the object is updated in all existing viewers
264   (OCC viewers are supported only)
265   \param upd if \c true, update the viewer(s)
266 */
267 void LIGHTGUI::updateLine( const int id, const bool allViewers, const bool upd )
268 {
269   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
270   if ( dm && id > 0 ) {
271     ViewManagerList viewers;
272     if ( allViewers )
273       getApp()->viewManagers( "OCCViewer", viewers );
274     else
275       viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
276     
277     for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
278       OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
279       if ( !aMgr ) continue;
280       SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();  
281       if ( !aViewer ) continue;
282       QString aLine = dm->getLineText( id );
283       QString entry = LIGHTGUI_DataModel::entry( id );
284       if ( aViewer->isVisible( new SALOME_InteractiveObject( entry.toLatin1(), "" ) ) ) {
285         SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
286         if ( prs ) {
287           if ( aLine.isEmpty() ) {
288             aViewer->Erase( prs, false );
289           }
290           else {
291             double aX = 0, aY = dm->lineNb( id ) * LIGHTGUI_TextPrs::TextSize(), aZ = 0;
292             aViewer->Erase( prs, true );
293             Handle(LIGHTGUI_TextPrs) aPrs = new LIGHTGUI_TextPrs( aLine.toLatin1(), gp_Pnt( aX, aY, aZ ) );
294             aPrs->SetOwner( new SALOME_InteractiveObject( entry.toLatin1(), "" ) );
295             prs->Clear();
296             prs->AddObject( aPrs );
297             aViewer->Display( prs );
298           }
299           if ( upd )
300             aViewer->Repaint();
301         }
302       }
303     }
304   }
305 }
306
307 /*!
308   \brief Erase objects.
309   \param l objects IDs list
310   \param allViewers if \c true the objects are erased in all existing viewers
311   (OCC viewers are supported only)
312 */
313 void LIGHTGUI::eraseLines( const QList<int>& l, const bool allViewers )
314 {
315   for ( QList<int>::const_iterator it = l.begin(); it != l.end(); ++it )
316     eraseLine( *it, allViewers );
317 }
318
319 /*!
320   \brief Update objects presentations.
321   \param l objects IDs list
322   \param allViewers if \c true the objects are updated in all existing viewers
323   (OCC viewers are supported only)
324 */
325 void LIGHTGUI::updateLines( const QList<int>& l, const bool allViewers )
326 {
327   for ( QList<int>::const_iterator it = l.begin(); it != l.end(); ++it )
328     updateLine( *it, allViewers );
329 }
330
331 /*!
332   \brief Activate module.
333   \param study current study
334   \return \c true if activaion is done successfully or 0 to prevent
335   activation on error
336 */
337 bool LIGHTGUI::activateModule( SUIT_Study* study )
338 {
339   bool isDone = LightApp_Module::activateModule( study );
340   if ( !isDone ) return false;
341
342   setMenuShown( true );
343
344   return isDone;
345 }
346
347 /*!
348   \brief Deactivate module.
349   \param study current study
350   \return \c true if deactivaion is done successfully or 0 to prevent
351   deactivation on error
352 */
353 bool LIGHTGUI::deactivateModule( SUIT_Study* study )
354 {
355   // hide menus
356   setMenuShown( false );
357
358   return LightApp_Module::deactivateModule( study );
359 }
360
361 /*!
362   \brief Called when "load text file" action is activated.
363 */
364 void LIGHTGUI::onLoadFile()
365 {
366   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
367   if ( !dm ) return;
368
369   QStringList filtersList;
370   filtersList.append( tr( "LIGHTGUI_MEN_TXT_FILES" ) );
371   filtersList.append( tr( "LIGHTGUI_MEN_ALL_FILES" ) );
372
373   // Select a file to be loaded
374   QString aFileName = getApp()->getFileName( true, QString(), filtersList.join( ";;" ), tr( "LIGHTGUI_MEN_LOAD" ), 0 );
375   if ( !aFileName.isEmpty() ) {
376     // Load the file
377     QList<int> l = dm->getIds();
378     if ( dm->loadFile( aFileName ) ) {
379       eraseLines( l, true );
380       updateObjBrowser( true );
381     } 
382     else {
383       SUIT_MessageBox::warning ( application()->desktop(),
384                                  tr( "WRN_WARNING" ),
385                                  tr( "WRN_LOAD_FAILED" ) );
386       }
387   }
388 }
389
390 /*!
391   \brief Called when "save text file" action is activated.
392 */
393 void LIGHTGUI::onSaveFile()
394 {
395   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
396   if ( !dm ) return;
397
398   QStringList filtersList;
399   filtersList.append( tr( "LIGHTGUI_MEN_TXT_FILES" ) );
400   filtersList.append( tr( "LIGHTGUI_MEN_ALL_FILES" ) );
401
402   // Select a file name to dump the lines into
403   QString aFileName = getApp()->getFileName( false, dm->fileName(), filtersList.join( ";;" ), tr( "LIGHTGUI_MEN_DUMP" ), 0 );
404   if ( !aFileName.isEmpty() ) {
405     // Dump the file
406     if ( !dm->dumpFile( aFileName ) ) {
407       SUIT_MessageBox::warning ( application()->desktop(),
408                                  tr( "WRN_WARNING" ),
409                                  tr( "WRN_DUMP_FAILED" ) );
410       }
411   }
412 }
413
414 /*!
415   \brief Called when "display selected line" action is activated.
416 */
417 void LIGHTGUI::onDisplayLine()
418 {
419   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
420   if ( !dm ) return;
421
422   // Define position
423   int id = selectedLine();
424   QString aLine = dm->getLineText( id );
425   
426   // Check, that position is defined
427   if ( id == -1 || aLine.isEmpty() ) {
428     SUIT_MessageBox::warning ( application()->desktop(),
429                                tr( "WRN_WARNING" ),
430                                tr( "WRN_SELECT_LINE" ) );
431     return;
432   }
433   displayLine( id );
434 }
435
436 /*!
437   \brief Called when "erase selected line" action is activated.
438 */
439 void LIGHTGUI::onEraseLine()
440 {
441   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
442   if ( !dm ) return;
443
444   // Define position
445   int id = selectedLine();
446   QString aLine = dm->getLineText( id );
447   
448   // Check, that position is defined
449   if ( id == -1 || aLine.isEmpty() ) {
450     SUIT_MessageBox::warning ( application()->desktop(),
451                                tr( "WRN_WARNING" ),
452                                tr( "WRN_SELECT_LINE" ) );
453     return;
454   }
455   eraseLine( id );
456 }
457
458 /*!
459   \brief Called when "edit selected line" action is activated.
460 */
461 void LIGHTGUI::onEditLine()
462 {
463   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
464   if ( !dm ) return;
465
466   // Define position
467   int id = selectedLine();
468   
469   // Check, that position is defined
470   if ( id == -1 ) {
471     SUIT_MessageBox::warning ( application()->desktop(),
472                                tr( "WRN_WARNING" ),
473                                tr( "WRN_SELECT_LINE" ) );
474     return;
475   }
476
477   // Get new text
478   bool isOk;
479   QString aText = QInputDialog::getText( application()->desktop(),
480                                          tr( "LIGHTGUI_EDIT_LINE" ),
481                                          QString(),
482                                          QLineEdit::Normal,
483                                          dm->getLineText( id ),
484                                          &isOk );
485   if ( !isOk ) return;
486   
487   // try to change a text of the selected line
488   
489   isOk = dm->setLineText( id, aText );
490
491   if ( isOk ) {
492     updateLine( id, true );
493     updateObjBrowser( true );
494   } 
495   else {
496     SUIT_MessageBox::warning ( application()->desktop(),
497                                tr( "WRN_WARNING" ),
498                                tr( "WRN_EDIT_FAILED" ) );
499   }
500 }
501
502 /*!
503   \brief Called when "insert new line" action is activated.
504 */
505 void LIGHTGUI::onAddLine()
506 {
507   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
508   if ( !dm ) return;
509
510   // Define position
511   int id = selectedLine();
512   
513   // Get new text
514   bool isOk;
515   QString aText = QInputDialog::getText( getApp()->desktop(),
516                                          tr( "LIGHTGUI_ADD_LINE" ),
517                                          QString(),
518                                          QLineEdit::Normal,
519                                          QString(),
520                                          &isOk );
521   if ( !isOk ) return;
522
523   QList<int> l = dm->getIds();
524
525   // try to insert/add text line
526   isOk = dm->insertLineBefore( id, aText );
527
528   if ( isOk ) {
529     updateLines( l, true );
530     updateObjBrowser( true );
531   } 
532   else {
533     SUIT_MessageBox::warning ( application()->desktop(),
534                                tr( "WRN_WARNING" ),
535                                tr( "WRN_ADD_FAILED" ) );
536   }
537 }
538
539 /*!
540   \brief Called when "delete selected line" action is activated.
541 */
542 void LIGHTGUI::onDelLine()
543 {
544   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
545   if ( !dm ) return;
546
547   // Define position
548   int id = selectedLine();
549   
550   // Check, that position is defined
551   if ( id == -1 ) {
552     SUIT_MessageBox::warning ( application()->desktop(),
553                                tr( "WRN_WARNING" ),
554                                tr( "WRN_SELECT_LINE" ) );
555     return;
556   }
557
558   QList<int> l = dm->getIds();
559
560   // try to delete line
561   bool isOk = dm->deleteTextLine( id );
562   if ( isOk ) {
563     updateLines( l, true );
564     updateObjBrowser( true );
565   } 
566   else {
567     SUIT_MessageBox::warning ( application()->desktop(),
568                                tr( "WRN_WARNING" ),
569                                tr( "WRN_DELETE_FAILED" ) );
570   }
571 }
572
573 /*!
574   \brief Called when "clear all contents" action is activated.
575 */
576 void LIGHTGUI::onClear()
577 {
578   LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
579   if ( !dm ) return;
580
581   QList<int> l = dm->getIds();
582   eraseLines( l, true );
583
584   dm->clearAll();
585
586   updateObjBrowser( true );
587 }
588
589 /*!
590   \fn CAM_Module* createModule();
591   \brief Export module instance (factory function).
592   \return new created instance of the module
593 */
594
595 #ifdef WNT
596 #define LIGHTGUI_EXPORT __declspec(dllexport)
597 #else   // WNT
598 #define LIGHTGUI_EXPORT
599 #endif  // WNT
600
601 extern "C" {
602   LIGHTGUI_EXPORT CAM_Module* createModule() {
603     return new LIGHTGUI();
604   }
605 }