1 // Copyright (C) 2005-2019 OPEN CASCADE
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, or (at your option) any later version.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : LIGHTGUI.cxx
20 // Author : Julia DOROVSKIKH
23 #include "LIGHTGUI_DataModel.h"
24 #include "LIGHTGUI_Selection.h"
25 #include "LIGHTGUI_TextPrs.h"
26 #include "LIGHT_version.h"
28 #include <LightApp_Application.h>
29 #include <LightApp_DataOwner.h>
30 #include <LightApp_SelectionMgr.h>
31 #include <OCCViewer_ViewManager.h>
32 #include <SUIT_Desktop.h>
33 #include <SUIT_MessageBox.h>
35 #include <SOCC_ViewModel.h>
38 #include <QInputDialog>
39 #include <QStringList>
43 \brief Implementation of the sample light (no-CORBA-engine) SALOME module.
45 This class represents a GUI module itself; the instance of the class is
46 created and exported by the static function, which is automatically invoked
47 from SALOME GUI; SALOME GUI application loads the module when user activates
48 it via the "Components" toolbar.
50 The LIGHTGUI class is responsible for the creation of the data model.
51 It dispatches user actions to the corresponding slots.
53 Method engineIOR() of this class returns empty string which means that this
54 module uses default persistence mechanism provided by the SALOME GUI via
55 the SalomeApp embedded engine (SalomeAppEngine class).
59 \brief Constructor. Sets the default name for the module.
62 : LightApp_Module( "LIGHTGUI" )
74 \brief Initialize module. Creates menus, prepares context menu, etc.
75 \param app application instance
77 void LIGHTGUI::initialize( CAM_Application* app )
79 LightApp_Module::initialize( app );
81 SUIT_Desktop* desk = application()->desktop();
83 createAction( lgLoadFile, tr( "TOP_LOAD_FILE" ), QIcon(), tr( "MEN_LOAD_FILE" ),
84 tr( "STB_LOAD_FILE" ), 0, desk, false, this, SLOT( onLoadFile() ) );
85 createAction( lgDisplayLine, tr( "TOP_DISPLAY_LINE" ), QIcon(), tr( "MEN_DISPLAY_LINE" ),
86 tr( "STB_DISPLAY_LINE" ), 0, desk, false, this, SLOT( onDisplayLine() ) );
87 createAction( lgEraseLine, tr( "TOP_ERASE_LINE" ), QIcon(), tr( "MEN_ERASE_LINE" ),
88 tr( "STB_ERASE_LINE" ), 0, desk, false, this, SLOT( onEraseLine() ) );
89 createAction( lgSaveFile, tr( "TOP_SAVE_FILE" ), QIcon(), tr( "MEN_SAVE_FILE" ),
90 tr( "STB_SAVE_FILE" ), 0, desk, false, this, SLOT( onSaveFile() ) );
91 createAction( lgEditLine, tr( "TOP_EDIT_LINE" ), QIcon(), tr( "MEN_EDIT_LINE" ),
92 tr( "STB_EDIT_LINE" ), 0, desk, false, this, SLOT( onEditLine() ) );
93 createAction( lgAddLine, tr( "TOP_ADD_LINE" ), QIcon(), tr( "MEN_ADD_LINE" ),
94 tr( "STB_ADD_LINE" ), 0, desk, false, this, SLOT( onAddLine() ) );
95 createAction( lgDelLine, tr( "TOP_DEL_LINE" ), QIcon(), tr( "MEN_DEL_LINE" ),
96 tr( "STB_DEL_LINE" ), 0, desk, false, this, SLOT( onDelLine() ) );
97 createAction( lgClear, tr( "TOP_CLEAR_ALL" ), QIcon(), tr( "MEN_CLEAR_ALL" ),
98 tr( "STB_CLEAR_ALL" ), 0, desk, false, this, SLOT( onClear() ) );
100 int aFileMnu = createMenu( tr( "MEN_FILE" ), -1, -1 );
101 createMenu( separator(), aFileMnu, -1, 10 );
102 createMenu( lgLoadFile, aFileMnu, 10 );
103 createMenu( lgSaveFile, aFileMnu, 10 );
105 int aLightMnu = createMenu( tr( "MEN_LIGHT" ), -1, -1, 50 );
106 createMenu( lgAddLine, aLightMnu, 10 );
107 createMenu( lgEditLine, aLightMnu, 10 );
108 createMenu( lgDelLine, aLightMnu, 10 );
109 createMenu( separator(), aLightMnu, -1, 10 );
110 createMenu( lgClear, aLightMnu, 10 );
112 QString rule = "(client='ObjectBrowser' or client='OCCViewer') and selcount=1 and type='TextLine' and !empty";
114 popupMgr()->insert ( action( lgDisplayLine ), -1, 0 );
115 popupMgr()->setRule( action( lgDisplayLine ), rule + " and !visible" );
117 popupMgr()->insert ( action( lgEraseLine ), -1, 0 );
118 popupMgr()->setRule( action( lgEraseLine ), rule + " and activeView='OCCViewer' and visible" );
120 rule = "client='ObjectBrowser' and selcount=1 and type='TextLine'";
122 popupMgr()->insert ( action( lgEditLine ), -1, 0 );
123 popupMgr()->setRule( action( lgEditLine ), rule );
125 popupMgr()->insert ( action( lgAddLine ), -1, 0 );
126 popupMgr()->setRule( action( lgAddLine ), rule );
128 popupMgr()->insert ( separator(), -1, 0 );
130 popupMgr()->insert ( action( lgDelLine ), -1, 0 );
131 popupMgr()->setRule( action( lgDelLine ), rule );
133 rule = "client='ObjectBrowser'";
135 popupMgr()->insert ( action( lgClear ), -1, 0 );
136 popupMgr()->setRule( action( lgClear ), rule );
140 \brief Get list of compliant dockable GUI elements
141 \param m map to be filled in ("type":"default_position")
143 void LIGHTGUI::windows( QMap<int, int>& m ) const
145 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
146 #ifndef DISABLE_PYCONSOLE
147 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
152 \brief Create custom popup menu selection object.
153 \return new selected object
155 LightApp_Selection* LIGHTGUI::createSelection() const
157 return new LIGHTGUI_Selection();
161 \brief Create data model.
162 \return module specific data model
164 CAM_DataModel* LIGHTGUI::createDataModel()
166 return new LIGHTGUI_DataModel( this );
170 \brief Get the identifier of the currently selected object.
171 \return ID of the currently selected line or -1 if not appropriate
172 object (or multiple objects) is selected.
174 int LIGHTGUI::selectedLine()
176 int id = -1; // bad value
178 // Look for selected lines
179 LightApp_Application* app = getApp();
180 LightApp_SelectionMgr* mgr = app ? app->selectionMgr() : 0;
182 SUIT_DataOwnerPtrList anOwnersList;
183 mgr->selected( anOwnersList );
185 // Get index of the single selected line
186 if ( anOwnersList.size() == 1 ) {
187 const LightApp_DataOwner* owner =
188 dynamic_cast<const LightApp_DataOwner*>( anOwnersList[0].get() );
189 QString anEntry = owner->entry();
190 id = LIGHTGUI_DataModel::id( anEntry );
197 \brief Display the object with the specified identifier.
199 \param allViewers if \c true the object is displayed in all existing viewers
200 (OCC viewers are supported only)
201 \param upd if \c true, update the viewer(s)
203 void LIGHTGUI::displayLine( const int id, const bool allViewers, const bool upd )
205 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
206 if ( dm && id > 0 ) {
207 ViewManagerList viewers;
209 getApp()->viewManagers( "OCCViewer", viewers );
211 viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
213 for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
214 OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
215 if ( !aMgr ) continue;
216 SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();
217 if ( !aViewer ) continue;
218 QString aLine = dm->getLineText( id );
219 QString entry = LIGHTGUI_DataModel::entry( id );
220 SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
222 double aX = 0, aY = dm->lineNb( id ) * LIGHTGUI_TextPrs::TextSize(), aZ = 0;
223 aViewer->Erase( prs, true );
224 Handle(LIGHTGUI_TextPrs) aPrs = new LIGHTGUI_TextPrs( aLine.toLatin1(), gp_Pnt( aX, aY, aZ ) );
225 aPrs->SetOwner( new SALOME_InteractiveObject( entry.toLatin1(), "" ) );
227 prs->AddObject( aPrs );
228 aViewer->Display( prs );
237 \brief Erase the object with the specified identifier.
239 \param allViewers if \c true the object is erased in all existing viewers
240 (OCC viewers are supported only)
241 \param upd if \c true, update the viewer(s)
243 void LIGHTGUI::eraseLine( const int id, const bool allViewers, const bool upd )
245 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
246 if ( dm && id > 0 ) {
247 ViewManagerList viewers;
249 getApp()->viewManagers( "OCCViewer", viewers );
251 viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
253 for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
254 OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
255 if ( !aMgr ) continue;
256 SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();
257 if ( !aViewer ) continue;
258 QString entry = LIGHTGUI_DataModel::entry( id );
259 SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
261 aViewer->Erase( prs, false );
270 \brief Update the object presentation.
272 \param allViewers if \c true the object is updated in all existing viewers
273 (OCC viewers are supported only)
274 \param upd if \c true, update the viewer(s)
276 void LIGHTGUI::updateLine( const int id, const bool allViewers, const bool upd )
278 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
279 if ( dm && id > 0 ) {
280 ViewManagerList viewers;
282 getApp()->viewManagers( "OCCViewer", viewers );
284 viewers.append( getApp()->getViewManager( "OCCViewer", true ) );
286 for ( ViewManagerList::iterator it = viewers.begin(); it != viewers.end(); ++it ) {
287 OCCViewer_ViewManager* aMgr = dynamic_cast<OCCViewer_ViewManager*>( *it );
288 if ( !aMgr ) continue;
289 SOCC_Viewer* aViewer = (SOCC_Viewer*)aMgr->getViewModel();
290 if ( !aViewer ) continue;
291 QString aLine = dm->getLineText( id );
292 QString entry = LIGHTGUI_DataModel::entry( id );
293 if ( aViewer->isVisible( new SALOME_InteractiveObject( entry.toLatin1(), "" ) ) ) {
294 SOCC_Prs* prs = dynamic_cast<SOCC_Prs*>( aViewer->CreatePrs( entry.toLatin1() ) );
296 if ( aLine.isEmpty() ) {
297 aViewer->Erase( prs, false );
300 double aX = 0, aY = dm->lineNb( id ) * LIGHTGUI_TextPrs::TextSize(), aZ = 0;
301 aViewer->Erase( prs, true );
302 Handle(LIGHTGUI_TextPrs) aPrs = new LIGHTGUI_TextPrs( aLine.toLatin1(), gp_Pnt( aX, aY, aZ ) );
303 aPrs->SetOwner( new SALOME_InteractiveObject( entry.toLatin1(), "" ) );
305 prs->AddObject( aPrs );
306 aViewer->Display( prs );
317 \brief Erase objects.
318 \param l objects IDs list
319 \param allViewers if \c true the objects are erased in all existing viewers
320 (OCC viewers are supported only)
322 void LIGHTGUI::eraseLines( const QList<int>& l, const bool allViewers )
324 for ( QList<int>::const_iterator it = l.begin(); it != l.end(); ++it )
325 eraseLine( *it, allViewers );
329 \brief Update objects presentations.
330 \param l objects IDs list
331 \param allViewers if \c true the objects are updated in all existing viewers
332 (OCC viewers are supported only)
334 void LIGHTGUI::updateLines( const QList<int>& l, const bool allViewers )
336 for ( QList<int>::const_iterator it = l.begin(); it != l.end(); ++it )
337 updateLine( *it, allViewers );
341 \brief Activate module.
342 \param study current study
343 \return \c true if activaion is done successfully or 0 to prevent
346 bool LIGHTGUI::activateModule( SUIT_Study* study )
348 bool isDone = LightApp_Module::activateModule( study );
349 if ( !isDone ) return false;
351 setMenuShown( true );
357 \brief Deactivate module.
358 \param study current study
359 \return \c true if deactivaion is done successfully or 0 to prevent
360 deactivation on error
362 bool LIGHTGUI::deactivateModule( SUIT_Study* study )
365 setMenuShown( false );
367 return LightApp_Module::deactivateModule( study );
371 \brief Called when "load text file" action is activated.
373 void LIGHTGUI::onLoadFile()
375 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
378 QStringList filtersList;
379 filtersList.append( tr( "LIGHTGUI_MEN_TXT_FILES" ) );
380 filtersList.append( tr( "LIGHTGUI_MEN_ALL_FILES" ) );
382 // Select a file to be loaded
383 QString aFileName = getApp()->getFileName( true, QString(), filtersList.join( ";;" ), tr( "LIGHTGUI_MEN_LOAD" ), 0 );
384 if ( !aFileName.isEmpty() ) {
386 QList<int> l = dm->getIds();
387 if ( dm->loadFile( aFileName ) ) {
388 eraseLines( l, true );
389 updateObjBrowser( true );
392 SUIT_MessageBox::warning ( application()->desktop(),
394 tr( "WRN_LOAD_FAILED" ) );
400 \brief Called when "save text file" action is activated.
402 void LIGHTGUI::onSaveFile()
404 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
407 QStringList filtersList;
408 filtersList.append( tr( "LIGHTGUI_MEN_TXT_FILES" ) );
409 filtersList.append( tr( "LIGHTGUI_MEN_ALL_FILES" ) );
411 // Select a file name to dump the lines into
412 QString aFileName = getApp()->getFileName( false, dm->fileName(), filtersList.join( ";;" ), tr( "LIGHTGUI_MEN_DUMP" ), 0 );
413 if ( !aFileName.isEmpty() ) {
415 if ( !dm->dumpFile( aFileName ) ) {
416 SUIT_MessageBox::warning ( application()->desktop(),
418 tr( "WRN_DUMP_FAILED" ) );
424 \brief Called when "display selected line" action is activated.
426 void LIGHTGUI::onDisplayLine()
428 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
432 int id = selectedLine();
433 QString aLine = dm->getLineText( id );
435 // Check, that position is defined
436 if ( id == -1 || aLine.isEmpty() ) {
437 SUIT_MessageBox::warning ( application()->desktop(),
439 tr( "WRN_SELECT_LINE" ) );
446 \brief Called when "erase selected line" action is activated.
448 void LIGHTGUI::onEraseLine()
450 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
454 int id = selectedLine();
455 QString aLine = dm->getLineText( id );
457 // Check, that position is defined
458 if ( id == -1 || aLine.isEmpty() ) {
459 SUIT_MessageBox::warning ( application()->desktop(),
461 tr( "WRN_SELECT_LINE" ) );
468 \brief Called when "edit selected line" action is activated.
470 void LIGHTGUI::onEditLine()
472 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
476 int id = selectedLine();
478 // Check, that position is defined
480 SUIT_MessageBox::warning ( application()->desktop(),
482 tr( "WRN_SELECT_LINE" ) );
488 QString aText = QInputDialog::getText( application()->desktop(),
489 tr( "LIGHTGUI_EDIT_LINE" ),
492 dm->getLineText( id ),
496 // try to change a text of the selected line
498 isOk = dm->setLineText( id, aText );
501 updateLine( id, true );
502 updateObjBrowser( true );
505 SUIT_MessageBox::warning ( application()->desktop(),
507 tr( "WRN_EDIT_FAILED" ) );
512 \brief Called when "insert new line" action is activated.
514 void LIGHTGUI::onAddLine()
516 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
520 int id = selectedLine();
524 QString aText = QInputDialog::getText( getApp()->desktop(),
525 tr( "LIGHTGUI_ADD_LINE" ),
532 QList<int> l = dm->getIds();
534 // try to insert/add text line
535 isOk = dm->insertLineBefore( id, aText );
538 updateLines( l, true );
539 updateObjBrowser( true );
542 SUIT_MessageBox::warning ( application()->desktop(),
544 tr( "WRN_ADD_FAILED" ) );
549 \brief Called when "delete selected line" action is activated.
551 void LIGHTGUI::onDelLine()
553 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
557 int id = selectedLine();
559 // Check, that position is defined
561 SUIT_MessageBox::warning ( application()->desktop(),
563 tr( "WRN_SELECT_LINE" ) );
567 QList<int> l = dm->getIds();
569 // try to delete line
570 bool isOk = dm->deleteTextLine( id );
572 updateLines( l, true );
573 updateObjBrowser( true );
576 SUIT_MessageBox::warning ( application()->desktop(),
578 tr( "WRN_DELETE_FAILED" ) );
583 \brief Called when "clear all contents" action is activated.
585 void LIGHTGUI::onClear()
587 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
590 QList<int> l = dm->getIds();
591 eraseLines( l, true );
595 updateObjBrowser( true );
599 \brief Check if this object is can't be renamed in place
601 This method can be re-implemented in the subclasses.
602 Return true in case if object isn't reference or component (module root).
604 \param entry column id
605 \return \c true if the item can be renamed by the user in place (e.g. in the Object browser)
607 bool LIGHTGUI::renameAllowed( const QString& entry ) const
609 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
610 return dm && dm->lineNb( entry ) >= 0;
614 Rename object by entry.
615 \param entry entry of the object
616 \param name new name of the object
617 \brief Return \c true if rename operation finished successfully, \c false otherwise.
619 bool LIGHTGUI::renameObject( const QString& entry, const QString& name )
623 LIGHTGUI_DataModel* dm = dynamic_cast<LIGHTGUI_DataModel*>( dataModel() );
624 if ( dm && dm->lineNb( entry ) ) {
625 int id = LIGHTGUI_DataModel::id( entry );
626 result = dm->setLineText( id, name );
628 updateLine( id, true );
629 updateObjBrowser( true );
636 \fn CAM_Module* createModule();
637 \brief Export module instance (factory function).
638 \return new created instance of the module
642 \fn char* getModuleVersion();
643 \brief Get version of this module.
644 \return version information
648 LIGHT_EXPORT CAM_Module* createModule() {
649 return new LIGHTGUI();
652 LIGHT_EXPORT char* getModuleVersion() {
653 return (char*)LIGHT_VERSION_STR;