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