Salome HOME
fix module list updating in SalomeApprc
[modules/gui.git] / src / LightApp / LightApp_Application.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  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, or (at your option) any later version.
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      LightApp_Application.cxx
24 // Created:   6/20/2005 18:39:45 PM
25 // Author:    Natalia Donis
26 #ifdef WIN32
27 // E.A. : On windows with python 2.6, there is a conflict
28 // E.A. : between pymath.h and Standard_math.h which define
29 // E.A. : some same symbols : acosh, asinh, ...
30   #include <Standard_math.hxx>
31   #ifndef DISABLE_PYCONSOLE
32     #include <pymath.h>
33   #endif
34 #endif
35
36 #ifndef DISABLE_PYCONSOLE
37   #include "PyConsole_Interp.h"
38   #include "LightApp_PyEditor.h"
39   #include "PyConsole_Console.h"
40 #endif
41
42 #include "LightApp_Application.h"
43 #include "LightApp_Module.h"
44 #include "LightApp_DataModel.h"
45 #include "LightApp_DataOwner.h"
46 #include "LightApp_Displayer.h"
47 #include "LightApp_Study.h"
48 #include "LightApp_Preferences.h"
49 #include "LightApp_PreferencesDlg.h"
50 #include "LightApp_ModuleDlg.h"
51 #include "LightApp_AboutDlg.h"
52 #include "LightApp_ExtInfoDlg.h"
53 #include "LightApp_ModuleAction.h"
54 // temporary commented
55 #include "LightApp_EventFilter.h"
56 #include "LightApp_OBSelector.h"
57 #include "LightApp_SelectionMgr.h"
58 #include "LightApp_DataObject.h"
59 #include "LightApp_WgViewModel.h"
60 #include "LightApp_FullScreenHelper.h"
61
62 #include <GUI_version.h>
63
64 #include <SALOME_Event.h>
65
66 #ifdef USE_SALOME_STYLE
67 #include <Style_Salome.h>
68 #include <Style_PrefDlg.h>
69 #endif // USE_SALOME_STYLE
70
71 #include <CAM_Module.h>
72 #include <CAM_DataModel.h>
73 #include <CAM_Study.h>
74 #include <STD_TabDesktop.h>
75
76 #include <SUIT_DataBrowser.h>
77 #include <SUIT_Session.h>
78 #include <SUIT_Study.h>
79 #include <SUIT_FileDlg.h>
80 #include <SUIT_ResourceMgr.h>
81 #include <SUIT_ShortcutMgr.h>
82 #include <SUIT_Tools.h>
83 #include <SUIT_Accel.h>
84 #include <SUIT_MessageBox.h>
85 #include <SUIT_ViewWindow.h>
86
87 #include <Qtx.h>
88 #include <QtxFontEdit.h>
89 #include <QtxToolBar.h>
90 #include <QtxTreeView.h>
91 #include <QtxInfoPanel.h>
92 #include <QtxMRUAction.h>
93 #include <QtxDockAction.h>
94 #include <QtxDockWidget.h>
95 #include <QtxActionToolMgr.h>
96 #include <QtxSearchTool.h>
97 #include <QtxWorkstack.h>
98 #include <QtxMap.h>
99
100 #include <LogWindow.h>
101 #include <SalomeApprc_utils.h>
102
103 #ifndef DISABLE_GLVIEWER
104   #include <GLViewer_Viewer.h>
105   #include <GLViewer_ViewManager.h>
106   #include "LightApp_GLSelector.h"
107 #endif
108
109 #ifndef DISABLE_PLOT2DVIEWER
110   #include <Plot2d_ViewManager.h>
111   #include <Plot2d_ViewModel.h>
112   #include <Plot2d_ViewWindow.h>
113   #include <Plot2d_ViewFrame.h>
114   #include "LightApp_Plot2dSelector.h"
115 #ifndef DISABLE_SALOMEOBJECT
116   #include <SPlot2d_ViewModel.h>
117 #else
118   #include <Plot2d_ViewModel.h>
119 #endif
120 #endif
121
122 #ifndef DISABLE_OCCVIEWER
123   #include <OCCViewer_ViewManager.h>
124   #include <OCCViewer_ViewFrame.h>
125   #include <OCCViewer_ViewPort3d.h>
126 #ifndef DISABLE_SALOMEOBJECT
127   #include <SOCC_ViewModel.h>
128 #else
129   #include <OCCViewer_ViewModel.h>
130 #endif
131   #include "LightApp_OCCSelector.h"
132 #endif
133
134 #ifndef DISABLE_VTKVIEWER
135 #ifndef DISABLE_SALOMEOBJECT
136   #include <SVTK_ViewModel.h>
137   #include <SVTK_ViewManager.h>
138   #include "LightApp_VTKSelector.h"
139 #else
140   #include <VTKViewer_ViewModel.h>
141   #include <VTKViewer_ViewManager.h>
142 #endif
143   #include <VTKViewer_ViewModel.h>
144 #endif
145
146 #ifndef DISABLE_QXGRAPHVIEWER
147   #include <QxScene_ViewManager.h>
148   #include <QxScene_ViewModel.h>
149   #include <QxScene_ViewWindow.h>
150 #endif
151
152 #ifndef DISABLE_GRAPHICSVIEW
153   #include "GraphicsView_Viewer.h"
154   #include "GraphicsView_ViewManager.h"
155   #include "LightApp_GVSelector.h"
156 #endif
157
158 #ifndef DISABLE_PVVIEWER
159   #include "PVViewer_ViewManager.h"
160   #include "PVViewer_ViewWindow.h"
161   #include "PVViewer_ViewModel.h"
162 #endif
163
164 #ifndef DISABLE_PYVIEWER
165   #include <PyViewer_ViewManager.h>
166   #include <PyViewer_ViewModel.h>
167   #include <PyViewer_ViewWindow.h>
168 #endif
169
170 #ifndef DISABLE_PV3DVIEWER
171 #ifndef DISABLE_SALOMEOBJECT
172   #include <SPV3D_ViewModel.h>
173   #include <SPV3D_ViewManager.h>
174   #include "LightApp_PV3DSelector.h"
175 #else
176   #include <PV3DViewer_ViewModel.h>
177   #include <PV3DViewer_ViewManager.h>
178 #endif
179   #include <PV3DViewer_ViewManager.h>
180   #include <PV3DViewer_ViewModel.h>
181   #include "PV3DViewer_ViewWindow.h"
182 #endif
183
184
185 #define VISIBILITY_COLUMN_WIDTH 25
186
187 #include <QDir>
188 #include <QImage>
189 #include <QString>
190 #include <QWidget>
191 #include <QStringList>
192 #include <QFile>
193 #include <QApplication>
194 #include <QMap>
195 #include <QStatusBar>
196 #include <QThread>
197 #include <QObjectList>
198 #include <QComboBox>
199 #include <QInputDialog>
200 #include <QFontDatabase>
201 #include <QIcon>
202 #include <QByteArray>
203 #include <QMenu>
204 #include <QProcess>
205 #include <QTimer>
206 #include <QHeaderView>
207 #include <QTreeView>
208 #include <QMimeData>
209 #include <QShortcut>
210 #include <QRegExp>
211
212 #include <utilities.h>
213
214 #define FIRST_HELP_ID 1000000
215 #define HAS_WWW_URL true
216 #define HAS_FORUM_URL true
217 #define HAS_YOUTUBE_URL true
218 #define HAS_TUTORIAL_URL false
219
220 #ifndef DISABLE_SALOMEOBJECT
221   #include <SALOME_InteractiveObject.hxx>
222   #include <SALOME_ListIO.hxx>
223 #endif
224
225 #include <Standard_Version.hxx>
226
227 #define ToolBarMarker    0
228 #define DockWidgetMarker 1
229
230 static const char* imageEmptyIcon[] = {
231 "20 20 1 1",
232 ".      c None",
233 "....................",
234 "....................",
235 "....................",
236 "....................",
237 "....................",
238 "....................",
239 "....................",
240 "....................",
241 "....................",
242 "....................",
243 "....................",
244 "....................",
245 "....................",
246 "....................",
247 "....................",
248 "....................",
249 "....................",
250 "....................",
251 "....................",
252 "...................."};
253
254 // Markers used to parse array with dockable windows and toolbars state.
255 // For more details please see the qdockarealayout.cpp && qtoolbararealayout.cpp
256 // in the Qt source code.
257
258 #define QDockWidgetMarker 0xfd // = DockWidgetStateMarker
259 #define QToolBarMarker 0xfc    // = ToolBarStateMarkerEx
260
261 // Format of the Byte array with the windows and toolbar state is:
262 // VersionMarker|version|DockWidgetStateMarker|nbDockWidgetLines|...DocWidgetData...|ToolBarStateMarkerEx|nbToolBarLines|...ToolBarData...
263
264 //Find toolbar marker position in the array in the following way:
265 //since the 'toolbar marker' is not unique, find index of first occurrence of the
266 //'toolbar marker' in the array and check that next string is name of the toolbar
267
268 namespace
269 {
270   const char* salomeAppDir = "SALOME_APPLICATION_DIR";
271 }
272
273 void LightAppCleanUpAppResources()
274 {
275   if ( LightApp_Application::_prefs_ ) {
276     delete LightApp_Application::_prefs_;
277     LightApp_Application::_prefs_ = 0;
278   }
279 }
280
281 namespace
282 {
283   int getToolbarMarkerIndex( QByteArray input, const QStringList& aFlags ) {
284     int aResult = -1,tmp = 0;
285     int inputLen = input.length();
286     QDataStream anInputData( &input, QIODevice::ReadOnly );
287     while ( tmp < inputLen ) {
288       tmp = input.indexOf( (uchar)QToolBarMarker, tmp + 1 );
289       if ( tmp < 0 )
290         break;
291       anInputData.device()->seek( tmp );
292       uchar mark;
293       anInputData >> mark;
294       int lines;
295       anInputData >> lines;
296
297       if ( lines == 0 && anInputData.atEnd() ) {
298         //Case then array doesn't contain information about toolbars,
299         aResult = tmp;
300         break;
301       }
302
303       int pos;
304       anInputData >> pos;
305       int cnt;
306       anInputData >> cnt;
307       QString str;
308       anInputData >> str;
309       if ( aFlags.contains( str ) ) {
310         aResult = tmp;
311         break;
312       }
313     }
314     return aResult;
315   }
316
317   QString langToName( const QString& lang )
318   {
319     // special processing for English language to avoid such result as "American English"
320     // as Qt cannot just say "English"
321     QString result;
322     if ( lang == "en" )
323       result = "English";
324     else
325       result = QLocale( lang ).nativeLanguageName();
326     return result;
327   }
328
329   QString getHelpItem( const QString& section, const QString& parameter, const QString& root = QString() )
330   {
331     SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
332     foreach( QString item, resMgr->stringValue( section, parameter ).split( ";;", QString::SkipEmptyParts ) )
333     {
334       if ( item.startsWith( "http", Qt::CaseInsensitive ) )
335         return item;
336       QString path = item;
337       path.remove( QRegExp( "#.*$" ) );
338       QFileInfo fi( path );
339       if ( fi.isRelative() && !root.isEmpty() )
340         path = Qtx::addSlash( root ) + path;
341       if ( QFile::exists( path ) )
342         return item;
343     }
344     return QString();
345   }
346
347   const bool HAS_SALOME_ON_DEMAND =
348 #if defined(WITH_SALOME_ON_DEMAND)
349     true;
350 #else
351     false;
352 #endif
353 }
354
355 /*!Create new instance of LightApp_Application.*/
356 extern "C" LIGHTAPP_EXPORT SUIT_Application* createApplication()
357 {
358   return new LightApp_Application();
359 }
360
361 /*! \var global preferences of LightApp */
362 LightApp_Preferences* LightApp_Application::_prefs_ = 0;
363
364
365 /*!
366   \class LightApp_Application
367   Application containing LightApp module
368 */
369
370 /*!Constructor.*/
371 LightApp_Application::LightApp_Application()
372 : CAM_Application( false ),
373   myPrefs( 0 ),
374   myScreenHelper(new LightApp_FullScreenHelper())
375 {
376   Q_INIT_RESOURCE( LightApp );
377
378   STD_TabDesktop* desk = new STD_TabDesktop();
379   desk->setFullScreenAllowed(false);
380   desk->setMinimizeAllowed(false);
381
382   setDesktop( desk );
383
384   // initialize auto save timer
385   myAutoSaveTimer = new QTimer( this );
386   myAutoSaveTimer->setSingleShot( true );
387   connect( myAutoSaveTimer, SIGNAL( timeout() ), this, SLOT( onSaveDoc() ) );
388
389   //connect( this, SIGNAL( moving() ), this, SLOT( onMoved() ) );
390
391   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
392   QPixmap aLogo = aResMgr->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false );
393
394   desktop()->setWindowIcon( aLogo );
395   desktop()->setDockableMenuBar( false );
396   desktop()->setDockableStatusBar( false );
397
398   // base logo (salome itself)
399   desktop()->logoInsert( "_app_base",  aResMgr->loadPixmap( "LightApp", tr( "APP_BASE_LOGO" ), false ) );
400   // extra logo (salome-based application)
401   desktop()->logoInsert( "_app_extra", aResMgr->loadPixmap( "LightApp", tr( "APP_EXTRA_LOGO" ), false ) );
402
403   clearViewManagers();
404
405   mySelMgr = new LightApp_SelectionMgr( this );
406
407   myAccel = SUIT_Accel::getAccel();
408
409 #ifndef DISABLE_OCCVIEWER
410   myAccel->setActionKey( SUIT_Accel::PanLeft,     Qt::CTRL+Qt::Key_Left,     OCCViewer_Viewer::Type() );
411   myAccel->setActionKey( SUIT_Accel::PanRight,    Qt::CTRL+Qt::Key_Right,    OCCViewer_Viewer::Type() );
412   myAccel->setActionKey( SUIT_Accel::PanUp,       Qt::CTRL+Qt::Key_Up,       OCCViewer_Viewer::Type() );
413   myAccel->setActionKey( SUIT_Accel::PanDown,     Qt::CTRL+Qt::Key_Down,     OCCViewer_Viewer::Type() );
414   myAccel->setActionKey( SUIT_Accel::ZoomIn,      Qt::CTRL+Qt::Key_Plus,     OCCViewer_Viewer::Type() );
415   myAccel->setActionKey( SUIT_Accel::ZoomOut,     Qt::CTRL+Qt::Key_Minus,    OCCViewer_Viewer::Type() );
416   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::CTRL+Qt::Key_Asterisk, OCCViewer_Viewer::Type() );
417   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::Key_Space,             OCCViewer_Viewer::Type() );
418   myAccel->setActionKey( SUIT_Accel::RotateLeft,  Qt::ALT+Qt::Key_Left,      OCCViewer_Viewer::Type() );
419   myAccel->setActionKey( SUIT_Accel::RotateRight, Qt::ALT+Qt::Key_Right,     OCCViewer_Viewer::Type() );
420   myAccel->setActionKey( SUIT_Accel::RotateUp,    Qt::ALT+Qt::Key_Up,        OCCViewer_Viewer::Type() );
421   myAccel->setActionKey( SUIT_Accel::RotateDown,  Qt::ALT+Qt::Key_Down,      OCCViewer_Viewer::Type() );
422 #endif
423 #ifndef DISABLE_VTKVIEWER
424   myAccel->setActionKey( SUIT_Accel::PanLeft,     Qt::CTRL+Qt::Key_Left,     VTKViewer_Viewer::Type() );
425   myAccel->setActionKey( SUIT_Accel::PanRight,    Qt::CTRL+Qt::Key_Right,    VTKViewer_Viewer::Type() );
426   myAccel->setActionKey( SUIT_Accel::PanUp,       Qt::CTRL+Qt::Key_Up,       VTKViewer_Viewer::Type() );
427   myAccel->setActionKey( SUIT_Accel::PanDown,     Qt::CTRL+Qt::Key_Down,     VTKViewer_Viewer::Type() );
428   myAccel->setActionKey( SUIT_Accel::ZoomIn,      Qt::CTRL+Qt::Key_Plus,     VTKViewer_Viewer::Type() );
429   myAccel->setActionKey( SUIT_Accel::ZoomOut,     Qt::CTRL+Qt::Key_Minus,    VTKViewer_Viewer::Type() );
430   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::CTRL+Qt::Key_Asterisk, VTKViewer_Viewer::Type() );
431   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::Key_Space,             VTKViewer_Viewer::Type() );
432   myAccel->setActionKey( SUIT_Accel::RotateLeft,  Qt::ALT+Qt::Key_Left,      VTKViewer_Viewer::Type() );
433   myAccel->setActionKey( SUIT_Accel::RotateRight, Qt::ALT+Qt::Key_Right,     VTKViewer_Viewer::Type() );
434   myAccel->setActionKey( SUIT_Accel::RotateUp,    Qt::ALT+Qt::Key_Up,        VTKViewer_Viewer::Type() );
435   myAccel->setActionKey( SUIT_Accel::RotateDown,  Qt::ALT+Qt::Key_Down,      VTKViewer_Viewer::Type() );
436 #endif
437 #ifndef DISABLE_PLOT2DVIEWER
438   myAccel->setActionKey( SUIT_Accel::PanLeft,     Qt::CTRL+Qt::Key_Left,     Plot2d_Viewer::Type() );
439   myAccel->setActionKey( SUIT_Accel::PanRight,    Qt::CTRL+Qt::Key_Right,    Plot2d_Viewer::Type() );
440   myAccel->setActionKey( SUIT_Accel::PanUp,       Qt::CTRL+Qt::Key_Up,       Plot2d_Viewer::Type() );
441   myAccel->setActionKey( SUIT_Accel::PanDown,     Qt::CTRL+Qt::Key_Down,     Plot2d_Viewer::Type() );
442   myAccel->setActionKey( SUIT_Accel::ZoomIn,      Qt::CTRL+Qt::Key_Plus,     Plot2d_Viewer::Type() );
443   myAccel->setActionKey( SUIT_Accel::ZoomOut,     Qt::CTRL+Qt::Key_Minus,    Plot2d_Viewer::Type() );
444   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::CTRL+Qt::Key_Asterisk, Plot2d_Viewer::Type() );
445   myAccel->setActionKey( SUIT_Accel::ZoomFit,     Qt::Key_Space,             Plot2d_Viewer::Type() );
446 #endif
447
448   connect( mySelMgr, SIGNAL( selectionChanged() ), this, SLOT( onSelection() ) );
449   connect( desktop(), SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
450            this,      SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
451   connect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
452            this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ), Qt::UniqueConnection );
453
454
455   // Set existing font for the python console in resources
456   if( !aResMgr->hasValue( "PyConsole", "font" ) )
457     return;
458
459   QFont f = aResMgr->fontValue( "PyConsole", "font" );
460   QFontDatabase fdb;
461   QStringList famdb = fdb.families();
462
463   if ( famdb.contains(f.family()) || !aResMgr->hasValue( "PyConsole", "additional_families" ) )
464     return;
465
466   QStringList anAddFamilies = aResMgr->stringValue( "PyConsole", "additional_families" ).split( ";", QString::SkipEmptyParts );
467   QString aFamily;
468   for ( QStringList::Iterator it = anAddFamilies.begin(); it != anAddFamilies.end(); ++it )
469   {
470     aFamily = *it;
471     if ( famdb.contains(aFamily) )
472     {
473       f.setFamily( aFamily );
474       aResMgr->setValue( "PyConsole", "font", f );
475       break;
476     }
477   }
478 }
479
480 /*!Destructor.
481  *\li Save window geometry.
482  *\li Save desktop geometry.
483  *\li Save resource maneger.
484  *\li Delete selection manager.
485  */
486 LightApp_Application::~LightApp_Application()
487 {
488   savePreferences();
489   delete mySelMgr;
490   delete myScreenHelper;
491   myPrefs = 0;
492 }
493
494 /*!Start application.*/
495 void LightApp_Application::start()
496 {
497   CAM_Application::start();
498
499   updateWindows();
500   updateViewManagers();
501   updateCommandsStatus();
502
503   putInfo( "" );
504   desktop()->statusBar()->showMessage( "" );
505
506   LightApp_EventFilter::Init();
507
508   onNewDoc();
509 }
510
511 /*!Closeapplication.*/
512 void LightApp_Application::closeApplication()
513 {
514 #ifndef DISABLE_QTXWEBBROWSER
515   QProcess::startDetached( "HelpBrowser",
516                            QStringList() << QString( "--remove=%1" ).arg( QApplication::instance()->applicationPid() ) );
517 #endif
518   CAM_Application::closeApplication();
519 }
520
521 /*!Gets application name.*/
522 QString LightApp_Application::applicationName() const
523 {
524   static QString _app_name;
525   if ( _app_name.isEmpty() )
526     _app_name = tr( "APP_NAME" );
527   return _app_name;
528 }
529
530 /*!Gets application version.*/
531 QString LightApp_Application::applicationVersion() const
532 {
533   static QString _app_version;
534
535   if ( _app_version.isEmpty() )
536   {
537     QString resVersion = tr( "APP_VERSION" );
538     if ( resVersion != "APP_VERSION" )
539     {
540       _app_version = resVersion;
541     }
542     else
543     {
544       _app_version = GUI_VERSION_STR;
545     }
546   }
547   return _app_version;
548 }
549
550 /*!Load module by \a name.*/
551 CAM_Module* LightApp_Application::loadModule( const QString& name, const bool showMsg )
552 {
553   CAM_Module* mod = CAM_Application::loadModule( name, showMsg );
554   if ( mod )
555   {
556     connect( this, SIGNAL( studyOpened() ), mod, SLOT( onModelOpened() ) );
557     connect( this, SIGNAL( studySaved() ),  mod, SLOT( onModelSaved() ) );
558     connect( this, SIGNAL( studyClosed() ), mod, SLOT( onModelClosed() ) );
559   }
560   return mod;
561 }
562
563 /*!Activate module by \a modName*/
564 bool LightApp_Application::activateModule( const QString& modName )
565 {
566   QString actName;
567   CAM_Module* prevMod = activeModule();
568
569   if ( prevMod )
570     actName = prevMod->moduleName();
571
572   QString name = modName;
573   if ( !name.isEmpty() && !moduleTitle( modName ).isEmpty() )
574     name = moduleTitle( modName );
575
576   if ( actName == name )
577     return true;
578
579   putInfo( tr( "ACTIVATING_MODULE" ).arg( name ) );
580
581   saveDockWindowsState();
582
583   if ( infoPanel() )
584     infoPanel()->clear();
585
586   bool status = CAM_Application::activateModule( name );
587
588   updateModuleActions();
589
590   putInfo( "" );
591
592   if ( !status )
593     return false;
594
595   updateWindows();
596   updateViewManagers();
597
598   if ( activeStudy() && activeStudy()->root() && objectBrowser() ) {
599     if ( objectBrowser()->root() != activeStudy()->root() )
600       objectBrowser()->setRoot( activeStudy()->root() );
601     updateObjectBrowser( true );
602   }
603
604   if ( activeModule() ) activeModule()->updateModuleVisibilityState();
605
606   updateActions();
607   return true;
608 }
609
610 /*!Gets selection manager.*/
611 LightApp_SelectionMgr* LightApp_Application::selectionMgr() const
612 {
613   return mySelMgr;
614 }
615
616 /*!Creat action "New window" for certain type of viewer:*/
617 void LightApp_Application::createActionForViewer( const int id,
618                                                   const int parentId,
619                                                   const QString& suffix,
620                                                   const int accel )
621 {
622   QString vtlt = tr( QString( "NEW_WINDOW_%1" ).arg( suffix ).toLatin1().constData() );
623   QString tip = tr( "CREATING_NEW_WINDOW" ).arg( vtlt.remove( "&" ) );
624   QAction* a = createAction( id,                      // menu action id
625                              tip,                     // status tip
626                              QIcon(),                 // icon
627                              vtlt,                    // menu text
628                              tip,                     // tooltip
629                              accel,                   // shortcut
630                              desktop(),               // parent
631                              false,                   // toggle flag
632                              this,                    // receiver
633                              SLOT( onNewWindow() ) ); // slot
634   createMenu( a, parentId, -1 );
635 }
636
637 /*!Create actions:*/
638
639 void LightApp_Application::createActions()
640 {
641   CAM_Application::createActions();
642
643   SUIT_Desktop* desk = desktop();
644   SUIT_ResourceMgr* resMgr = resourceMgr();
645
646   // Preferences
647   createAction( PreferencesId, tr( "TOT_DESK_PREFERENCES" ), QIcon(),
648                 tr( "MEN_DESK_PREFERENCES" ), tr( "PRP_DESK_PREFERENCES" ),
649                 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onPreferences() ) );
650
651   // Help menu
652
653   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 );
654
655   QString url;
656
657   // a) Link to web site
658   if ( HAS_WWW_URL ) {
659     url = resMgr->stringValue("GUI", "site_url");
660     if ( !url.isEmpty() ) {
661       QString title = tr ( "SALOME_SITE" );
662       QAction* as = createAction( WebSiteId, title,
663                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
664                                   title, title,
665                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
666       as->setData( url );
667       createMenu( as, helpMenu, -1, 0 );
668     }
669   }
670
671   // b) Link to Forum
672   if ( HAS_FORUM_URL ) {
673     url = resMgr->stringValue("GUI", "forum_url");
674     if ( !url.isEmpty() ) {
675       QString title = tr ( "SALOME_FORUM" );
676       QAction* af = createAction( ForumId, title,
677                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
678                                   title, title,
679                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
680       af->setData( url );
681       createMenu( af, helpMenu, -1, 0 );
682     }
683   }
684
685   // c) Link to YouTube channel
686   if ( HAS_YOUTUBE_URL ) {
687     url = resMgr->stringValue("GUI", "channel_url");
688     if ( !url.isEmpty() ) {
689       createMenu( separator(), helpMenu, -1, 0 );
690       QString title = tr ( "SALOME_VIDEO_TUTORIALS" );
691       QAction* av = createAction( VideosId, title,
692                                   resMgr->loadPixmap( "LightApp", tr( "ICON_LIFE_RIGN" ), false ),
693                                   title, tr( "PRP_SALOME_VIDEO_TUTORIALS" ),
694                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
695       av->setData( url );
696       createMenu( av, helpMenu, -1, 0 );
697     }
698   }
699
700   // d) Link to Tutorials
701   if ( HAS_TUTORIAL_URL ) {
702     url = resMgr->stringValue("GUI", "tutorials_url");
703     if ( !url.isEmpty() ) {
704       QString title = tr ( "SALOME_TUTORIALS" );
705       QAction* as = createAction( TutorialsId, title,
706                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
707                                   title, tr( "PRP_SALOME_TUTORIALS" ),
708                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
709       as->setData( url );
710       createMenu( as, helpMenu, -1, 0 );
711     }
712   }
713
714   // e) Help for modules
715
716   QStringList aModuleList;
717   modules( aModuleList, false );
718   aModuleList.prepend( "GUI" );
719   aModuleList.prepend( "KERNEL" );
720
721   foreach( QString aModule, aModuleList )
722     createHelpItems( aModule );
723
724   // f) Additional help items
725
726   int id = LightApp_Application::UserID + FIRST_HELP_ID + 1000;
727   createMenu( separator(), helpMenu, -1, 10 );
728
729   QStringList addHelpItems = resMgr->parameters( "add_help" );
730   foreach ( QString paramName, addHelpItems ) {
731     QString helpItem = getHelpItem( "add_help", paramName );
732     if ( !helpItem.isEmpty() )
733     {
734       QPixmap helpIcon = helpItem.startsWith( "http", Qt::CaseInsensitive ) ?
735         resMgr->loadPixmap( "STD", tr( "ICON_WWW" ), false ) : resMgr->loadPixmap( "STD", tr( "ICON_HELP" ), false );
736       QAction* a = createAction( id++, paramName, helpIcon, paramName, paramName,
737                                  0, desk, false, this, SLOT( onHelpContentsModule() ) );
738       a->setData( helpItem );
739       createMenu( a, helpMenu, -1, 10 );
740     }
741   }
742
743   //! MRU
744   static QtxMRUAction* mru = new QtxMRUAction( tr( "TOT_DESK_MRU" ), tr( "MEN_DESK_MRU" ), 0 );
745   connect( mru, SIGNAL( activated( const QString& ) ), this, SLOT( onMRUActivated( const QString& ) ) );
746   registerAction( MRUId, mru );
747
748   // List of modules
749   LightApp_ModuleAction* moduleAction = new LightApp_ModuleAction( resMgr, desk );
750   registerAction( ModulesListId, moduleAction );
751   // a. here we add regular modules (specified to GUI via --modules cmd line option, or default list from configuration)
752   // b. custom modules are added in customize() method
753   QStringList modList;
754   modules( modList, false );
755   foreach ( QString aModule, modList )
756     moduleAction->insertModule( aModule, moduleIcon( aModule, 20 ) ); // scale icon to 20x20 pix
757
758   connect( this, SIGNAL( moduleActivated( QString ) ),
759            moduleAction, SLOT( setActiveModule( QString ) ) );
760   connect( moduleAction, SIGNAL( moduleActivated( const QString& ) ),
761            this, SLOT( onModuleActivation( const QString& ) ) );
762   connect( moduleAction, SIGNAL( adding() ),
763            this, SLOT( onExtAdding() ) );
764   connect( moduleAction, SIGNAL( removing( QString ) ),
765            this, SLOT( onExtRemoving( QString ) ) );
766   connect( moduleAction, SIGNAL(showExtInfo()),
767            this, SLOT(onShowExtInfo()));
768
769   addExtensionsActions(moduleAction);
770
771   // New window
772   int windowMenu = createMenu( tr( "MEN_DESK_WINDOW" ), -1, MenuWindowId, 100 );
773   int newWinMenu = createMenu( tr( "MEN_DESK_NEWWINDOW" ), windowMenu, -1, 0 );
774
775   createAction( CloseId, tr( "TOT_CLOSE" ), QIcon(), tr( "MEN_DESK_CLOSE" ), tr( "PRP_CLOSE" ),
776                 Qt::CTRL+Qt::Key_F4, desk, false, this, SLOT( onCloseWindow() ) );
777   createAction( CloseAllId, tr( "TOT_CLOSE_ALL" ), QIcon(), tr( "MEN_DESK_CLOSE_ALL" ), tr( "PRP_CLOSE_ALL" ),
778                 0, desk, false, this, SLOT( onCloseAllWindow() ) );
779   createAction( GroupAllId, tr( "TOT_GROUP_ALL" ), QIcon(), tr( "MEN_DESK_GROUP_ALL" ), tr( "PRP_GROUP_ALL" ),
780                 0, desk, false, this, SLOT( onGroupAllWindow() ) );
781
782   createMenu( CloseId,     windowMenu, 0, -1 );
783   createMenu( CloseAllId,  windowMenu, 0, -1 );
784   createMenu( GroupAllId,  windowMenu, 0, -1 );
785   createMenu( separator(), windowMenu, -1, 0 );
786
787 #ifndef DISABLE_GLVIEWER
788   createActionForViewer( NewGLViewId, newWinMenu, QString::number( 0 ), Qt::ALT+Qt::Key_G );
789 #endif
790 #ifndef DISABLE_PLOT2DVIEWER
791   createActionForViewer( NewPlot2dId, newWinMenu, QString::number( 1 ), Qt::ALT+Qt::Key_P );
792 #endif
793 #ifndef DISABLE_OCCVIEWER
794   createActionForViewer( NewOCCViewId, newWinMenu, QString::number( 2 ), Qt::ALT+Qt::Key_O );
795 #endif
796 #ifndef DISABLE_VTKVIEWER
797   createActionForViewer( NewVTKViewId, newWinMenu, QString::number( 3 ), Qt::ALT+Qt::Key_K );
798 #endif
799 #ifndef DISABLE_QXGRAPHVIEWER
800   createActionForViewer( NewQxSceneViewId, newWinMenu, QString::number( 4 ), Qt::ALT+Qt::Key_S );
801 #endif
802 #ifndef DISABLE_GRAPHICSVIEW
803   createActionForViewer( NewGraphicsViewId, newWinMenu, QString::number( 5 ), Qt::ALT+Qt::Key_C );
804 #endif
805 #ifndef DISABLE_PVVIEWER
806   createActionForViewer( NewPVViewId, newWinMenu, QString::number( 6 ), Qt::ALT+Qt::Key_A );
807 #endif
808 #ifndef DISABLE_PYVIEWER
809   createActionForViewer( NewPyViewerId, newWinMenu, QString::number( 7 ), Qt::ALT+Qt::Key_Y );
810 #endif
811 #ifndef DISABLE_PV3DVIEWER
812   createActionForViewer( NewPV3DViewId, newWinMenu, QString::number( 8 ), Qt::ALT+Qt::Key_3 );
813 #endif
814
815   createAction( RenameId, tr( "TOT_RENAME" ), QIcon(), tr( "MEN_DESK_RENAME" ), tr( "PRP_RENAME" ),
816                 Qt::ALT+Qt::SHIFT+Qt::Key_R, desk, false, this, SLOT( onRenameWindow() ) );
817   createMenu( RenameId, windowMenu, -1 );
818
819   int fileMenu = createMenu( tr( "MEN_DESK_FILE" ), -1 );
820   createMenu( PreferencesId, fileMenu, 50, -1 );
821   createMenu( separator(), fileMenu, -1, 50, -1 );
822
823   createMenu( separator(), fileMenu, -1, 100, -1 );
824   createMenu( MRUId, fileMenu, 100, -1 );
825   createMenu( separator(), fileMenu, -1, 100, -1 );
826
827 #ifdef USE_SALOME_STYLE
828   createAction( StyleId, tr( "TOT_THEME" ), QIcon(), tr( "MEN_DESK_THEME" ), tr( "PRP_THEME" ),
829                 0, desk, false, this, SLOT( onStylePreferences() ) );
830 #endif // USE_SALOME_STYLE
831
832   createAction( FullScreenId, tr( "TOT_FULLSCREEN" ), QIcon(), tr( "MEN_DESK_FULLSCREEN" ), tr( "PRP_FULLSCREEN" ),
833                 Qt::Key_F11, desk, false, this, SLOT( onFullScreen() ) );
834
835
836   int viewMenu = createMenu( tr( "MEN_DESK_VIEW" ), -1 );
837   createMenu( separator(), viewMenu, -1, 20, -1 );
838 #ifdef USE_SALOME_STYLE
839   createMenu( StyleId, viewMenu, 20, -1 );
840 #endif // USE_SALOME_STYLE
841   createMenu( FullScreenId, viewMenu, 20, -1 );
842   createMenu( separator(), viewMenu, -1, 20, -1 );
843   createMenu( ModulesListId, viewMenu );
844
845   int modTBar = createTool( tr( "INF_TOOLBAR_MODULES" ),    // title (language-dependant)
846                             QString( "SalomeModules" ) );   // name (language-independant)
847   createTool( ModulesListId, modTBar );
848 }
849
850 /*!Create actions for installed extensions:*/
851 void LightApp_Application::addExtensionsActions(LightApp_ModuleAction* moduleAction)
852 {
853   if (!moduleAction)
854   {
855     MESSAGE("Couldn't get a moduleAction! Return.");
856     return;
857   }
858
859   // It should be set on the app start if we use an --on_demand 1 command line option
860   auto extRootDir = getenv(salomeAppDir);
861   if (!extRootDir)
862   {
863     // It's ok if we don't use --on_demand
864     return;
865   }
866   SCRUTE(extRootDir);
867
868    // Import Python module that manages SALOME extensions.
869   PyLockWrapper lck; // acquire GIL
870   PyObjWrapper extensionQuery = PyImport_ImportModule((char*)"SalomeOnDemandTK.extension_query");
871   PyObjWrapper installedExtensions = PyObject_CallMethod(
872       extensionQuery, (char*)"ext_by_name", (char*)"s", extRootDir);
873   if (!installedExtensions)
874   {
875     return;
876   }
877
878   // Iterate installed extensions
879   for (Py_ssize_t pos = 0; pos < PyList_Size(installedExtensions); ++pos)
880   {
881     // Get the current ext name
882     auto extNameItem = PyList_GetItem(installedExtensions, pos);
883     QString extName(PyUnicode_AsUTF8(extNameItem));
884     SCRUTE(extName.toStdString());
885
886     moduleAction->insertExtension(extName);
887   }
888
889   // Udate actions only once after all of them were already inserted
890   moduleAction->updateExtActions();
891 }
892
893 /*!
894   Customize actions.
895 */
896 void LightApp_Application::customize()
897 {
898   // List of modules
899   LightApp_ModuleAction* moduleAction = qobject_cast<LightApp_ModuleAction*>( action( ModulesListId ) );
900   // a. regular modules were added in createActions() method
901   // b. here we add custom modules (manually added by the user)
902   if ( HAS_SALOME_ON_DEMAND )
903   {
904     // Update rc file
905     updateSalomeApprc();
906
907     QStringList modList = resourceMgr()->stringValue( "launch", "user_modules" ).split( ";", QString::SkipEmptyParts );
908     foreach ( QString aModule, modList )
909       addUserModule(  aModule, resourceMgr()->stringValue( "user_modules", aModule ) );
910   }
911   else
912   {
913     moduleAction->setModeEnabled( LightApp_ModuleAction::AddRemove, false );
914   }
915 }
916
917 /*!
918   Update rc file with SALOME_APPLICATION_DIR or with SALOME_MODULES.
919 */
920 void LightApp_Application::updateSalomeApprc()
921 {
922     SUIT_ResourceMgr* resMgr = resourceMgr();
923     auto extRootDir = getenv(salomeAppDir);
924
925     QString salomemodules(getenv("SALOME_MODULES"));
926     if(salomemodules.isEmpty())
927         AddComponents_from_salomeappdir(  QDir(extRootDir), resMgr );
928     else
929         AddComponents_from_salomemodules(salomemodules, QDir(extRootDir), resMgr);
930 }
931
932 /*!On module activation action.*/
933 void LightApp_Application::onModuleActivation( const QString& modTitle )
934 {
935   // Force user to create/open a study before module activation
936   QPixmap icon = moduleIcon( modTitle );
937   bool cancelled = false;
938
939   while ( !modTitle.isEmpty() && !activeStudy() && !cancelled ){
940     LightApp_ModuleDlg aDlg( desktop(), modTitle, icon );
941     QMap<int, QString> opmap = activateModuleActions();
942     for ( QMap<int, QString>::ConstIterator it = opmap.begin(); it != opmap.end(); ++it )
943       aDlg.addButton( it.value(), it.key() );
944
945     int res = aDlg.exec();
946     if ( res ) {
947       // some operation is selected
948       moduleActionSelected( res );
949     }
950     else {
951       // cancelled
952       putInfo( tr("INF_CANCELLED") );
953       emit moduleActivated( QString() );
954       cancelled = true;
955     }
956   }
957
958   if ( !cancelled )
959     activateModule( modTitle );
960 }
961
962 /*!On extension adding action.*/
963 void LightApp_Application::onExtAdding()
964 {
965   // Show dialog to browse a salome extension file
966   QStringList filters = (QStringList() << tr("Salome extension files") + " (*.salomex)" << tr("All files") + " (*)");
967   QStringList paths = getOpenFileNames(QString(), filters.join(";;"), QString(), desktop());
968   if (paths.isEmpty())
969   {
970     MESSAGE("Adding an extension was cancelled.");
971     return;
972   }
973
974   LightApp_ModuleAction* moduleAction = qobject_cast<LightApp_ModuleAction*>(action(ModulesListId));
975   if (!moduleAction)
976   {
977     MESSAGE("Couldn't get a moduleAction! Return.");
978     return;
979   }
980
981   // It should be set on the app start
982   auto extRootDir = getenv(salomeAppDir);
983   if (!extRootDir)
984   {
985     SUIT_MessageBox::warning(desktop(), tr("WRN_WARNING"), tr("WRN_SALOME_APPLICATION_DIR"));
986     return;
987   }
988   SCRUTE(extRootDir);
989
990   // We'll load all the extensions modules from this path
991   auto SalomeExtDir = QDir::cleanPath(QString(extRootDir) + QDir::separator() + "__SALOME_EXT__");
992   SCRUTE(SalomeExtDir.toStdString());
993
994   // Import Python module that manages SALOME extensions.
995   // It seems to be faster to lock and unlock once than on each iteration,
996   // but I didn't compare the performance for each case.
997   PyLockWrapper lck; // acquire GIL
998   PyObjWrapper extensionUnpacker = PyImport_ImportModule((char*)"SalomeOnDemandTK.extension_unpacker");
999   PyObjWrapper runSalomeOnDemand = PyImport_ImportModule((char*)"runSalomeOnDemand");
1000
1001   // Loop via selected extensions files
1002   foreach(QString path, paths)
1003   {
1004     std::string extPath = path.toStdString();
1005     SCRUTE(extPath);
1006
1007     PyObjWrapper unpackedModules = PyObject_CallMethod(
1008       extensionUnpacker, (char*)"install_salomex", (char*)"s", extPath.c_str());
1009     if (!unpackedModules || unpackedModules == Py_None)
1010     {
1011       SUIT_MessageBox::warning(desktop(), tr("WRN_WARNING"), tr("WRN_FAILED_UNPACK_EXTENSION").arg(path) );
1012       continue;
1013     }
1014
1015     PyObjWrapper pKeys = PyDict_Keys(unpackedModules);
1016     // Iterate all the components (modules) for this extension
1017     for (Py_ssize_t pos = 0; pos < PyDict_Size(unpackedModules); ++pos)
1018     {
1019       auto moduleNameItem = PyList_GetItem(pKeys, pos);
1020       auto interactiveItem = PyDict_GetItem(unpackedModules, moduleNameItem);
1021
1022       QString moduleName(PyUnicode_AsUTF8(moduleNameItem));
1023       SCRUTE(moduleName.toStdString());
1024       addUserModule(moduleName, SalomeExtDir, PyObject_IsTrue(interactiveItem));
1025     }
1026
1027     // Add an extension to GUI
1028     QFileInfo extFileInfo(path);
1029     QString extName = extFileInfo.baseName();
1030     if (moduleAction)
1031     {
1032       moduleAction->insertExtension(extName);
1033     }
1034
1035     // Update environment of salome
1036     PyObjWrapper update_env = PyObject_CallMethod(
1037       runSalomeOnDemand, (char*)"set_selext_env", (char*)"ss", extRootDir, extName.toStdString().c_str());
1038     if (!update_env)
1039     {
1040       SUIT_MessageBox::warning(desktop(), tr("WRN_WARNING"), tr("WRN_FAILED_UPDATE_ENV").arg(extName + "_env.py") );
1041       continue;
1042     }
1043   }
1044
1045   // Udate actions only once after all of them were already inserted
1046   moduleAction->updateExtActions();
1047 }
1048
1049 /*Add user module.*/
1050 bool LightApp_Application::addUserModule( const QString& name, const QString& root, bool interactive )
1051 {
1052   if ( name.isEmpty() || root.isEmpty() )
1053     return false;
1054
1055   if ( !moduleTitle( name ).isEmpty() ) // module alread in current session
1056   {
1057     if ( interactive )
1058       SUIT_MessageBox::warning( desktop(), tr( "WRN_WARNING" ), tr( "WRN_MODULE_DUPLICATED" ).arg( name ) );
1059     return false;
1060   }
1061   if ( !QFileInfo( root ).exists() ) // root directory does not exist
1062   {
1063     if ( interactive )
1064       SUIT_MessageBox::warning( desktop(), tr( "WRN_WARNING" ), tr( "WRN_MODULE_ROOT_DOES_NOT_EXIST" ).arg( root ) );
1065     return false;
1066   }
1067   // resources directory
1068   QString resDir = Qtx::joinPath( QStringList() << root << "share" << "salome" << "resources" << name.toLower() );
1069   if ( !QFileInfo( resDir ).exists() ) // resources directory does not exist
1070   {
1071     if ( interactive )
1072       SUIT_MessageBox::warning( desktop(), tr( "WRN_WARNING" ), tr( "WRN_MODULE_BAD_RESDIR" ).arg( resDir ) );
1073     return false;
1074   }
1075
1076   SUIT_ResourceMgr* resMgr = resourceMgr();
1077
1078   // read XML configuration file
1079   resMgr->setConstant(QString("%1_ROOT_DIR").arg(name), root);
1080   if (!resMgr->addResource(resDir)) // cannot read configuration
1081   {
1082     if ( interactive )
1083       SUIT_MessageBox::warning( desktop(), tr( "WRN_WARNING" ), tr( "WRN_MODULE_CANNOT_READ_CFG" ).arg( resDir ) );
1084     return false;
1085   }
1086   // fill in information about module
1087   if ( !appendModuleInfo( name ) ) // cannot append module information to internal table
1088   {
1089     if ( interactive )
1090       SUIT_MessageBox::warning( desktop(), tr( "WRN_WARNING" ), tr( "WRN_MODULE_BAD_CFG_FILE" ).arg( name ) );
1091     return false;
1092   }
1093
1094   // load translations
1095   resMgr->loadLanguage(name);
1096
1097   // Do all the GUI related stuff only if the module supports that.
1098   // We already did check for GUI inside CAM_Application::appendModuleInfo, but
1099   // need to do that again.
1100   // TODO: Maybe it's better to return ModuleInfo from appendModuleInfo() and check status.
1101   const QString title = resMgr->stringValue(name, "name", QString()).trimmed();
1102   if (resMgr->booleanValue(name, "gui", false) || !title.isEmpty() && interactive)
1103   {
1104     // Append module to the menu / toolbar
1105     LightApp_ModuleAction* moduleAction = qobject_cast<LightApp_ModuleAction*>(action(ModulesListId));
1106     if (moduleAction)
1107     {
1108       // Scale icon to 20x20 pix
1109       moduleAction->insertModule(moduleTitle(name), moduleIcon(moduleTitle(name), 20), true);
1110     }
1111   }
1112
1113   // add empty page to Preferences dialog
1114   LightApp_Preferences* prefs = preferences();
1115   if ( prefs && !prefs->hasModule( moduleTitle( name ) ) )
1116   {
1117     int prefId = prefs->addPreference( moduleTitle( name ) );
1118     prefs->setItemIcon( prefId, moduleIcon( moduleTitle( name ), 20 ) ); // scale icon to 20x20 pix
1119     LightApp_Module* m = qobject_cast<LightApp_Module*>( module( moduleTitle( name ) ) );
1120     if ( m )
1121     {
1122       m->createPreferences();
1123       emptyPreferences( moduleTitle( name ) );
1124     }
1125   }
1126   // add Help items
1127   createHelpItems( moduleTitle( name ) );
1128   // extend module catalog
1129   QString catalogue = QDir( resDir ).filePath( QString( "%1Catalog.xml" ).arg( name ) );
1130   addCatalogue( name, catalogue );
1131   // update windows (in particular, Info panel)
1132   updateWindows();
1133   // save module in the resource manager
1134   if ( interactive )
1135   {
1136     QStringList customModules = resMgr->stringValue("launch", "user_modules").split(";", QString::SkipEmptyParts);
1137     customModules << name;
1138     customModules.removeDuplicates();
1139     resMgr->setValue( "launch", "user_modules", customModules.join( ";" ) );
1140     resMgr->setValue( "user_modules", name, root );
1141   }
1142   return true;
1143 }
1144
1145 /*!Remove user module from UI.*/
1146 void LightApp_Application::removeUserModule(const QString& moduleInnerName, LightApp_ModuleAction* moduleAction)
1147 {
1148   MESSAGE("Remove a module from UI...");
1149   SCRUTE(moduleInnerName.toStdString());
1150
1151   // There is a some confusion point, because now we have a module's 'inner' name
1152   // from the extension's salomexd file.
1153   // But, in the next GUI methods we need to use a module title (user name).
1154   // For example, PYHELLO (inner name) and PyHello (user name to display in GUI).
1155   // Then, from the inner module's name we need to get a user one.
1156   QString moduleUserName = moduleTitle(moduleInnerName);
1157   SCRUTE(moduleUserName.toStdString());
1158
1159   // Set current state in modules combo box
1160   // Don't confuse again, because activeModule()->moduleName() returns a module title, not an inner one!
1161   if (activeModule() && activeModule()->moduleName() == moduleUserName)
1162     activateModule("");
1163
1164   // Remove from "Modules" menu and toolbar
1165   if (moduleAction)
1166   {
1167     moduleAction->removeModule(moduleUserName);
1168   }
1169
1170   // Remove Help menu items
1171   removeHelpItems(moduleUserName);
1172
1173   // Remove Preferences
1174   LightApp_Preferences* prefs = preferences();
1175   if (prefs)
1176     prefs->removeModule(moduleUserName);
1177
1178   // Remove settings
1179   // Here we use an inner module name!
1180   QStringList customModules = resourceMgr()->stringValue("launch", "user_modules").split(";", QString::SkipEmptyParts);
1181   customModules.removeAll(moduleInnerName);
1182   resourceMgr()->setValue("launch", "user_modules", customModules.join(";"));
1183   removeModuleInfo(moduleInnerName);
1184 }
1185
1186 /*!On module removing action.*/
1187 void LightApp_Application::onExtRemoving(const QString& title)
1188 {
1189   MESSAGE("Remove an extension...");
1190   std::string extName = title.toStdString();
1191   SCRUTE(extName);
1192
1193   // Ask user if he's ready to completely remove an extension and all its modules.
1194   int answer = SUIT_MessageBox::question(
1195     desktop(),
1196     tr("TLT_REMOVE_EXTENSION"),
1197     tr("QUE_REMOVE_EXTENSION").arg(title),
1198     SUIT_MessageBox::Ok | SUIT_MessageBox::Cancel,
1199     SUIT_MessageBox::Ok
1200   );
1201
1202   if (answer == SUIT_MessageBox::Cancel)
1203   {
1204     MESSAGE("Removing of an extension was cancelled");
1205     return; // cancelled
1206   }
1207   
1208   if (activeStudy() && activeStudy()->isModified() && !onSaveDoc())
1209   {
1210     // doc is not saved, or saving cancelled
1211     SUIT_MessageBox::warning(
1212       desktop(),
1213       tr("WRN_WARNING"), tr("WRN_CANCEL_REMOVE_EXTENSION_UNSAVE").arg(title)
1214     );
1215
1216     return;
1217   }
1218
1219   // It should be set on the app start
1220   auto extRootDir = getenv(salomeAppDir);
1221   if (!extRootDir)
1222   {
1223     SUIT_MessageBox::warning(desktop(), tr("WRN_WARNING"), tr("WRN_SALOME_APPLICATION_DIR"));
1224     return;
1225   }
1226   SCRUTE(extRootDir);
1227
1228   // Import Python module that manages SALOME extensions.
1229   PyLockWrapper lck; // acquire GIL
1230   PyObjWrapper extensionRemover = PyImport_ImportModule((char*)"SalomeOnDemandTK.extension_remover");
1231   PyObjWrapper removedModules = PyObject_CallMethod(
1232       extensionRemover, (char*)"remove_salomex", (char*)"ss", extRootDir, extName.c_str());
1233   if (!removedModules || removedModules == Py_None)
1234   {
1235     SUIT_MessageBox::warning(desktop(), tr("WRN_WARNING"), tr("WRN_FAILED_REMOVE_EXTENSION").arg(title));
1236     return;
1237   }
1238
1239   // We need it to remove ext and modules from UI
1240   LightApp_ModuleAction* moduleAction = qobject_cast<LightApp_ModuleAction*>(action(ModulesListId));
1241   if (!moduleAction)
1242   {
1243     MESSAGE("Cannot get a pointer to LightApp_ModuleAction! Removing from menue and toolbars will skipped.");
1244   }
1245
1246   // Module's content was already removed on python remove_salomex call,
1247   // then all we do next - just remove UI items.
1248   for (Py_ssize_t pos = 0; pos < PyList_Size(removedModules); ++pos)
1249   {
1250     // Get the current module's name
1251     auto moduleNameItem = PyList_GetItem(removedModules, pos);
1252     const QString moduleInnerName(PyUnicode_AsUTF8(moduleNameItem));
1253
1254     removeUserModule(moduleInnerName, moduleAction);
1255   }
1256
1257   // Remove an ext from UI
1258   if (moduleAction)
1259   {
1260     moduleAction->removeExtension(title);
1261   }
1262
1263   // Update windows (in particular, Info panel)
1264   updateWindows();
1265 }
1266
1267 /*!On show extension info action.*/
1268 void LightApp_Application::onShowExtInfo()
1269 {
1270   // Show dialog with information about loaded salome extensions
1271   LightApp_ExtInfoDlg dlg(desktop());
1272   dlg.exec();
1273 }
1274
1275 /*!Default module activation.*/
1276 QString LightApp_Application::defaultModule() const
1277 {
1278   QStringList aModuleNames;
1279   modules( aModuleNames, false ); // obtain a complete list of module names for the current configuration
1280   //! If there's the one and only module --> activate it automatically
1281   //! TODO: Possible improvement - default module can be taken from preferences
1282   return aModuleNames.count() > 1 ? "" : ( aModuleNames.count() ? aModuleNames.first() : "" );
1283 }
1284
1285 /*!On new window slot.*/
1286 void LightApp_Application::onNewWindow()
1287 {
1288   const QObject* obj = sender();
1289   if ( !obj || !obj->inherits( "QAction" ) )
1290     return;
1291
1292   QString type;
1293   int id = actionId( (QAction*)obj );
1294   switch ( id )
1295   {
1296 #ifndef DISABLE_GLVIEWER
1297   case NewGLViewId:
1298     type = GLViewer_Viewer::Type();
1299     break;
1300 #endif
1301 #ifndef DISABLE_PLOT2DVIEWER
1302   case NewPlot2dId:
1303     type = Plot2d_Viewer::Type();
1304     break;
1305 #endif
1306 #ifndef DISABLE_OCCVIEWER
1307   case NewOCCViewId:
1308     type = OCCViewer_Viewer::Type();
1309     break;
1310 #endif
1311 #ifndef DISABLE_VTKVIEWER
1312   case NewVTKViewId:
1313     type = VTKViewer_Viewer::Type();
1314     break;
1315 #endif
1316 #ifndef DISABLE_QXGRAPHVIEWER
1317   case NewQxSceneViewId:
1318     type = QxScene_Viewer::Type();
1319     break;
1320 #endif
1321 #ifndef DISABLE_GRAPHICSVIEW
1322   case NewGraphicsViewId:
1323     type = GraphicsView_Viewer::Type();
1324     break;
1325 #endif
1326 #ifndef DISABLE_PVVIEWER
1327   case NewPVViewId:
1328     type = PVViewer_Viewer::Type();
1329     break;
1330 #endif
1331 #ifndef DISABLE_PYVIEWER
1332   case NewPyViewerId:
1333     type = PyViewer_Viewer::Type();
1334     break;
1335 #endif
1336 #ifndef DISABLE_PV3DVIEWER
1337   case NewPV3DViewId:
1338     type = PV3DViewer_ViewModel::Type();
1339     break;
1340 #endif
1341   }
1342
1343   if ( !type.isEmpty() )
1344     createViewManager( type );
1345 }
1346
1347 /*!
1348   SLOT: Creates new document
1349 */
1350 void LightApp_Application::onNewDoc()
1351 {
1352   if ( !checkExistingDoc() )
1353     return;
1354
1355   //asl: fix for 0020515
1356   saveDockWindowsState();
1357
1358   CAM_Application::onNewDoc();
1359 }
1360
1361 /*!
1362   SLOT: Opens new document
1363 */
1364 void LightApp_Application::onOpenDoc()
1365 {
1366   SUIT_Study* study = activeStudy();
1367
1368   if ( !checkExistingDoc( false ) )
1369     return;
1370
1371   QString aName = getFileName( true, QString(), getFileFilter( true ), QString(), 0 );
1372   if ( aName.isNull() ) //Cancel
1373     return;
1374
1375   onOpenDoc( aName );
1376
1377   if ( !study ) // new study will be create in THIS application
1378   {
1379     updateWindows();
1380     updateViewManagers();
1381   }
1382 }
1383
1384 bool LightApp_Application::canOpenDoc( const QString& )
1385 {
1386   return true;
1387 }
1388
1389 /*!
1390   SLOT: Opens new document.
1391   \param aName - name of file
1392 */
1393 bool LightApp_Application::onOpenDoc( const QString& aName )
1394 {
1395   if ( !canOpenDoc(aName)) {
1396     bool showError = !property("open_study_from_command_line").isValid() ||
1397       !property("open_study_from_command_line").toBool();
1398
1399     putInfo( tr("OPEN_DOCUMENT_PROBLEM") );
1400     if ( showError )
1401       SUIT_MessageBox::critical( desktop(), tr("ERR_ERROR"), tr("OPEN_DOCUMENT_PROBLEM"));
1402
1403     return false;
1404   }
1405
1406   closeDoc(false);
1407
1408   if ( !checkExistingDoc() )
1409     return false;
1410
1411   saveDockWindowsState();
1412
1413   // We should take mru action first because this application instance can be deleted later.
1414   QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
1415
1416   bool res = CAM_Application::onOpenDoc( aName );
1417
1418   if ( mru )
1419   {
1420     if ( res )
1421       mru->insert( aName );
1422     else
1423       mru->remove( aName );
1424   }
1425   return res;
1426 }
1427
1428 /*!
1429   SLOT: Displays "About" message box
1430 */
1431 void LightApp_Application::onHelpAbout()
1432 {
1433   LightApp_AboutDlg dlg( applicationName(), applicationVersion(), desktop() );
1434   dlg.exec();
1435 }
1436
1437 /*!
1438   Private SLOT: Called on selection is changed
1439   Dispatchs active module that selection is changed
1440 */
1441 void LightApp_Application::onSelection()
1442 {
1443   //MESSAGE("onSelection")
1444   onSelectionChanged();
1445
1446   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
1447     ((LightApp_Module*)activeModule())->selectionChanged();
1448 }
1449
1450 /*!
1451   Sets active study.
1452  \param study - SUIT_Study.
1453 */
1454 void LightApp_Application::setActiveStudy( SUIT_Study* study )
1455 {
1456   CAM_Application::setActiveStudy( study );
1457 }
1458
1459 /*!
1460   Enables/Disables menu items and toolbar buttons. Rebuild menu
1461 */
1462 void LightApp_Application::updateCommandsStatus()
1463 {
1464   CAM_Application::updateCommandsStatus();
1465   QAction* a = 0;
1466
1467 #ifndef DISABLE_GLVIEWER
1468   a = action( NewGLViewId );
1469   if( a )
1470     a->setEnabled( activeStudy() );
1471 #endif
1472
1473 #ifndef DISABLE_PLOT2DVIEWER
1474   a = action( NewPlot2dId );
1475   if( a )
1476     a->setEnabled( activeStudy() );
1477 #endif
1478
1479 #ifndef DISABLE_OCCVIEWER
1480   a = action( NewOCCViewId );
1481   if( a )
1482     a->setEnabled( activeStudy() );
1483 #endif
1484
1485 #ifndef DISABLE_VTKVIEWER
1486   a = action( NewVTKViewId );
1487   if( a )
1488     a->setEnabled( activeStudy() );
1489 #endif
1490
1491 #ifndef DISABLE_QXGRAPHVIEWER
1492   a = action( NewQxSceneViewId );
1493   if( a )
1494     a->setEnabled( activeStudy() );
1495 #endif
1496
1497 #ifndef DISABLE_GRAPHICSVIEW
1498   a = action( NewGraphicsViewId );
1499   if( a )
1500     a->setEnabled( activeStudy() );
1501 #endif
1502
1503 #ifndef DISABLE_PVVIEWER
1504   a = action( NewPVViewId );
1505   if( a )
1506     a->setEnabled( activeStudy() );
1507 #endif
1508
1509 #ifndef DISABLE_PYVIEWER
1510   a = action( NewPyViewerId );
1511   if( a )
1512     a->setEnabled( activeStudy() );
1513 #endif
1514
1515 #ifndef DISABLE_PV3DVIEWER
1516   a = action( NewPV3DViewId );
1517   if( a )
1518     a->setEnabled( activeStudy() );
1519 #endif
1520 }
1521
1522 /*!
1523   \class RunBrowser
1524   Runs system command in separate thread
1525 */
1526 class RunBrowser: public QThread
1527 {
1528 public:
1529   static void execute( LightApp_Application* application,
1530                        const QString& browser,
1531                        const QString& parameters,
1532                        const QString& url )
1533   {
1534     (new RunBrowser( application, browser, parameters, url ))->start();
1535   }
1536
1537 protected:
1538   RunBrowser( LightApp_Application* application,
1539               const QString&        browser,
1540               const QString&        parameters,
1541               const QString&        url)
1542     : myApplication( application ),
1543       myBrowser( browser ),
1544       myParameters( parameters ),
1545       myUrl( url )
1546   {
1547     if ( !myUrl.startsWith( "http", Qt::CaseInsensitive ) )
1548     {
1549       // normalize path
1550       if ( myUrl.startsWith( "file://", Qt::CaseInsensitive ) )
1551         myUrl = myUrl.remove( 0, QString( "file://" ).count() );
1552       // For the external browser we always specify 'file://' protocol,
1553       // because some web browsers (e.g. Mozilla Firefox) can't open local file without protocol.
1554       myUrl = myUrl.prepend( "file://" );
1555     }
1556     connect(this, SIGNAL(finished()), SLOT(deleteLater()));
1557   }
1558
1559   virtual void run()
1560   {
1561     if ( !myBrowser.isEmpty() && !myUrl.isEmpty() )
1562     {
1563       QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
1564 #ifdef WIN32
1565       QString cmdLine = QString( "\"%1\" %2 \"%3\"" ).arg( myBrowser, myParameters, myUrl );
1566 #else
1567       QString cmdLine = QString( "%1 %2 \"%3\"" ).arg( myBrowser, myParameters, myUrl );
1568       // remove LD_LIBRARY_PATH from the environement before starting launcher to avoid bad interactions.
1569       // (especially in the case of universal binaries)
1570       env.remove("LD_LIBRARY_PATH");
1571 #endif
1572       QProcess* proc = new QProcess();
1573       proc->setProcessEnvironment(env);
1574       proc->start( cmdLine );
1575       if ( !proc->waitForStarted() )
1576       {
1577         SALOME_CustomEvent* ce2000 = new SALOME_CustomEvent( 2000 );
1578         QString* msg = new QString( QObject::tr( "EXTERNAL_BROWSER_CANNOT_SHOW_PAGE" ).arg( myBrowser, myUrl ) );
1579         ce2000->setData( msg );
1580         QApplication::postEvent( myApplication, ce2000 );
1581       }
1582     }
1583   }
1584
1585 private:
1586   LightApp_Application* myApplication;
1587   QString               myBrowser;
1588   QString               myParameters;
1589   QString               myUrl;
1590 };
1591
1592 void LightApp_Application::showHelp( const QString& path )
1593 {
1594   SUIT_ResourceMgr* resMgr = resourceMgr();
1595
1596 #if DISABLE_QTXWEBBROWSER
1597   bool useExternalBrowser = true;
1598 #else
1599   bool useExternalBrowser = resMgr->booleanValue("ExternalBrowser", "use_external_browser", false );
1600 #endif
1601
1602   if ( useExternalBrowser )
1603   {
1604 #ifdef WIN32
1605     QString browser = resMgr->stringValue( "ExternalBrowser", "winapplication" ) ;
1606 #else
1607     QString browser = resMgr->stringValue( "ExternalBrowser", "application" );
1608 #endif
1609     QString parameters = resMgr->stringValue("ExternalBrowser", "parameters");
1610
1611     if ( !browser.isEmpty() )
1612     {
1613       RunBrowser::execute( this, browser, parameters, path );
1614     }
1615     else
1616     {
1617       if ( SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "DEFINE_EXTERNAL_BROWSER" ),
1618                                       SUIT_MessageBox::Yes | SUIT_MessageBox::No,
1619                                       SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes )
1620       {
1621         QStringList path;
1622         path << tr( "PREF_CATEGORY_SALOME" ) << tr( "PREF_TAB_GENERAL" )
1623              << tr( "PREF_GROUP_EXT_BROWSER" ) << tr( "PREF_APP" );
1624         showPreferences( path );
1625       }
1626     }
1627   }
1628   else
1629   {
1630     QStringList cmdLine;
1631     cmdLine << QString( "--language=%1" ).arg( resMgr->stringValue( "language", "language" ) );
1632     cmdLine << QString( "--add=%1" ).arg( QApplication::instance()->applicationPid() );
1633     cmdLine << path;
1634     QProcess::startDetached( "HelpBrowser", cmdLine );
1635   }
1636 }
1637
1638 /*!
1639   SLOT: Displays help contents for choosen module
1640 */
1641 void LightApp_Application::onHelpContentsModule()
1642 {
1643   const QAction* a = (QAction*) sender();
1644   QString helpFile = a->data().toString();
1645   if ( !helpFile.isEmpty() )
1646     showHelp( helpFile );
1647 }
1648
1649 /*!
1650   SLOT: Displays contextual help (e.g. for choosen dialog)
1651 */
1652 void LightApp_Application::onHelpContextModule( const QString& component,
1653                                                 const QString& url,
1654                                                 const QString& context )
1655 {
1656   QString path = url;
1657   if ( !url.startsWith( "http", Qt::CaseInsensitive ) )
1658   {
1659     // local file path
1660     QFileInfo fi( url );
1661     if ( fi.isRelative() && !component.isEmpty() )
1662     {
1663       QString rootDir = Qtx::getenv( (component + "_ROOT_DIR").toLatin1().constData() );
1664       if ( !rootDir.isEmpty() )
1665       {
1666         path = (QStringList() << rootDir << "share" << "doc" << "salome" << "gui" << component << url).join( QDir::separator() );
1667       }
1668     }
1669   }
1670   if ( !context.isEmpty() )
1671   {
1672     path += QString( "#%1" ).arg( context );
1673   }
1674   showHelp( path );
1675 }
1676
1677 /*!
1678   Sets enable or disable some actions on selection changed.
1679 */
1680 void LightApp_Application::onSelectionChanged()
1681 {
1682   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
1683   bool canCopy  = m ? m->canCopy() : false;
1684   bool canPaste = m ? m->canPaste() : false;
1685
1686   action( EditCopyId )->setEnabled(canCopy);
1687   action( EditPasteId )->setEnabled(canPaste);
1688 }
1689
1690 /*!
1691   SLOT: Performs some actions when dockable windows are triggered
1692 */
1693 void LightApp_Application::onDockWindowVisibilityChanged( bool )
1694 {
1695 }
1696
1697 QWidget* LightApp_Application::dockWindow( const int id ) const
1698 {
1699   QWidget* wid = 0;
1700   if ( myWin.contains( id ) )
1701     wid = myWin[id];
1702   return wid;
1703 }
1704
1705 QDockWidget* LightApp_Application::windowDock( QWidget* wid ) const
1706 {
1707   if ( !wid )
1708     return 0;
1709
1710   QDockWidget* dock = 0;
1711   QWidget* w = wid->parentWidget();
1712   while ( w && !dock )
1713   {
1714     dock = ::qobject_cast<QDockWidget*>( w );
1715     w = w->parentWidget();
1716   }
1717   return dock;
1718 }
1719
1720 void LightApp_Application::insertDockWindow( const int id, QWidget* wid )
1721 {
1722   if ( !wid )
1723     return;
1724
1725   if ( wid != dockWindow( id ) )
1726     removeDockWindow( id );
1727
1728   myWin.insert( id, wid );
1729
1730   QtxDockWidget* dock = new QtxDockWidget( true, desktop() );
1731   if ( id == WT_InfoPanel ) {
1732     // Info panel's position is strongly limited to the right area;
1733     // It is not movable and not floatable.
1734     dock->setAllowedAreas( Qt::RightDockWidgetArea );
1735     dock->setFeatures( QDockWidget::DockWidgetClosable );
1736     connect( dock, SIGNAL( aboutToShow()), this, SLOT( onInfoPanelShown() ) );
1737   }
1738   else {
1739     dock->setFeatures( QDockWidget::AllDockWidgetFeatures );
1740   }
1741   connect( dock, SIGNAL(  destroyed( QObject* ) ), this, SLOT( onWCDestroyed( QObject* ) ) );
1742
1743   dock->setObjectName( wid->objectName().isEmpty() ? QString( "window_%1" ).arg( id ) :
1744                        QString( "%1Dock" ).arg( wid->objectName() ) );
1745   dock->setWidget( wid );
1746   dock->toggleViewAction()->setData( QVariant( wid->objectName() ) );
1747   connect( dock->toggleViewAction(), SIGNAL( triggered( bool ) ),
1748            this, SLOT( onDockWindowVisibilityChanged( bool ) ) );
1749
1750   QKeySequence accel = wid->property( "shortcut" ).value<QKeySequence>();
1751   if ( !accel.isEmpty() )
1752     dock->toggleViewAction()->setShortcut( accel );
1753
1754   dock->show();
1755 }
1756
1757 void LightApp_Application::removeDockWindow( const int id )
1758 {
1759   QWidget* wid = dockWindow( id );
1760   if ( !wid )
1761     return;
1762
1763   myWin.remove( id );
1764
1765   QDockWidget* dock = windowDock( wid );
1766   if ( !dock )
1767     return;
1768
1769   dock->setWidget( 0 );
1770   wid->setParent( 0 );
1771   wid->setVisible( false );
1772   delete dock;
1773 }
1774
1775 void LightApp_Application::placeDockWindow( const int id, Qt::DockWidgetArea place )
1776 {
1777   QDockWidget* dock = windowDock( dockWindow( id ) );
1778   if ( dock && desktop() ) {
1779     desktop()->addDockWidget( place, dock );
1780     QtxDockAction* a = qobject_cast<QtxDockAction*>( action( ViewWindowsId ) );
1781     if ( a ) a->update();
1782   }
1783 }
1784
1785 /*!
1786   Gets window.
1787   \param flag - key for window
1788   Flag used how identificator of window in windows list.
1789 */
1790 QWidget* LightApp_Application::getWindow( const int flag)
1791 {
1792   QWidget* wid = dockWindow( flag );
1793   if ( !wid )
1794     insertDockWindow( flag, wid = createWindow( flag ) );
1795
1796   QMap<int, int> winMap;
1797   currentWindows( winMap );
1798   if ( winMap.contains( flag ) )
1799     placeDockWindow( flag, (Qt::DockWidgetArea)winMap[flag] );
1800
1801   return wid;
1802 }
1803
1804 /*!
1805   \return Object Browser
1806 */
1807 SUIT_DataBrowser* LightApp_Application::objectBrowser()
1808 {
1809   return qobject_cast<SUIT_DataBrowser*>( dockWindow( WT_ObjectBrowser ) );
1810 }
1811
1812 QtxInfoPanel* LightApp_Application::infoPanel()
1813 {
1814   return qobject_cast<QtxInfoPanel *>( dockWindow( WT_InfoPanel ));
1815 }
1816
1817 /*!
1818   \return Log Window
1819 */
1820 LogWindow* LightApp_Application::logWindow()
1821 {
1822   return qobject_cast<LogWindow*>( dockWindow( WT_LogWindow ) );
1823 }
1824
1825 #ifndef DISABLE_PYCONSOLE
1826 /*!
1827   This returns the python console integrated to the GUI. Depending
1828   when you request the python console, this function could return
1829   null. Then the optional parameter force (default to false) can be
1830   set to force the creation of the python console if it is not done
1831   already.
1832   \param force - if true, the pythonConsole is created if it does not exist yet
1833   \return Python Console
1834 */
1835 PyConsole_Console* LightApp_Application::pythonConsole(const bool force)
1836 {
1837   QWidget* wid = dockWindow( WT_PyConsole );
1838   if ( !wid && force==true) {
1839     wid = getWindow(WT_PyConsole);
1840   }
1841   return qobject_cast<PyConsole_Console*>( wid );
1842 }
1843 #endif
1844
1845 /*!
1846   Updates object browser and maybe data models
1847   \param updateModels - if it is true, then data models are updated
1848 */
1849 void LightApp_Application::updateObjectBrowser( const bool updateModels )
1850 {
1851   // update existing data models
1852   if ( updateModels )
1853   {
1854     const bool isAutoUpdate = objectBrowser() ? objectBrowser()->autoUpdate() : true;
1855     if ( objectBrowser() )
1856       objectBrowser()->setAutoUpdate( false );
1857
1858     LightApp_Study* study = dynamic_cast<LightApp_Study*>(activeStudy());
1859     if ( study ) {
1860       CAM_Study::ModelList dm_list;
1861       study->dataModels( dm_list );
1862       QListIterator<CAM_DataModel*> it( dm_list );
1863       while ( it.hasNext() ) {
1864         CAM_DataModel* camDM = it.next();
1865         if ( camDM && camDM->inherits( "LightApp_DataModel" ) )
1866           ((LightApp_DataModel*)camDM)->update();
1867       }
1868     }
1869
1870     if( objectBrowser() )
1871       objectBrowser()->setAutoUpdate( isAutoUpdate );
1872   }
1873
1874   if ( objectBrowser() ) {
1875     objectBrowser()->updateGeometry();
1876     objectBrowser()->updateTree( 0, false );
1877   }
1878 }
1879
1880 /*!
1881   \return preferences
1882 */
1883 LightApp_Preferences* LightApp_Application::preferences() const
1884 {
1885   return preferences( false );
1886 }
1887
1888 /*!
1889   \return first view manager of some type
1890   \param vmType - type of view manager
1891   \param create - is it necessary to create view manager in case, when there is no manager of such type
1892 */
1893 SUIT_ViewManager* LightApp_Application::getViewManager( const QString& vmType, const bool create )
1894 {
1895   SUIT_ViewManager* aVM = viewManager( vmType );
1896   SUIT_ViewManager* anActiveVM = CAM_Application::activeViewManager();
1897   MESSAGE("vmType: " << vmType.toStdString() << " aVM: " << aVM << " anActiveVM: " << anActiveVM );
1898   if ( anActiveVM && anActiveVM->getType() == vmType )
1899     {
1900       MESSAGE("aVM = anActiveVM");
1901       aVM = anActiveVM;
1902     }
1903
1904   bool keepDetached = property("keep_detached").toBool();
1905   if ( aVM && (!aVM->getDetached() || keepDetached) && create )
1906   {
1907     if ( !aVM->getActiveView() )
1908       {
1909         MESSAGE("aVM->createView()");
1910         aVM->createView();
1911       }
1912     else
1913       {
1914         MESSAGE("desktop()->setActiveWindow: " << aVM->getActiveView());
1915         desktop()->setActiveWindow( aVM->getActiveView() );
1916       }
1917   }
1918   else if ( create )
1919     {
1920       MESSAGE("aVM = createViewManager( vmType )");
1921       aVM = createViewManager( vmType );
1922     }
1923
1924   return aVM;
1925 }
1926
1927 /*!
1928   Creates view manager of some type
1929   \param vmType - type of view manager
1930 */
1931 SUIT_ViewManager* LightApp_Application::createViewManager( const QString& vmType, bool detached )
1932 {
1933   SUIT_ResourceMgr* resMgr = resourceMgr();
1934
1935   SUIT_ViewManager* viewMgr = 0;
1936 #ifndef DISABLE_GLVIEWER
1937   if( vmType == GLViewer_Viewer::Type() )
1938   {
1939     viewMgr = new GLViewer_ViewManager( activeStudy(), desktop() );
1940     new LightApp_GLSelector( (GLViewer_Viewer2d*)viewMgr->getViewModel(), mySelMgr );
1941   }
1942 #endif
1943 #ifndef DISABLE_PLOT2DVIEWER
1944   if( vmType == Plot2d_Viewer::Type() )
1945   {
1946     viewMgr = new Plot2d_ViewManager( activeStudy(), desktop() );
1947     Plot2d_Viewer* vm;
1948 #ifndef DISABLE_SALOMEOBJECT
1949     SPlot2d_Viewer* v = new SPlot2d_Viewer();
1950     vm = v;
1951     new LightApp_Plot2dSelector( v, mySelMgr );
1952 #else
1953     vm = new Plot2d_Viewer();
1954 #endif
1955     viewMgr->setViewModel( vm  );// custom view model, which extends SALOME_View interface
1956     Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( viewMgr->getActiveView() );
1957     if( wnd )
1958     {
1959       Plot2d_ViewFrame* frame = wnd->getViewFrame();
1960       frame->setBackgroundColor( resMgr->colorValue( "Plot2d", "Background", frame->backgroundColor() ) );
1961     }
1962   }
1963 #endif
1964 #ifndef DISABLE_QXGRAPHVIEWER
1965   if( vmType == QxScene_Viewer::Type() )
1966   {
1967     viewMgr = new QxScene_ViewManager( activeStudy(), desktop() );
1968     QxScene_Viewer* vm = new QxScene_Viewer();
1969     viewMgr->setViewModel( vm  );
1970     //QxScene_ViewWindow* wnd = dynamic_cast<QxScene_ViewWindow*>( viewMgr->getActiveView() );
1971   }
1972 #endif
1973 #ifndef DISABLE_GRAPHICSVIEW
1974   if( vmType == GraphicsView_Viewer::Type() )
1975   {
1976     viewMgr = new GraphicsView_ViewManager( activeStudy(), desktop() );
1977     new LightApp_GVSelector( (GraphicsView_Viewer*)viewMgr->getViewModel(), mySelMgr );
1978   }
1979 #endif
1980 #ifndef DISABLE_PVVIEWER
1981   if( vmType == PVViewer_Viewer::Type() )
1982   {
1983     if (( viewMgr = dynamic_cast<PVViewer_ViewManager*>( getViewManager( vmType, false )))) {
1984       viewMgr->getActiveView()->setFocus();
1985       return 0;
1986     } else {
1987       viewMgr = new PVViewer_ViewManager( activeStudy(), desktop() );
1988     }
1989   }
1990 #endif
1991 #ifndef DISABLE_PYVIEWER
1992   if( vmType == PyViewer_Viewer::Type() )
1993   {
1994     viewMgr = new PyViewer_ViewManager( activeStudy(), desktop() );
1995   }
1996 #endif
1997 #ifndef DISABLE_OCCVIEWER
1998   if( vmType == OCCViewer_Viewer::Type() )
1999   {
2000     viewMgr = new OCCViewer_ViewManager( activeStudy(), desktop() );
2001     OCCViewer_Viewer* vm;
2002 #ifndef DISABLE_SALOMEOBJECT
2003     vm = new SOCC_Viewer();
2004 #else
2005     vm = new OCCViewer_Viewer( true );
2006 #endif
2007     vm->setBackground( OCCViewer_ViewFrame::TOP_LEFT,
2008                        resMgr->backgroundValue( "OCCViewer", "xz_background", vm->background(OCCViewer_ViewFrame::TOP_LEFT) ) );
2009     vm->setBackground( OCCViewer_ViewFrame::TOP_RIGHT,
2010                        resMgr->backgroundValue( "OCCViewer", "yz_background", vm->background(OCCViewer_ViewFrame::TOP_RIGHT) ) );
2011     vm->setBackground( OCCViewer_ViewFrame::BOTTOM_LEFT,
2012                        resMgr->backgroundValue( "OCCViewer", "xy_background", vm->background(OCCViewer_ViewFrame::BOTTOM_LEFT) ) );
2013     vm->setBackground( OCCViewer_ViewFrame::BOTTOM_RIGHT,
2014                        resMgr->backgroundValue( "OCCViewer", "background", vm->background(OCCViewer_ViewFrame::MAIN_VIEW) ) );
2015
2016     vm->setTrihedronSize(  resMgr->doubleValue( "3DViewer", "trihedron_size", vm->trihedronSize() ),
2017                            resMgr->booleanValue( "3DViewer", "relative_size", vm->trihedronRelative() ));
2018     vm->setInteractionStyle( resMgr->integerValue( "3DViewer", "navigation_mode", vm->interactionStyle() ) );
2019     vm->setProjectionType( resMgr->integerValue( "OCCViewer", "projection_mode", vm->projectionType() ) );
2020     vm->setStereoType( resMgr->integerValue( "OCCViewer", "stereo_type", vm->stereoType() ) );
2021     vm->setAnaglyphFilter( resMgr->integerValue( "OCCViewer", "anaglyph_filter", vm->anaglyphFilter() ) );
2022     vm->setStereographicFocus( resMgr->integerValue( "OCCViewer", "focus_type", vm->stereographicFocusType() ),
2023                                resMgr->doubleValue( "OCCViewer", "focus_value", vm->stereographicFocusValue() ));
2024     vm->setInterocularDistance( resMgr->integerValue( "OCCViewer", "iod_type", vm->interocularDistanceType() ),
2025                                 resMgr->doubleValue( "OCCViewer", "iod_value", vm->interocularDistanceValue() ));
2026     vm->setSelectionStyle((OCCViewer_ViewWindow::SelectionStyle) resMgr->integerValue( "OCCViewer", "adv_selection_mode", vm->selectionStyle() ) );
2027
2028     vm->setReverseStereo( resMgr->booleanValue( "OCCViewer", "reverse_stereo", vm->isReverseStereo() ) );
2029     vm->setVSync( resMgr->booleanValue( "OCCViewer", "enable_vsync", vm->isVSync() ) );
2030     vm->setQuadBufferSupport( resMgr->booleanValue( "OCCViewer", "enable_quad_buffer_support", vm->isQuadBufferSupport() ) );
2031     vm->setZoomingStyle( resMgr->integerValue( "3DViewer", "zooming_mode", vm->zoomingStyle() ) );
2032     vm->enablePreselection( resMgr->booleanValue( "OCCViewer", "enable_preselection", vm->isPreselectionEnabled() ) );
2033     vm->enableSelection(    resMgr->booleanValue( "OCCViewer", "enable_selection",    vm->isSelectionEnabled() ) );
2034     vm->setClippingColor( resMgr->colorValue( "OCCViewer", "clipping_color", vm->clippingColor() ) );
2035     vm->setClippingTextureParams( resMgr->booleanValue( "OCCViewer", "clipping_use_default_texture", vm->isDefaultTextureUsed() ),
2036                                   resMgr->stringValue( "OCCViewer", "clipping_texture", vm->clippingTexture() ),
2037                                   resMgr->booleanValue( "OCCViewer", "clipping_modulate", vm->isTextureModulated() ),
2038                                   resMgr->doubleValue( "OCCViewer", "clipping_scale", vm->clippingTextureScale() ) );
2039
2040
2041     viewMgr->setViewModel( vm );// custom view model, which extends SALOME_View interface
2042     new LightApp_OCCSelector( (OCCViewer_Viewer*)viewMgr->getViewModel(), mySelMgr );
2043   }
2044 #endif
2045 #ifndef DISABLE_VTKVIEWER
2046 #ifndef DISABLE_SALOMEOBJECT
2047   if ( vmType == SVTK_Viewer::Type() )
2048 #else
2049   if ( vmType == VTKViewer_Viewer::Type() )
2050 #endif
2051   {
2052 #ifndef DISABLE_SALOMEOBJECT
2053     viewMgr = new SVTK_ViewManager( activeStudy(), desktop() );
2054     SVTK_Viewer* vm = dynamic_cast<SVTK_Viewer*>( viewMgr->getViewModel() );
2055     if( vm )
2056     {
2057       vm->setProjectionMode( resMgr->integerValue( "VTKViewer", "projection_mode", vm->projectionMode() ) );
2058       vm->setStereoType( resMgr->integerValue( "VTKViewer", "stereo_type", vm->stereoType() ) );
2059       vm->setAnaglyphFilter( resMgr->integerValue( "VTKViewer", "anaglyph_filter", vm->anaglyphFilter() ) );
2060       vm->setQuadBufferSupport( resMgr->booleanValue( "VTKViewer", "enable_quad_buffer_support", vm->isQuadBufferSupport() ) );
2061       vm->setBackground( resMgr->backgroundValue( "VTKViewer", "background", vm->background() ) );
2062       vm->setTrihedronSize( resMgr->doubleValue( "3DViewer", "trihedron_size", vm->trihedronSize() ),
2063                             resMgr->booleanValue( "3DViewer", "relative_size", vm->trihedronRelative() ) );
2064       vm->setStaticTrihedronVisible( resMgr->booleanValue( "3DViewer", "show_static_trihedron", vm->isStaticTrihedronVisible() ) );
2065       vm->setInteractionStyle( resMgr->integerValue( "3DViewer", "navigation_mode", vm->interactionStyle() ) );
2066       vm->setZoomingStyle( resMgr->integerValue( "3DViewer", "zooming_mode", vm->zoomingStyle() ) );
2067       vm->setPreSelectionMode(resMgr->integerValue( "VTKViewer", "preselection", vm->preSelectionMode() ) );
2068       vm->enableSelection( resMgr->booleanValue( "VTKViewer", "enable_selection", vm->isSelectionEnabled() ) );
2069       vm->setIncrementalSpeed( resMgr->integerValue( "VTKViewer", "speed_value", vm->incrementalSpeed() ),
2070                                resMgr->integerValue( "VTKViewer", "speed_mode", vm->incrementalSpeedMode() ) );
2071       vm->setSpacemouseButtons( resMgr->integerValue( "VTKViewer", "spacemouse_func1_btn", vm->spacemouseBtn(1) ),
2072                                 resMgr->integerValue( "VTKViewer", "spacemouse_func2_btn", vm->spacemouseBtn(2) ),
2073                                 resMgr->integerValue( "VTKViewer", "spacemouse_func5_btn", vm->spacemouseBtn(3) ) );
2074       new LightApp_VTKSelector( vm, mySelMgr );
2075     }
2076 #else
2077     viewMgr = new VTKViewer_ViewManager( activeStudy(), desktop() );
2078     VTKViewer_Viewer* vm = dynamic_cast<VTKViewer_Viewer*>( viewMgr->getViewModel() );
2079     if ( vm )
2080       vm->setBackground( resMgr->backgroundValue( "VTKViewer", "background", vm->background() ) );
2081 #endif
2082   }
2083 #endif
2084
2085 #ifndef DISABLE_PV3DVIEWER
2086 # ifndef DISABLE_SALOMEOBJECT
2087   if ( vmType == SPV3D_ViewModel::Type() )
2088 # else
2089   if ( vmType == PV3DViewer_ViewModel::Type() )
2090 # endif
2091   {
2092     viewMgr = new SPV3D_ViewManager( activeStudy(), desktop() );
2093     SPV3D_ViewModel* vm = dynamic_cast<SPV3D_ViewModel*>( viewMgr->getViewModel() );
2094     if ( vm )
2095     {
2096       // vm->setBackground(...); //NYI
2097       // vm->...
2098
2099       new LightApp_PV3DSelector( vm, mySelMgr );
2100     }
2101 #else
2102     viewMgr = new PV3DViewer_ViewManager( activeStudy(), desktop() );
2103     PV3DViewer_ViewModel* vm = dynamic_cast<PV3DViewer_ViewModel*>( viewMgr->getViewModel() );
2104     if ( vm )
2105     {
2106       // vm->setBackground(...); //NYI
2107     }
2108 #endif
2109   }
2110
2111   if ( !viewMgr )
2112     return 0;
2113
2114   viewMgr->setDetached(detached);
2115   addViewManager( viewMgr );
2116   SUIT_ViewWindow* viewWin = viewMgr->createViewWindow();
2117
2118   if ( viewWin && desktop() ) {
2119     viewWin->resize( (int)( desktop()->width() * 0.6 ), (int)( desktop()->height() * 0.6 ) );
2120     viewWin->setDropDownButtons( resMgr->booleanValue( "viewers", "drop_down_buttons", true ) );
2121   }
2122
2123   return viewMgr;
2124 }
2125
2126 SUIT_ViewManager* LightApp_Application::createViewManager( const QString& vmType, QWidget* w )
2127 {
2128   SUIT_ResourceMgr* resMgr = resourceMgr();
2129
2130   SUIT_ViewManager* vm = new SUIT_ViewManager( activeStudy(),
2131                                                desktop(),
2132                                                new LightApp_WgViewModel( vmType, w ) );
2133   vm->setTitle( QString( "%1: %M - viewer %V" ).arg( vmType ) );
2134
2135   addViewManager( vm );
2136   SUIT_ViewWindow* vw = vm->createViewWindow();
2137   if ( vw && desktop() ) {
2138     vw->resize( (int)( desktop()->width() * 0.6 ), (int)( desktop()->height() * 0.6 ) );
2139     vw->setDropDownButtons( resMgr->booleanValue( "viewers", "drop_down_buttons", true ) );
2140   }
2141
2142   if ( !vmType.isEmpty() && !myUserWmTypes.contains( vmType ) )
2143     myUserWmTypes << vmType;
2144
2145   return vm;
2146 }
2147
2148 SUIT_ViewManager* LightApp_Application::createViewManager( SUIT_ViewModel* theModel )
2149 {
2150   SUIT_ResourceMgr* resMgr = resourceMgr();
2151
2152   SUIT_ViewManager* vm = new SUIT_ViewManager( activeStudy(),
2153                                                desktop(),
2154                                                theModel );
2155
2156   QString vmType = vm->getType();
2157
2158   vm->setTitle( QString( "%1: %M - viewer %V" ).arg( vmType ) );
2159
2160   addViewManager( vm );
2161   SUIT_ViewWindow* vw = vm->createViewWindow();
2162   if ( vw && desktop() ) {
2163     vw->resize( (int)( desktop()->width() * 0.6 ), (int)( desktop()->height() * 0.6 ) );
2164     vw->setDropDownButtons( resMgr->booleanValue( "viewers", "drop_down_buttons", true ) );
2165   }
2166
2167   if ( !vmType.isEmpty() && !myUserWmTypes.contains( vmType ) )
2168     myUserWmTypes << vmType;
2169
2170   return vm;
2171 }
2172
2173 /*!
2174   SLOT: Removes view manager from application
2175 */
2176 void LightApp_Application::onCloseView( SUIT_ViewManager* theVM )
2177 {
2178   removeViewManager( theVM );
2179 }
2180
2181 /*!
2182   Protected SLOT: On study created.
2183   \param theStudy - just created study
2184 */
2185 void LightApp_Application::onStudyCreated( SUIT_Study* theStudy )
2186 {
2187   SUIT_DataObject* aRoot = 0;
2188   if ( theStudy && theStudy->root() )
2189   {
2190     aRoot = theStudy->root();
2191     //aRoot->setName( tr( "DATA_MODELS" ) );
2192   }
2193
2194   getWindow( WT_ObjectBrowser );
2195   getWindow( WT_InfoPanel );
2196
2197   loadDockWindowsState();
2198
2199   if ( objectBrowser() )
2200     objectBrowser()->setRoot( aRoot );
2201
2202   activateModule( defaultModule() );
2203
2204   if ( objectBrowser() )
2205     objectBrowser()->openLevels();
2206
2207 #ifndef DISABLE_PYCONSOLE
2208   if( pythonConsole() )
2209     getPyInterp()->initStudy();
2210 #endif
2211 }
2212
2213 /*!
2214   Protected SLOT: On study opened.
2215   \param theStudy - just opened  study
2216 */
2217 void LightApp_Application::onStudyOpened( SUIT_Study* theStudy )
2218 {
2219   SUIT_DataObject* aRoot = 0;
2220   if ( theStudy && theStudy->root() )
2221   {
2222     aRoot = theStudy->root();
2223     //aRoot->dump();
2224   }
2225
2226   getWindow( WT_ObjectBrowser );
2227   getWindow( WT_InfoPanel );
2228
2229   loadDockWindowsState();
2230
2231   if ( objectBrowser() )
2232     objectBrowser()->setRoot( aRoot );
2233
2234   activateModule( defaultModule() );
2235
2236   if ( objectBrowser() )
2237     objectBrowser()->openLevels();
2238
2239 #ifndef DISABLE_PYCONSOLE
2240   if( pythonConsole() )
2241     getPyInterp()->initStudy();
2242 #endif
2243
2244   emit studyOpened();
2245 }
2246
2247 /*!Protected SLOT. On study saved.*/
2248 void LightApp_Application::onStudySaved( SUIT_Study* s )
2249 {
2250   QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
2251   if ( mru && s )
2252     mru->insert( s->studyName() );
2253
2254   emit studySaved();
2255 }
2256
2257 /*!Protected SLOT. On study closed.*/
2258 void LightApp_Application::onStudyClosed( SUIT_Study* /*s*/ )
2259 {
2260   /*
2261   disconnect( this, SIGNAL( viewManagerRemoved( SUIT_ViewManager* ) ),
2262               this, SLOT( onViewManagerRemoved( SUIT_ViewManager* ) ) );
2263   */
2264
2265   // stop auto-save timer
2266   myAutoSaveTimer->stop();
2267
2268   // Bug 10396: clear selection
2269   mySelMgr->clearSelected();
2270
2271   // Bug 12944: emit signal only after clear selection
2272   emit studyClosed();
2273
2274   activateModule( "" );
2275 }
2276
2277 /*!Protected SLOT.On desktop activated.*/
2278 void LightApp_Application::onDesktopActivated()
2279 {
2280   CAM_Application::onDesktopActivated();
2281   LightApp_Module* aModule = dynamic_cast<LightApp_Module*>(activeModule());
2282   if(aModule)
2283     aModule->studyActivated();
2284 }
2285
2286 void LightApp_Application::studyOpened( SUIT_Study* s )
2287 {
2288   CAM_Application::studyOpened( s );
2289
2290   updateWindows();
2291   updateViewManagers();
2292 }
2293
2294 void LightApp_Application::studySaved( SUIT_Study* s )
2295 {
2296   CAM_Application::studyOpened( s );
2297   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
2298   if ( aResMgr && activeStudy() ) {
2299     int autoSaveInterval = aResMgr->integerValue( "Study", "auto_save_interval", 0 );
2300     if ( autoSaveInterval > 0 ) myAutoSaveTimer->start( autoSaveInterval*60000 );
2301   }
2302 }
2303
2304 void LightApp_Application::studyCreated( SUIT_Study* s )
2305 {
2306   CAM_Application::studyCreated( s );
2307
2308   updateWindows();
2309   updateViewManagers();
2310 }
2311
2312 /*!Gets file filter.
2313  *\retval QString "(*.hdf)"
2314  */
2315 QString LightApp_Application::getFileFilter( bool /*open*/) const
2316 {
2317   return "(*.hdf)";
2318 }
2319
2320 /*!
2321   Shows file dialog and return user selected file name
2322 */
2323 QString LightApp_Application::getFileName( bool open, const QString& initial, const QString& filters,
2324                                            const QString& caption, QWidget* parent )
2325 {
2326   if ( !parent )
2327     parent = desktop();
2328   QStringList fls = filters.split( ";;", QString::SkipEmptyParts );
2329   return SUIT_FileDlg::getFileName( parent, initial, fls, caption, open, true );
2330 }
2331
2332 /*! Gets directory*/
2333 QString LightApp_Application::getDirectory( const QString& initial, const QString& caption, QWidget* parent )
2334 {
2335   if ( !parent )
2336     parent = desktop();
2337   return SUIT_FileDlg::getExistingDirectory( parent, initial, caption, true );
2338 }
2339
2340 /*! Get open file names*/
2341 QStringList LightApp_Application::getOpenFileNames( const QString& initial, const QString& filters,
2342                                                     const QString& caption, QWidget* parent )
2343 {
2344   if ( !parent )
2345     parent = desktop();
2346   QStringList fls = filters.split( ";;", QString::SkipEmptyParts );
2347   return SUIT_FileDlg::getOpenFileNames( parent, initial, fls, caption, true );
2348 }
2349
2350 /*!Private SLOT. Update object browser.*/
2351 void LightApp_Application::onRefresh()
2352 {
2353   updateObjectBrowser( true );
2354 }
2355
2356 /*!Private SLOT. Update actions after rename object.*/
2357 void LightApp_Application::onRenamed()
2358 {
2359   activeStudy()->Modified();
2360   updateActions();
2361 }
2362
2363 // IMN 08.07.2015 : issue 002556: Some stereo outputs are affected by window position.
2364 // To prevent reversion the window should be either aligned during movement and resize.
2365 /*!Private SLOT. Update actions after rename object.*/
2366 /*void LightApp_Application::onMoved()
2367 {
2368   OCCViewer_ViewManager* viewMgr = 0;
2369   viewMgr = dynamic_cast<OCCViewer_ViewManager*>( getViewManager( OCCViewer_Viewer::Type(), false ) );
2370   if (viewMgr) {
2371     OCCViewer_ViewWindow* view = 0;
2372     view = dynamic_cast<OCCViewer_ViewWindow*>( viewMgr->getActiveView() );
2373     if (view) {
2374       view->getViewPort()->repaintViewAfterMove();
2375     }
2376   }
2377 }
2378 */
2379 /*!Private SLOT. Support drag-and-drop operation.*/
2380 void LightApp_Application::onDropped( const QList<SUIT_DataObject*>& objects, SUIT_DataObject* parent, int row, Qt::DropAction action )
2381 {
2382   LightApp_DataObject* parentObj = dynamic_cast<LightApp_DataObject*>( parent );
2383   if ( !parentObj )
2384     return;
2385
2386   LightApp_Module* aModule = dynamic_cast<LightApp_Module*>( parentObj->module() );
2387   if ( aModule )
2388     aModule->dropObjects( objects, parentObj, row, action );
2389 }
2390
2391 /*!Private SLOT. On preferences.*/
2392 void LightApp_Application::onPreferences()
2393 {
2394   showPreferences( activeModule() ? activeModule()->moduleName() : tr( "PREF_CATEGORY_SALOME" ) );
2395 }
2396
2397 /*!Private SLOT. On preferences.*/
2398 void LightApp_Application::showPreferences( const QString& path )
2399 {
2400   showPreferences( QStringList() << path );
2401 }
2402
2403 void LightApp_Application::showPreferences( const QStringList& path )
2404 {
2405   QApplication::setOverrideCursor( Qt::WaitCursor );
2406
2407   LightApp_PreferencesDlg* prefDlg = new LightApp_PreferencesDlg( preferences( true ), desktop());
2408
2409   QApplication::restoreOverrideCursor();
2410
2411   if ( !prefDlg )
2412     return;
2413
2414   preferences()->activateItem( path );
2415
2416   if ( ( prefDlg->exec() == QDialog::Accepted || prefDlg->isSaved() ) &&  resourceMgr() )
2417   {
2418     if ( desktop() )
2419       resourceMgr()->setValue( "desktop", "geometry", desktop()->storeGeometry() );
2420     resourceMgr()->save();
2421
2422     // Update shortcuts
2423     shortcutMgr()->updateShortcuts();
2424   }
2425
2426   delete prefDlg;
2427 }
2428
2429 /*!Protected SLOT. On preferences changed.*/
2430 void LightApp_Application::onPreferenceChanged( QString& modName, QString& section, QString& param )
2431 {
2432   LightApp_Module* sMod = 0;
2433   CAM_Module* mod = module( modName );
2434   if ( mod && mod->inherits( "LightApp_Module" ) )
2435     sMod = (LightApp_Module*)mod;
2436
2437   if ( sMod )
2438     sMod->preferencesChanged( section, param );
2439   else
2440     preferencesChanged( section, param );
2441   // emit signal to allow additional preferences changing processing
2442   emit preferenceChanged( modName, section, param );
2443 }
2444
2445 /*!Remove all windows from study.*/
2446 void LightApp_Application::beforeCloseDoc( SUIT_Study* s )
2447 {
2448   saveDockWindowsState();
2449
2450   if ( SUIT_DataBrowser* ob = objectBrowser() )
2451     ob->setModel(0);
2452
2453   CAM_Application::beforeCloseDoc( s );
2454 }
2455
2456 /*!Update actions.*/
2457 void LightApp_Application::updateActions()
2458 {
2459   updateCommandsStatus();
2460 }
2461
2462 /*!
2463   Creates new study
2464 */
2465 SUIT_Study* LightApp_Application::createNewStudy()
2466 {
2467   LightApp_Study* aStudy = new LightApp_Study( this );
2468
2469   // Set up processing of major study-related events
2470   connect( aStudy, SIGNAL( created( SUIT_Study* ) ), this, SLOT( onStudyCreated( SUIT_Study* ) ) );
2471   connect( aStudy, SIGNAL( opened ( SUIT_Study* ) ), this, SLOT( onStudyOpened ( SUIT_Study* ) ) );
2472   connect( aStudy, SIGNAL( saved  ( SUIT_Study* ) ), this, SLOT( onStudySaved  ( SUIT_Study* ) ) );
2473   connect( aStudy, SIGNAL( closed ( SUIT_Study* ) ), this, SLOT( onStudyClosed ( SUIT_Study* ) ) );
2474
2475   return aStudy;
2476 }
2477
2478 /*!
2479   Creates window by flag.
2480   \param flag - identificator of window type
2481 */
2482 QWidget* LightApp_Application::createWindow( const int flag )
2483 {
2484   QWidget* wid = 0;
2485
2486   SUIT_ResourceMgr* resMgr = resourceMgr();
2487
2488   if ( flag == WT_ObjectBrowser )
2489   {
2490     SUIT_DataBrowser* ob = new SUIT_DataBrowser( new LightApp_DataObject(), desktop() );
2491     ob->setObjectName( "objectBrowser" );
2492     ob->setSortMenuEnabled( true );
2493     ob->setAutoUpdate( true );
2494     if ( resMgr->hasValue( "ObjectBrowser", "auto_hide_search_tool" ) )
2495       ob->searchTool()->enableAutoHide( resMgr->booleanValue( "ObjectBrowser", "auto_hide_search_tool" ) );
2496
2497     //ob->setAutoOpenLevel( 1 ); // commented by ASV as a fix to bug IPAL10107
2498     ob->setWindowTitle( tr( "OBJECT_BROWSER" ) );
2499     connect( ob, SIGNAL( requestUpdate() ), this, SLOT( onRefresh() ) );
2500
2501     QString EntryCol = QObject::tr( "ENTRY_COLUMN" );
2502     SUIT_AbstractModel* treeModel = dynamic_cast<SUIT_AbstractModel*>( ob->model() );
2503     treeModel->setSearcher( this );
2504     treeModel->registerColumn( 0, EntryCol, LightApp_DataObject::EntryId );
2505     treeModel->setAppropriate( EntryCol, Qtx::Toggled );
2506
2507     // Mantis issue 0020136: Drag&Drop in OB
2508     SUIT_ProxyModel* proxyModel = dynamic_cast<SUIT_ProxyModel*>(treeModel);
2509     if ( proxyModel ) {
2510       connect( proxyModel, SIGNAL( dropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ),
2511                this,       SLOT( onDropped( const QList<SUIT_DataObject*>&, SUIT_DataObject*, int, Qt::DropAction ) ) );
2512       connect( proxyModel, SIGNAL( renamed( SUIT_DataObject* ) ),
2513                this,       SLOT( onRenamed( ) ) );
2514
2515     }
2516
2517     // temporary commented
2518     /*
2519     OB_ListView* ob_list = dynamic_cast<OB_ListView*>( const_cast<QListView*>( ob->listView() ) );
2520     if( ob_list )
2521       ob_list->setColumnMaxWidth( 0, desktop()->width()/4 );
2522     */
2523
2524     // Create OBSelector
2525     new LightApp_OBSelector( ob, mySelMgr );
2526     ob->treeView()->header()->setSectionResizeMode(SUIT_DataObject::VisibilityId, QHeaderView::Fixed);
2527     ob->treeView()->header()->moveSection(SUIT_DataObject::NameId,SUIT_DataObject::VisibilityId);
2528     ob->treeView()->setColumnWidth(SUIT_DataObject::VisibilityId, VISIBILITY_COLUMN_WIDTH);
2529     ob->setProperty( "shortcut", QKeySequence( "Alt+Shift+O" ) );
2530     wid = ob;
2531     ob->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
2532   }
2533   else if ( flag == WT_InfoPanel)
2534   {
2535     QtxInfoPanel* ipanel = new QtxInfoPanel( desktop() );
2536     ipanel->setObjectName( "infoPanel" );
2537     ipanel->setWindowTitle( tr( "INFO_PANEL" ) );
2538     wid = ipanel;
2539   }
2540 #ifndef DISABLE_PYCONSOLE
2541   else  if ( flag == WT_PyConsole )
2542   {
2543     PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) );
2544     pyCons->setObjectName( "pythonConsole" );
2545     pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
2546     pyCons->setFont( resMgr->fontValue( "PyConsole", "font" ) );
2547     pyCons->setIsShowBanner( resMgr->booleanValue( "PyConsole", "show_banner", true ) );
2548     pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
2549     pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) );
2550     wid = pyCons;
2551   }
2552 #endif
2553   else if ( flag == WT_LogWindow )
2554   {
2555     LogWindow* logWin = new LogWindow( desktop() );
2556     logWin->handleQtMessages( true );
2557     logWin->setObjectName( "logWindow" );
2558     logWin->setWindowTitle( tr( "LOG_WINDOW" ) );
2559     logWin->setProperty( "shortcut", QKeySequence( "Alt+Shift+L" ) );
2560     wid = logWin;
2561     logWin->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) );
2562   }
2563   return wid;
2564 }
2565
2566 /*!
2567   \return default windows( Object Browser, Python Console )
2568   Adds to map \a aMap.
2569  */
2570 void LightApp_Application::defaultWindows( QMap<int, int>& aMap ) const
2571 {
2572 #ifndef DISABLE_PYCONSOLE
2573   aMap.insert( WT_PyConsole, Qt::BottomDockWidgetArea );
2574 #endif
2575   if ( activeStudy() ) {
2576     aMap.insert( WT_ObjectBrowser, Qt::LeftDockWidgetArea );
2577     aMap.insert( WT_InfoPanel, Qt::RightDockWidgetArea );
2578     //  aMap.insert( WT_LogWindow, Qt::DockBottom );
2579   }
2580 }
2581
2582 /*!Default view managers*/
2583 void LightApp_Application::defaultViewManagers( QStringList& ) const
2584 {
2585   /*!Do nothing.*/
2586 }
2587
2588 /*!
2589   \return preferences.
2590   Create preferences, if \a crt = true.
2591 */
2592 LightApp_Preferences* LightApp_Application::preferences( const bool crt ) const
2593 {
2594   if ( myPrefs )
2595     return myPrefs;
2596
2597   LightApp_Application* that = (LightApp_Application*)this;
2598
2599   bool toCreate = !_prefs_ && crt;
2600   if ( toCreate )
2601   {
2602     _prefs_ = new LightApp_Preferences( resourceMgr() );
2603     that->createPreferences( _prefs_ );
2604     qAddPostRoutine( LightAppCleanUpAppResources );
2605   }
2606
2607   that->myPrefs = _prefs_;
2608
2609   connect( myPrefs, SIGNAL( preferenceChanged( QString&, QString&, QString& ) ),
2610            this, SLOT( onPreferenceChanged( QString&, QString&, QString& ) ), Qt::UniqueConnection );
2611   connect( myPrefs, SIGNAL( resetToDefaults() ),
2612            this, SIGNAL( preferenceResetToDefaults() ), Qt::UniqueConnection );
2613
2614   if ( !crt )
2615     return myPrefs;
2616
2617   QList<SUIT_Application*> appList = SUIT_Session::session()->applications();
2618   for ( QList<SUIT_Application*>::iterator appIt = appList.begin(); appIt != appList.end(); ++appIt )
2619   {
2620     LightApp_Application* app = ::qobject_cast<LightApp_Application*>( *appIt );
2621     if ( !app )
2622       continue;
2623
2624     // all modules available in current session
2625     QStringList names;
2626     app->modules( names, false );
2627
2628     // step 1: iterate through list of all available modules
2629     // and add empty preferences page
2630     for ( QStringList::const_iterator it = names.begin(); it != names.end(); ++it )
2631     {
2632       if ( !_prefs_->hasModule( *it ) ) // prevent possible duplications
2633       {
2634         int modId = _prefs_->addPreference( *it ); // add empty page
2635         _prefs_->setItemIcon( modId, moduleIcon( *it, 20 ) ); // scale icon to 20x20 pix
2636       }
2637     }
2638
2639     // step 2: iterate through list of all loaded modules
2640     // and initialize their preferences
2641     ModuleList loadedModules;
2642     app->modules( loadedModules );
2643     QListIterator<CAM_Module*> itr( loadedModules );
2644     while ( itr.hasNext() )
2645     {
2646       LightApp_Module* module = 0;
2647       CAM_Module* m = itr.next();
2648       if ( m->inherits( "LightApp_Module" ) )
2649         module = (LightApp_Module*)m;
2650
2651       if ( module && !_prefs_->hasModule( module->moduleName() ) )
2652       {
2653         _prefs_->addPreference( module->moduleName() ); // add page (for sure, had to be done at step 1)
2654         module->createPreferences();                    // initialize preferences
2655         that->emptyPreferences( module->moduleName() ); // show dummy page if module does not export any preferences
2656       }
2657     }
2658   }
2659   _prefs_->setItemProperty( "info", tr( "PREFERENCES_NOT_LOADED" ) ); // dummy page for modules which are not loaded yet
2660
2661   return myPrefs;
2662 }
2663
2664 /*!
2665   Adds new module to application
2666 */
2667 void LightApp_Application::moduleAdded( CAM_Module* mod )
2668 {
2669   CAM_Application::moduleAdded( mod );
2670
2671   LightApp_Module* lightMod = 0;
2672   if ( mod && mod->inherits( "LightApp_Module" ) )
2673     lightMod = (LightApp_Module*)mod;
2674
2675   if ( myPrefs && lightMod && !myPrefs->hasModule( lightMod->moduleName() ))
2676   {
2677     myPrefs->addPreference( mod->moduleName() );
2678     lightMod->createPreferences();
2679     emptyPreferences( mod->moduleName() );
2680   }
2681 }
2682
2683 void LightApp_Application::moduleDeactivated( CAM_Module* /*mod*/ )
2684 {
2685   if ( infoPanel() )
2686     infoPanel()->clear();
2687 }
2688
2689 void LightApp_Application::emptyPreferences( const QString& modName )
2690 {
2691   QtxPreferenceItem* item = myPrefs->findItem( modName, true );
2692   if ( !item || !item->isEmpty() )
2693     return;
2694
2695   QtxPagePrefFrameItem* frm = new QtxPagePrefFrameItem( item->title(), item->parentItem() );
2696   frm->setIcon( item->icon() );
2697   frm->setStretch( false );
2698   item->parentItem()->insertItem( frm, item );
2699   new QtxPagePrefLabelItem( Qt::AlignCenter, tr( "PREFERENCES_NOT_SUPPORTED" ).arg( modName ), frm );
2700   delete item;
2701 }
2702
2703 /*!
2704   Create preferences
2705 */
2706 void LightApp_Application::createPreferences( LightApp_Preferences* pref )
2707 {
2708   if ( !pref )
2709     return;
2710
2711   QStringList     aValuesList;
2712   QList<QVariant> anIndicesList;
2713   QIntList        idList;
2714   QIntList        txtList;
2715
2716   // . Top-level "SALOME" preferences group <<start>>
2717   int salomeCat = pref->addPreference( tr( "PREF_CATEGORY_SALOME" ) );
2718   pref->setItemIcon( salomeCat, Qtx::scaleIcon( resourceMgr()->loadPixmap( "LightApp", tr( "APP_DEFAULT_ICO" ), false ), 20 ) );
2719
2720   // .. "General" preferences tab <<start>>
2721   int genTab = pref->addPreference( tr( "PREF_TAB_GENERAL" ), salomeCat );
2722
2723   // ... "Language" group <<start>>
2724   int langGroup = pref->addPreference( tr( "PREF_GROUP_LANGUAGE" ), genTab );
2725   pref->setItemProperty( "columns", 2, langGroup );
2726   // .... -> application language
2727   int curLang = pref->addPreference( tr( "PREF_CURRENT_LANGUAGE" ), langGroup,
2728                                           LightApp_Preferences::Selector, "language", "language" );
2729   QStringList aLangs = SUIT_Session::session()->resourceMgr()->stringValue( "language", "languages", "en" ).split( "," );
2730   QList<QVariant> aIcons;
2731   QList<QVariant> aNumbers;
2732   QStringList aTitles;
2733   foreach ( QString aLang, aLangs ) {
2734     aIcons << QPixmap( QString( ":/images/%1" ).arg( aLang ) );
2735     aNumbers << aLang;
2736     aTitles << langToName( aLang );
2737   }
2738   pref->setItemProperty( "strings", aTitles, curLang );
2739   pref->setItemProperty( "ids",     aNumbers, curLang );
2740   pref->setItemProperty( "icons",   aIcons, curLang );
2741   pref->setItemProperty( "restart",  true, curLang );
2742
2743   int curLocale = pref->addPreference( tr( "PREF_CURRENT_LOCALE" ), langGroup,
2744                                           LightApp_Preferences::Bool, "language", "locale" );
2745   pref->setItemProperty( "restart",  true, curLocale );
2746   // ... "Language" group <<end>>
2747
2748   // ... "Look and feel" group <<start>>
2749   int lookGroup = pref->addPreference( tr( "PREF_GROUP_LOOK_AND_FEEL" ), genTab );
2750   pref->setItemProperty( "columns", 2, lookGroup );
2751   // .... -> show splash-screen
2752   pref->addPreference( tr( "PREF_SHOW_SPLASH" ), lookGroup, LightApp_Preferences::Bool, "launch", "splash" );
2753   // .... -> opaque resize
2754   pref->addPreference( tr( "PREF_OPAQUE_RESIZE" ), lookGroup, LightApp_Preferences::Bool, "desktop", "opaque_resize" );
2755   // .... -> drop-down buttons
2756   pref->addPreference( tr( "PREF_DROP_DOWN_BUTTONS" ), lookGroup, LightApp_Preferences::Bool, "viewers", "drop_down_buttons" );
2757   // .... -> Notification timeout
2758   int delay = pref->addPreference( tr( "PREF_NOTIFY_TIMEOUT" ), lookGroup, LightApp_Preferences::IntSpin, "notification", "timeout" );
2759   pref->setItemProperty( "special", tr("PREF_NOTIFY_TIMEOUT_NONE"), delay );
2760   pref->setItemProperty( "min", 0, delay );
2761   pref->setItemProperty( "max", 100, delay );
2762   pref->setItemProperty( "suffix", " sec", delay );
2763   // ... "Look and feel" group <<end>>
2764
2765   // ... "Study properties" group <<start>>
2766   int studyGroup = pref->addPreference( tr( "PREF_GROUP_STUDY" ), genTab );
2767   pref->setItemProperty( "columns", 2, studyGroup );
2768   // .... -> multi-file save
2769   pref->addPreference( tr( "PREF_MULTI_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "multi_file" );
2770   // .... -> ascii save mode
2771   pref->addPreference( tr( "PREF_ASCII_FILE" ), studyGroup, LightApp_Preferences::Bool, "Study", "ascii_file" );
2772   // .... -> store windows geometry
2773   pref->addPreference( tr( "PREF_LOAD_LIGHT" ), studyGroup, LightApp_Preferences::Bool, "Study", "autoload_light_modules" );
2774   pref->addPreference( tr( "PREF_STORE_POS" ),  studyGroup, LightApp_Preferences::Bool, "Study", "store_positions" );
2775   pref->addPreference( "", studyGroup, LightApp_Preferences::Space );
2776   pref->addPreference( tr( "PREF_STORE_TOOL_POS" ),  studyGroup, LightApp_Preferences::Bool, "Study", "store_tool_positions" );
2777   // .... -> auto-save
2778   int autoSaveInterval = pref->addPreference( tr( "PREF_AUTO_SAVE" ),  studyGroup,
2779                                               LightApp_Preferences::IntSpin, "Study", "auto_save_interval" );
2780   pref->setItemProperty( "min",        0, autoSaveInterval );
2781   pref->setItemProperty( "max",     1440, autoSaveInterval );
2782   pref->setItemProperty( "special", tr( "PREF_AUTO_SAVE_DISABLED" ), autoSaveInterval );
2783   // ... "Study properties" group <<end>>
2784
2785   // ... "Help browser" group <<start>>
2786 #ifndef DISABLE_QTXWEBBROWSER
2787   int extgroup = pref->addPreference( tr( "PREF_GROUP_EXT_BROWSER" ), genTab, LightApp_Preferences::Auto, "ExternalBrowser", "use_external_browser");
2788 #else
2789   int extgroup = pref->addPreference( tr( "PREF_GROUP_EXT_BROWSER" ), genTab );
2790 #endif
2791
2792 #ifdef WIN32
2793   QString platform = "winapplication";
2794 #else
2795   QString platform = "application";
2796 #endif
2797   // .... -> browser application
2798   int apppref = pref->addPreference( tr( "PREF_APP" ), extgroup, LightApp_Preferences::File, "ExternalBrowser", platform );
2799   pref->setItemProperty( "mode", Qtx::PT_OpenFile, apppref );
2800   // .... -> browser parameters
2801   pref->addPreference( tr( "PREF_PARAM" ), extgroup, LightApp_Preferences::String, "ExternalBrowser", "parameters" );
2802   // ... "Help browser" group <<end>>
2803
2804   // ... "Python console properties" group <<start>>
2805   int pythonConsoleGroup = pref->addPreference( tr( "PREF_GROUP_PY_CONSOLE" ), genTab );
2806   pref->setItemProperty( "columns", 2, pythonConsoleGroup );
2807   // .... -> font
2808   pref->addPreference( tr( "PREF_FONT" ), pythonConsoleGroup, LightApp_Preferences::Font, "PyConsole", "font" );
2809   // .... -> show banner
2810   pref->addPreference( tr( "PREF_SHOW_BANNER" ), pythonConsoleGroup, LightApp_Preferences::Bool, "PyConsole", "show_banner" );
2811   // .... -> auto-completion
2812   pref->addPreference( tr( "PREF_AUTO_COMPLETION" ), pythonConsoleGroup, LightApp_Preferences::Bool, "PyConsole", "auto_completion" );
2813   // ... "Python console properties" group <<end>>
2814
2815   // ... "MRU" preferences group <<start>>
2816   int mruGroup = pref->addPreference( tr( "PREF_GROUP_MRU" ), genTab, LightApp_Preferences::Auto, "MRU", "show_mru" );
2817   pref->setItemProperty( "columns", 4, mruGroup );
2818   // number of MRU items
2819   int mruVisCount = pref->addPreference( tr( "PREF_MRU_VISIBLE_COUNT" ), mruGroup, LightApp_Preferences::IntSpin,
2820                                          "MRU", "visible_count" );
2821   pref->setItemProperty( "min", 0,   mruVisCount );
2822   pref->setItemProperty( "max", 100, mruVisCount );
2823   // MRU links type
2824   int mruLinkType = pref->addPreference( tr( "PREF_MRU_LINK_TYPE" ), mruGroup, LightApp_Preferences::Selector,
2825                                          "MRU", "link_type" );
2826   aValuesList.clear();
2827   anIndicesList.clear();
2828   aValuesList   << tr("PREF_MRU_LINK_AUTO") << tr("PREF_MRU_LINK_SHORT") << tr("PREF_MRU_LINK_FULL");
2829   anIndicesList << 0                        << 1                         << 2                       ;
2830   pref->setItemProperty( "strings", aValuesList,   mruLinkType );
2831   pref->setItemProperty( "indexes", anIndicesList, mruLinkType );
2832   // ... "MRU" preferences group <<end>>
2833
2834   // ... "Full-screen" group <<start>>
2835   int fullScreenGroup = pref->addPreference( tr( "PREF_GROUP_FULL_SCREEN" ), genTab );
2836   pref->setItemProperty( "columns", 2, fullScreenGroup );
2837   // .... -> automatic hiding toolbars
2838   pref->addPreference( tr( "PREF_FULL_SCREEN_AUTO" ), fullScreenGroup,
2839                        LightApp_Preferences::Bool, "OCCViewer", "automatic_hiding" );
2840   // ... "Full-screen" group <<end>>
2841
2842   // .. "General" preferences tab <<end>>
2843
2844   // .. "3D viewer" group <<start>>
2845   int Viewer3DGroup = pref->addPreference( tr( "PREF_GROUP_3DVIEWER" ), salomeCat );
2846   // ... -> navigation mode
2847   int vtkStyleMode = pref->addPreference( tr( "PREF_NAVIGATION" ), Viewer3DGroup,
2848                                           LightApp_Preferences::Selector, "3DViewer", "navigation_mode" );
2849   aValuesList.clear();
2850   anIndicesList.clear();
2851   aValuesList   << tr("PREF_STANDARD_STYLE") << tr("PREF_KEYFREE_STYLE");
2852   anIndicesList << 0                         << 1;
2853   pref->setItemProperty( "strings", aValuesList,   vtkStyleMode );
2854   pref->setItemProperty( "indexes", anIndicesList, vtkStyleMode );
2855   // ... -> zooming mode
2856   int occZoomingStyleMode = pref->addPreference( tr( "PREF_ZOOMING" ), Viewer3DGroup,
2857                                                  LightApp_Preferences::Selector, "3DViewer", "zooming_mode" );
2858   aValuesList.clear();
2859   anIndicesList.clear();
2860   aValuesList   << tr("PREF_ZOOMING_AT_CENTER") << tr("PREF_ZOOMING_AT_CURSOR");
2861   anIndicesList << 0                            << 1;
2862   pref->setItemProperty( "strings", aValuesList,   occZoomingStyleMode );
2863   pref->setItemProperty( "indexes", anIndicesList, occZoomingStyleMode );
2864   // ... "Trihedron" group <<start>>
2865   int occTriGroup = pref->addPreference( tr( "PREF_TRIHEDRON" ), Viewer3DGroup );
2866   pref->setItemProperty( "columns", 2, occTriGroup );
2867   // .... -> trihedron size
2868   int occTS = pref->addPreference( tr( "PREF_TRIHEDRON_SIZE" ), occTriGroup,
2869                                    LightApp_Preferences::DblSpin, "3DViewer", "trihedron_size" );
2870   pref->setItemProperty( "min", 1.0E-06, occTS );
2871   pref->setItemProperty( "max", 1000, occTS );
2872   // .... -> relative size of trihedron
2873   pref->addPreference( tr( "PREF_RELATIVE_SIZE" ), occTriGroup, LightApp_Preferences::Bool, "3DViewer", "relative_size" );
2874   // .... -> show static trihedron
2875   pref->addPreference( tr( "PREF_SHOW_STATIC_TRIHEDRON" ), occTriGroup, LightApp_Preferences::Bool, "3DViewer", "show_static_trihedron" );
2876   // ... "Trihedron" group <<end>>
2877   // .. "3D viewer" group <<end>>
2878
2879   QString formats;
2880   int bgId;
2881 #ifndef DISABLE_OCCVIEWER
2882   // .. "OCC viewer" group <<start>>
2883   int occGroup = pref->addPreference( tr( "PREF_GROUP_OCCVIEWER" ), salomeCat );
2884
2885   // .... -> Projection mode
2886   int occProjMode = pref->addPreference( tr( "PREF_PROJECTION_MODE" ), occGroup,
2887                                          LightApp_Preferences::Selector, "OCCViewer", "projection_mode" );
2888   aValuesList.clear();
2889   anIndicesList.clear();
2890   aValuesList   << tr("PREF_ORTHOGRAPHIC") << tr("PREF_PERSPECTIVE");
2891   anIndicesList << 0                       << 1;
2892   pref->setItemProperty( "strings", aValuesList,   occProjMode );
2893   pref->setItemProperty( "indexes", anIndicesList, occProjMode );
2894
2895   // .... -> Stereo group
2896   int stereoGroup = pref->addPreference( tr( "PREF_GROUP_STEREO" ), occGroup);
2897   pref->setItemProperty( "columns", 2, stereoGroup );
2898   // .... -> Stereo type
2899   int stereoType = pref->addPreference( tr( "PREF_STEREO_TYPE" ), stereoGroup,
2900                                             LightApp_Preferences::Selector, "OCCViewer", "stereo_type" );
2901   aValuesList.clear();
2902   anIndicesList.clear();
2903   idList.clear();
2904   OCCViewer_Viewer::stereoData( aValuesList, idList);
2905   foreach( int gid, idList ) anIndicesList << gid;
2906   pref->setItemProperty( "strings", aValuesList,   stereoType );
2907   pref->setItemProperty( "indexes", anIndicesList, stereoType );
2908
2909   // .... -> Anaglyph filter
2910   int anaglyphFilter = pref->addPreference( tr( "PREF_ANAGLYPH_FILTER" ), stereoGroup,
2911                                             LightApp_Preferences::Selector, "OCCViewer", "anaglyph_filter" );
2912   aValuesList.clear();
2913   anIndicesList.clear();
2914   aValuesList   << tr("PREF_ANAGLYPH_RED_CYAN") << tr("PREF_ANAGLYPH_YELLOW_BLUE") << tr("PREF_ANAGLYPH_GREEN_MAGENTA");
2915   anIndicesList << 0                            << 1                               << 2;
2916
2917   pref->setItemProperty( "strings", aValuesList,   anaglyphFilter );
2918   pref->setItemProperty( "indexes", anIndicesList, anaglyphFilter );
2919
2920   // .... -> Convergence distance type
2921   int occFocusType = pref->addPreference( tr( "PREF_FOCUS_TYPE" ), stereoGroup,
2922                                            LightApp_Preferences::Selector, "OCCViewer", "focus_type" );
2923   aValuesList.clear();
2924   anIndicesList.clear();
2925   aValuesList   << tr("PREF_ABSOLUTE") << tr("PREF_RELATIVE");
2926   anIndicesList << 0                   << 1;
2927   pref->setItemProperty( "strings", aValuesList,   occFocusType );
2928   pref->setItemProperty( "indexes", anIndicesList, occFocusType );
2929
2930   // .... -> Stereographic focus value
2931   int focusValue = pref->addPreference( tr( "PREF_FOCUS_VALUE" ), stereoGroup,
2932                LightApp_Preferences::DblSpin, "OCCViewer", "focus_value" );
2933   pref->setItemProperty( "precision", 3, focusValue );
2934   pref->setItemProperty( "min", 1.0E-03, focusValue );
2935   pref->setItemProperty( "max", 1.0E03, focusValue );
2936   pref->setItemProperty( "step", 0.05, focusValue );
2937
2938   // .... -> IOD type
2939   int occIODType = pref->addPreference( tr( "PREF_IOD_TYPE" ), stereoGroup,
2940                                            LightApp_Preferences::Selector, "OCCViewer", "iod_type" );
2941   aValuesList.clear();
2942   anIndicesList.clear();
2943   aValuesList   << tr("PREF_ABSOLUTE") << tr("PREF_RELATIVE");
2944   anIndicesList << 0                   << 1;
2945   pref->setItemProperty( "strings", aValuesList,   occIODType );
2946   pref->setItemProperty( "indexes", anIndicesList, occIODType );
2947
2948   // .... -> Interocular distance (IOD) value
2949   int IODValue = pref->addPreference( tr( "PREF_IOD_VALUE" ), stereoGroup,
2950                                       LightApp_Preferences::DblSpin, "OCCViewer", "iod_value" );
2951   pref->setItemProperty( "precision", 3, IODValue );
2952   pref->setItemProperty( "min", 1.0E-03, IODValue );
2953   pref->setItemProperty( "max", 1.0E03, IODValue );
2954   pref->setItemProperty( "step", 0.05, IODValue );
2955
2956   // .... -> Reverse stereo
2957   pref->addPreference( tr( "PREF_REVERSE_STEREO" ), stereoGroup,
2958                        LightApp_Preferences::Bool, "OCCViewer", "reverse_stereo" );
2959   // .... -> Enable V-Sync
2960   pref->addPreference( tr( "PREF_ENABLE_VSYNC" ), stereoGroup,
2961                        LightApp_Preferences::Bool, "OCCViewer", "enable_vsync" );
2962   // .... -> Enable quad-buffer support
2963   pref->addPreference( tr( "PREF_ENABLE_QUAD_BUFFER_SUPPORT" ), stereoGroup,
2964                        LightApp_Preferences::Bool, "OCCViewer", "enable_quad_buffer_support" );
2965
2966   // ... "Background" group <<start>>
2967   int bgGroup = pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), occGroup );
2968   //  pref->setItemProperty( "columns", 2, bgGroup );
2969   aValuesList.clear();
2970   anIndicesList.clear();
2971   txtList.clear();
2972   idList.clear();
2973   formats = OCCViewer_Viewer::backgroundData( aValuesList, idList, txtList );
2974   foreach( int gid, idList ) anIndicesList << gid;
2975   // .... -> 3D viewer background
2976   bgId = pref->addPreference( tr( "PREF_3DVIEWER_BACKGROUND" ), bgGroup,
2977                                   LightApp_Preferences::Background, "OCCViewer", "background" );
2978   pref->setItemProperty( "gradient_names", aValuesList, bgId );
2979   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
2980   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
2981   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
2982   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
2983   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
2984   pref->setItemProperty( "custom_enabled", false, bgId );
2985   pref->setItemProperty( "image_formats", formats, bgId );
2986   // .... -> XZ viewer background
2987   bgId = pref->addPreference( tr( "PREF_XZVIEWER_BACKGROUND" ), bgGroup,
2988                               LightApp_Preferences::Background, "OCCViewer", "xz_background" );
2989   pref->setItemProperty( "gradient_names", aValuesList, bgId );
2990   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
2991   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
2992   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
2993   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
2994   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
2995   pref->setItemProperty( "custom_enabled", false, bgId );
2996   pref->setItemProperty( "image_formats", formats, bgId );
2997   // .... -> YZ viewer background
2998   bgId = pref->addPreference( tr( "PREF_YZVIEWER_BACKGROUND" ), bgGroup,
2999                               LightApp_Preferences::Background, "OCCViewer", "yz_background" );
3000   pref->setItemProperty( "gradient_names", aValuesList, bgId );
3001   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
3002   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
3003   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
3004   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
3005   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
3006   pref->setItemProperty( "custom_enabled", false, bgId );
3007   pref->setItemProperty( "image_formats", formats, bgId );
3008   // .... -> XY viewer background
3009   bgId = pref->addPreference( tr( "PREF_XYVIEWER_BACKGROUND" ), bgGroup,
3010                               LightApp_Preferences::Background, "OCCViewer", "xy_background" );
3011   pref->setItemProperty( "gradient_names", aValuesList, bgId );
3012   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
3013   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
3014   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
3015   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
3016   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
3017   pref->setItemProperty( "custom_enabled", false, bgId );
3018   pref->setItemProperty( "image_formats", formats, bgId );
3019   // ... "Background" group <<end>>
3020
3021
3022   // ... "Selection" group <<start>>
3023   int occSelectionGroup = pref->addPreference( tr( "PREF_GROUP_SELECTION" ), occGroup );
3024   pref->setItemProperty( "columns", 3, occSelectionGroup );
3025   // .... -> enable preselection
3026   pref->addPreference( tr( "PREF_ENABLE_PRESELECTION" ), occSelectionGroup,
3027                        LightApp_Preferences::Bool, "OCCViewer", "enable_preselection" );
3028   // .... -> enable selection
3029   pref->addPreference( tr( "PREF_ENABLE_SELECTION" ), occSelectionGroup,
3030                        LightApp_Preferences::Bool, "OCCViewer", "enable_selection" );
3031   // .... -> selection style
3032   int aSeleStyle = pref->addPreference( tr( "PREF_SELECTION_STYLE" ), occSelectionGroup,
3033                        LightApp_Preferences::Selector, "OCCViewer", "adv_selection_mode" );
3034   aValuesList.clear();
3035   anIndicesList.clear();
3036   aValuesList   << tr("PREF_POLYGON_SELECTION") << tr("PREF_CIRCLE_SELECTION");
3037   anIndicesList << 0 << 1;
3038   pref->setItemProperty( "strings", aValuesList, aSeleStyle);
3039   pref->setItemProperty( "indexes", anIndicesList, aSeleStyle);
3040   // ... "Selection" group <<end>>
3041
3042   // ... "Clipping" group <<start>>
3043   int occClippingGroup = pref->addPreference( tr( "PREF_GROUP_CLIPPING" ), occGroup );
3044   // .... -> clipping color
3045   pref->addPreference( tr( "PREF_CLIPPING_COLOR" ), occClippingGroup,
3046                        LightApp_Preferences::Color, "OCCViewer", "clipping_color" );
3047   int texturePref = pref->addPreference( "", occClippingGroup, LightApp_Preferences::Frame );
3048   pref->setItemProperty( "columns", 2, texturePref );
3049   // .... -> use default texture
3050   pref->addPreference( tr( "PREF_CLIPPING_DEFAULT_TEXTURE" ), texturePref,
3051                LightApp_Preferences::Bool, "OCCViewer", "clipping_use_default_texture" );
3052   // .... -> clipping texture
3053   int filePref = pref->addPreference( tr( "PREF_CLIPPING_TEXTURE" ), texturePref,
3054                LightApp_Preferences::File, "OCCViewer", "clipping_texture" );
3055   pref->setItemProperty( "path_filter", tr( "OCC_TEXTURE_FILES" ), filePref );
3056   // .... -> modulate
3057   pref->addPreference( tr( "PREF_CLIPPING_MODULATE" ), texturePref,
3058                LightApp_Preferences::Bool, "OCCViewer", "clipping_modulate" );
3059   // .... -> scale factor
3060   int scaleFactor = pref->addPreference( tr( "PREF_CLIPPING_SCALE" ), texturePref,
3061                LightApp_Preferences::DblSpin, "OCCViewer", "clipping_scale" );
3062   pref->setItemProperty( "precision", 3, scaleFactor );
3063   pref->setItemProperty( "min", 1.0E-03, scaleFactor );
3064   pref->setItemProperty( "max", 1.0E03, scaleFactor );
3065   pref->setItemProperty( "step", 0.1, scaleFactor );
3066   // ... "Clipping" group <<end>>
3067
3068   // ... "Ray tracing" group <<start>>
3069   int occRayTracingGroup = pref->addPreference( tr( "PREF_GROUP_RAY_TRACING" ), occGroup );
3070   int rtPref = pref->addPreference( "", occRayTracingGroup, LightApp_Preferences::Frame );
3071   pref->setItemProperty( "columns", 2, rtPref );
3072   // .... -> depth
3073   int rt_depth = pref->addPreference( tr( "PREF_RAY_TRACING_DEPTH" ), rtPref,
3074                LightApp_Preferences::IntSpin, "OCCViewer", "rt_depth" );
3075   pref->setItemProperty( "min", 1, rt_depth );
3076   pref->setItemProperty( "max", 10, rt_depth );
3077   pref->setItemProperty( "step", 1, rt_depth );
3078   pref->addPreference( "", rtPref, LightApp_Preferences::Frame );
3079   // .... -> specular reflections
3080   pref->addPreference( tr( "PREF_RAY_TRACING_REFLECTION" ), rtPref,
3081                LightApp_Preferences::Bool, "OCCViewer", "rt_reflection" );
3082   // .... -> adaptive anti-aliasing
3083   pref->addPreference( tr( "PREF_RAY_TRACING_ANTIALIASING" ), rtPref,
3084                LightApp_Preferences::Bool, "OCCViewer", "rt_antialiasing" );
3085   // .... -> shadows rendering
3086   pref->addPreference( tr( "PREF_RAY_TRACING_SHADOW" ), rtPref,
3087                LightApp_Preferences::Bool, "OCCViewer", "rt_shadow" );
3088   // .... -> transparent shadow
3089   pref->addPreference( tr( "PREF_RAY_TRACING_TRANS_SHADOW" ), rtPref,
3090                LightApp_Preferences::Bool, "OCCViewer", "rt_trans_shadow" );
3091   // ... "Ray tracing" group <<end>>
3092
3093   // ... "Light source" group <<start>>
3094   int occLightGroup = pref->addPreference( tr( "PREF_GROUP_LIGHT" ), occGroup );
3095   // .... -> light color
3096   pref->addPreference( tr( "PREF_LIGHT_COLOR" ), occLightGroup,
3097                LightApp_Preferences::Color, "OCCViewer", "light_color" );
3098   int directionPref = pref->addPreference( "", occLightGroup, LightApp_Preferences::Frame );
3099   pref->setItemProperty( "columns", 3, directionPref );
3100   // .... -> light direction (dx component)
3101   int light_dx = pref->addPreference( tr( "Dx" ), directionPref,
3102                LightApp_Preferences::DblSpin, "OCCViewer", "light_dx" );
3103   pref->setItemProperty( "precision", 2, light_dx );
3104   pref->setItemProperty( "min", -1.0E03, light_dx );
3105   pref->setItemProperty( "max", 1.0E03, light_dx );
3106   pref->setItemProperty( "step", 0.1, light_dx );
3107   // .... -> light direction (dy component)
3108   int light_dy = pref->addPreference( tr( "Dy" ), directionPref,
3109                LightApp_Preferences::DblSpin, "OCCViewer", "light_dy" );
3110   pref->setItemProperty( "precision", 2, light_dy );
3111   pref->setItemProperty( "min", -1.0E03, light_dy );
3112   pref->setItemProperty( "max", 1.0E03, light_dy );
3113   pref->setItemProperty( "step", 0.1, light_dy );
3114   // .... -> light direction (dz component)
3115   int light_dz = pref->addPreference( tr( "Dz" ), directionPref,
3116                LightApp_Preferences::DblSpin, "OCCViewer", "light_dz" );
3117   pref->setItemProperty( "precision", 2, light_dz );
3118   pref->setItemProperty( "min", -1.0E03, light_dz );
3119   pref->setItemProperty( "max", 1.0E03, light_dz );
3120   pref->setItemProperty( "step", 0.1, light_dz );
3121   // ... "Light source" group <<end>>
3122
3123   // ... "View cube" group <<start>>
3124   int occViewCubeGroup = pref->addPreference( tr( "PREF_GROUP_VIEWCUBE" ), occGroup );
3125   pref->setItemProperty( "columns", 2, occViewCubeGroup );
3126   // .... -> show view cube on viewer start
3127   pref->addPreference( tr( "PREF_VIEWCUBE_SHOW" ), occViewCubeGroup,
3128                LightApp_Preferences::Bool, "OCCViewer", "viewcube_show" );
3129   // .... -> view cube duration of animation (sec)
3130   int viewcube_dur = pref->addPreference( tr( "PREF_VIEWCUBE_DURATION" ), occViewCubeGroup,
3131                LightApp_Preferences::DblSpin, "OCCViewer", "viewcube_duration" );
3132   pref->setItemProperty( "min", 0.1, viewcube_dur );
3133   pref->setItemProperty( "max", 10.0, viewcube_dur );
3134   pref->setItemProperty( "step", 0.1, viewcube_dur );
3135   // .... -> show view cube axes
3136   pref->addPreference( tr( "PREF_VIEWCUBE_AXES" ), occViewCubeGroup,
3137                LightApp_Preferences::Bool, "OCCViewer", "viewcube_axes" );
3138   // ... "View cube" group <<end>>
3139
3140   // ... "View cube default (OCCT) attributes" group <<start>>
3141   int occViewCubeAttrsGroup = pref->addPreference( tr( "PREF_VIEWCUBE_CUSTOM" ), occGroup,
3142                LightApp_Preferences::Auto, "OCCViewer", "viewcube_custom" );
3143   pref->setItemProperty( "columns", 2, occViewCubeAttrsGroup );
3144   // .... -> box color
3145   pref->addPreference( tr( "PREF_VIEWCUBE_COLOR" ), occViewCubeAttrsGroup,
3146                LightApp_Preferences::Color, "OCCViewer", "viewcube_color" );
3147   // .... -> view cube size
3148   int viewcube_size = pref->addPreference( tr( "PREF_VIEWCUBE_SIZE" ), occViewCubeAttrsGroup,
3149                LightApp_Preferences::DblSpin, "OCCViewer", "viewcube_size" );
3150   pref->setItemProperty( "min",  30.0, viewcube_size );
3151   pref->setItemProperty( "max", 100.0, viewcube_size );
3152   pref->setItemProperty( "step", 10.0, viewcube_size );
3153   // .... -> text color
3154   pref->addPreference( tr( "PREF_VIEWCUBE_TEXTCOLOR" ), occViewCubeAttrsGroup,
3155                LightApp_Preferences::Color, "OCCViewer", "viewcube_text_color" );
3156   // ... "View cube" group <<end>>
3157
3158   // ... -> empty frame (for layout) <<start>>
3159   int occGen = pref->addPreference( "", occGroup, LightApp_Preferences::Frame );
3160   pref->setItemProperty( "margin",  0, occGen );
3161   pref->setItemProperty( "columns", 2, occGen );
3162   // ... -> empty frame (for layout) <<end>>
3163
3164   // .. "OCC viewer" group <<end>>
3165 #endif
3166
3167 #ifndef DISABLE_VTKVIEWER
3168   // .. "VTK viewer" group <<start>>
3169   int vtkGroup = pref->addPreference( tr( "PREF_GROUP_VTKVIEWER" ), salomeCat ); //viewTab
3170
3171   // ... -> empty frame (for layout) <<start>>
3172   int vtkGen = pref->addPreference( "", vtkGroup, LightApp_Preferences::Frame );
3173   //pref->setItemProperty( "columns", 2, vtkGen );
3174   // .... -> projection mode
3175   int vtkProjMode = pref->addPreference( tr( "PREF_PROJECTION_MODE" ), vtkGen,
3176                                          LightApp_Preferences::Selector, "VTKViewer", "projection_mode" );
3177   aValuesList.clear();
3178   anIndicesList.clear();
3179   aValuesList   << tr("PREF_ORTHOGRAPHIC") << tr("PREF_PERSPECTIVE");
3180   anIndicesList << 0                       << 1;
3181   pref->setItemProperty( "strings", aValuesList,   vtkProjMode );
3182   pref->setItemProperty( "indexes", anIndicesList, vtkProjMode );
3183
3184   // .... -> Stereo group
3185   int vtkStereoGroup = pref->addPreference( tr( "PREF_GROUP_STEREO" ), vtkGroup);
3186   pref->setItemProperty( "columns", 2, vtkStereoGroup );
3187   // .... -> Stereo type
3188   int vtkStereoType = pref->addPreference( tr( "PREF_STEREO_TYPE" ), vtkStereoGroup,
3189                                            LightApp_Preferences::Selector, "VTKViewer", "stereo_type" );
3190   aValuesList.clear();
3191   anIndicesList.clear();
3192   idList.clear();
3193   SVTK_Viewer::stereoData( aValuesList, idList);
3194   foreach( int gid, idList ) anIndicesList << gid;
3195   pref->setItemProperty( "strings", aValuesList,   vtkStereoType );
3196   pref->setItemProperty( "indexes", anIndicesList, vtkStereoType );
3197   // .... -> Anaglyph filter
3198   int vtkAnaglyphFilter = pref->addPreference( tr( "PREF_ANAGLYPH_FILTER" ), vtkStereoGroup,
3199                                                LightApp_Preferences::Selector, "VTKViewer", "anaglyph_filter" );
3200   aValuesList.clear();
3201   anIndicesList.clear();
3202   aValuesList   << tr("PREF_ANAGLYPH_RED_CYAN") << tr("PREF_ANAGLYPH_YELLOW_BLUE") << tr("PREF_ANAGLYPH_GREEN_MAGENTA");
3203   anIndicesList << 0                            << 1                               << 2;
3204
3205   pref->setItemProperty( "strings", aValuesList,   vtkAnaglyphFilter );
3206   pref->setItemProperty( "indexes", anIndicesList, vtkAnaglyphFilter );
3207
3208   // .... -> Enable quad-buffer support
3209   pref->addPreference( tr( "PREF_ENABLE_QUAD_BUFFER_SUPPORT" ), vtkStereoGroup,
3210                        LightApp_Preferences::Bool, "VTKViewer", "enable_quad_buffer_support" );
3211
3212   // .... -> background
3213   aValuesList.clear();
3214   anIndicesList.clear();
3215   txtList.clear();
3216   idList.clear();
3217 #ifndef DISABLE_SALOMEOBJECT
3218   formats = SVTK_Viewer::backgroundData( aValuesList, idList, txtList );
3219 #endif
3220   foreach( int gid, idList ) anIndicesList << gid;
3221   bgId = pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), vtkGen,
3222                               LightApp_Preferences::Background, "VTKViewer", "background" );
3223   pref->setItemProperty( "gradient_names", aValuesList, bgId );
3224   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
3225   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
3226   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
3227   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
3228   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
3229   pref->setItemProperty( "custom_enabled", false, bgId );
3230 #ifndef DISABLE_SALOMEOBJECT
3231   pref->setItemProperty( "image_formats", formats, bgId );
3232 #endif
3233   // .... -> speed increment
3234   int vtkSpeed = pref->addPreference( tr( "PREF_INCREMENTAL_SPEED" ), vtkGen,
3235                                       LightApp_Preferences::IntSpin, "VTKViewer", "speed_value" );
3236   pref->setItemProperty( "min", 1, vtkSpeed );
3237   pref->setItemProperty( "max", 1000, vtkSpeed );
3238   // .... -> speed mode
3239   int vtkSpeedMode = pref->addPreference( tr( "PREF_INCREMENTAL_SPEED_MODE" ), vtkGen,
3240                                           LightApp_Preferences::Selector, "VTKViewer", "speed_mode" );
3241   aValuesList.clear();
3242   anIndicesList.clear();
3243   aValuesList   << tr("PREF_ARITHMETIC") << tr("PREF_GEOMETRICAL");
3244   anIndicesList << 0                     << 1;
3245   pref->setItemProperty( "strings", aValuesList,   vtkSpeedMode );
3246   pref->setItemProperty( "indexes", anIndicesList, vtkSpeedMode );
3247
3248   // ... "Selection" group <<start>>
3249   int vtkSelectionGroup = pref->addPreference( tr( "PREF_GROUP_SELECTION" ), vtkGroup );
3250   pref->setItemProperty( "columns", 2, vtkSelectionGroup );
3251   // .... -> preselection
3252   int vtkPreselection = pref->addPreference( tr( "PREF_PRESELECTION" ),  vtkSelectionGroup,
3253                                              LightApp_Preferences::Selector, "VTKViewer", "preselection" );
3254   aValuesList.clear();
3255   anIndicesList.clear();
3256   aValuesList   << tr("PREF_PRESELECTION_STANDARD") << tr("PREF_PRESELECTION_DYNAMIC") << tr("PREF_PRESELECTION_DISABLED");
3257   anIndicesList << 0 << 1 << 2;
3258   pref->setItemProperty( "strings", aValuesList,   vtkPreselection );
3259   pref->setItemProperty( "indexes", anIndicesList, vtkPreselection );
3260   // .... -> enable selection
3261   pref->addPreference( tr( "PREF_ENABLE_SELECTION" ), vtkSelectionGroup, LightApp_Preferences::Bool, "VTKViewer", "enable_selection" );
3262   // ... "Selection" group <<end>>
3263
3264   // ... -> empty frame (for layout) <<end>>
3265
3266   // ... space mouse sub-group <<start>>
3267   int vtkSM = pref->addPreference( tr( "PREF_FRAME_SPACEMOUSE" ), vtkGroup, LightApp_Preferences::GroupBox );
3268   //pref->setItemProperty( "columns", 2, vtkSM );
3269   // .... -> decrease speed increment
3270   int spacemousePref1 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_1" ), vtkSM,
3271                                              LightApp_Preferences::Selector, "VTKViewer",
3272                                              "spacemouse_func1_btn" );
3273   // .... -> increase speed increment
3274   int spacemousePref2 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_2" ), vtkSM,
3275                                              LightApp_Preferences::Selector, "VTKViewer",
3276                                              "spacemouse_func2_btn" );
3277   // .... -> dominant / combined switch
3278   int spacemousePref3 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_3" ), vtkSM,
3279                                              LightApp_Preferences::Selector, "VTKViewer",
3280                                              "spacemouse_func5_btn" ); //
3281   aValuesList.clear();
3282   anIndicesList.clear();
3283   aValuesList << tr( "PREF_SPACEMOUSE_BTN_1" )  << tr( "PREF_SPACEMOUSE_BTN_2" ) << tr( "PREF_SPACEMOUSE_BTN_3" );
3284   aValuesList << tr( "PREF_SPACEMOUSE_BTN_4" )  << tr( "PREF_SPACEMOUSE_BTN_5" ) << tr( "PREF_SPACEMOUSE_BTN_6" );
3285   aValuesList << tr( "PREF_SPACEMOUSE_BTN_7" )  << tr( "PREF_SPACEMOUSE_BTN_8" ) << tr( "PREF_SPACEMOUSE_BTN_*" );
3286   aValuesList << tr( "PREF_SPACEMOUSE_BTN_10" ) << tr( "PREF_SPACEMOUSE_BTN_11" );
3287   anIndicesList << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11;
3288   pref->setItemProperty( "strings", aValuesList,   spacemousePref1 );
3289   pref->setItemProperty( "indexes", anIndicesList, spacemousePref1 );
3290   pref->setItemProperty( "strings", aValuesList,   spacemousePref2 );
3291   pref->setItemProperty( "indexes", anIndicesList, spacemousePref2 );
3292   pref->setItemProperty( "strings", aValuesList,   spacemousePref3 );
3293   pref->setItemProperty( "indexes", anIndicesList, spacemousePref3 );
3294   // ... space mouse sub-group <<end>>
3295
3296   // ... avi recording sub-group <<start>>
3297   int vtkRec = pref->addPreference( tr( "PREF_FRAME_RECORDING" ), vtkGroup, LightApp_Preferences::GroupBox );
3298   pref->setItemProperty( "columns", 2, vtkRec );
3299   // .... -> recording mode
3300   int modePref = pref->addPreference( tr( "PREF_RECORDING_MODE" ), vtkRec,
3301                                       LightApp_Preferences::Selector, "VTKViewer", "recorder_mode" );
3302   aValuesList.clear();
3303   anIndicesList.clear();
3304   aValuesList   << tr( "PREF_SKIPPED_FRAMES" ) << tr( "PREF_ALL_DISLPAYED_FRAMES" );
3305   anIndicesList << 0                           << 1;
3306   pref->setItemProperty( "strings", aValuesList,   modePref );
3307   pref->setItemProperty( "indexes", anIndicesList, modePref );
3308   // .... -> fps
3309   int fpsPref = pref->addPreference( tr( "PREF_FPS" ), vtkRec,
3310                                      LightApp_Preferences::DblSpin, "VTKViewer", "recorder_fps" );
3311   pref->setItemProperty( "min", 0.1, fpsPref );
3312   pref->setItemProperty( "max", 100, fpsPref );
3313   // .... -> quality
3314   int qualityPref = pref->addPreference( tr( "PREF_QUALITY" ), vtkRec,
3315                                          LightApp_Preferences::IntSpin, "VTKViewer", "recorder_quality" );
3316   pref->setItemProperty( "min", 1, qualityPref );
3317   pref->setItemProperty( "max", 100, qualityPref );
3318   // .... -> progressive mode
3319   pref->addPreference( tr( "PREF_PROGRESSIVE" ), vtkRec,
3320                        LightApp_Preferences::Bool, "VTKViewer", "recorder_progressive" );
3321   // ... avi recording sub-group <<end>>
3322
3323   // ... group names sub-group <<start>>
3324   int vtkGN = pref->addPreference( tr( "PREF_FRAME_GROUP_NAMES" ), vtkGroup,
3325                                    LightApp_Preferences::GroupBox, "VTKViewer", "show_group_names" );
3326   pref->setItemProperty( "columns", 2, vtkGN );
3327   // .... -> text color
3328   pref->addPreference( tr(  "PREF_GROUP_NAMES_TEXT_COLOR" ), vtkGN,
3329                        LightApp_Preferences::Color, "VTKViewer", "group_names_text_color" );
3330   // .... -> transparency
3331   int transPref = pref->addPreference( tr( "PREF_GROUP_NAMES_TRANSPARENCY" ), vtkGN,
3332                                        LightApp_Preferences::DblSpin, "VTKViewer", "group_names_transparency" );
3333   pref->setItemProperty( "min", 0.0, transPref );
3334   pref->setItemProperty( "max", 1.0, transPref );
3335   pref->setItemProperty( "step", 0.1, transPref );
3336   // ... -> group names sub-group <<end>>
3337   // .. "VTK viewer" group <<end>>
3338 #endif
3339
3340   // .. "Plot2d viewer" group <<start>>
3341   int plot2dGroup = pref->addPreference( tr( "PREF_GROUP_PLOT2DVIEWER" ), salomeCat ); //viewTab
3342   //pref->setItemProperty( "columns", 2, plot2dGroup );
3343
3344   // ... -> background
3345   pref->addPreference( tr( "PREF_VIEWER_BACKGROUND_COLOR" ), plot2dGroup,
3346                        LightApp_Preferences::Color, "Plot2d", "Background" );
3347   // ... -> selection color
3348   pref->addPreference( tr( "PREF_VIEWER_SELECTION" ), plot2dGroup,
3349                        LightApp_Preferences::Color, "Plot2d", "SelectionColor" );
3350
3351   // ... "Viewer" group <<start>>
3352   int plot2dViewerGroup = pref->addPreference( tr( "PREF_GROUP_VIEWER" ), plot2dGroup );
3353
3354   // .... -> curve type
3355   int curveType = pref->addPreference( tr( "PREF_CURVE_TYPE" ), plot2dViewerGroup,
3356                                        LightApp_Preferences::Selector, "Plot2d", "CurveType" );
3357   aValuesList.clear();
3358   anIndicesList.clear();
3359   aValuesList   << tr("PREF_POINTS") << tr("PREF_LINES") << tr("PREF_SPLINE");
3360   anIndicesList << 0                 << 1                << 2                ;
3361   pref->setItemProperty( "strings", aValuesList,   curveType );
3362   pref->setItemProperty( "indexes", anIndicesList, curveType );
3363   // .... -> marker size
3364   int markerSize = pref->addPreference( tr( "PREF_MARKER_SIZE" ), plot2dViewerGroup,
3365                                         LightApp_Preferences::IntSpin, "Plot2d", "MarkerSize" );
3366   pref->setItemProperty( "min", 0, markerSize );
3367   pref->setItemProperty( "max", 100, markerSize );
3368   // .... -> horizontal scaling mode
3369   int horScale = pref->addPreference( tr( "PREF_HOR_AXIS_SCALE" ), plot2dViewerGroup,
3370                                       LightApp_Preferences::Selector, "Plot2d", "HorScaleMode" );
3371   aValuesList.clear();
3372   anIndicesList.clear();
3373   aValuesList   << tr("PREF_LINEAR") << tr("PREF_LOGARITHMIC");
3374   anIndicesList << 0                 << 1                     ;
3375   pref->setItemProperty( "strings", aValuesList,   horScale );
3376   pref->setItemProperty( "indexes", anIndicesList, horScale );
3377   // .... -> vertical scaling mode
3378   int verScale = pref->addPreference( tr( "PREF_VERT_AXIS_SCALE" ), plot2dViewerGroup,
3379                                       LightApp_Preferences::Selector, "Plot2d", "VerScaleMode" );
3380   pref->setItemProperty( "strings", aValuesList,   verScale );
3381   pref->setItemProperty( "indexes", anIndicesList, verScale );
3382
3383   // .... -> errors/deviation colot
3384   pref->addPreference( tr( "PREF_DEVIATION_COLOR" ), plot2dViewerGroup,
3385                        LightApp_Preferences::Color, "Plot2d", "DeviationMarkerColor" );
3386   // .... -> deviation markers line size
3387   int deviationMarkerLw = pref->addPreference( tr( "PREF_DEVIATION_MARKER_LW" ), plot2dViewerGroup,
3388                                         LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerLineWidth" );
3389   pref->setItemProperty( "min", 1, deviationMarkerLw );
3390   pref->setItemProperty( "max", 5, deviationMarkerLw );
3391   // .... -> deviation markers tick mark size
3392   int deviationMarkerTs = pref->addPreference( tr( "PREF_DEVIATION_MARKER_TS" ), plot2dViewerGroup,
3393                                         LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerTickSize" );
3394   pref->setItemProperty( "min", 1, deviationMarkerTs );
3395   pref->setItemProperty( "max", 5, deviationMarkerTs );
3396   // .... "Viewer" group <<end>>
3397
3398   // ... "Legend" group <<start>>
3399   int plot2dLegendGroup = pref->addPreference( tr( "PREF_GROUP_LEGEND" ), plot2dGroup );
3400
3401   // .... -> show legend
3402   pref->addPreference( tr( "PREF_SHOW_LEGEND" ), plot2dLegendGroup,
3403                        LightApp_Preferences::Bool, "Plot2d", "ShowLegend" );
3404   // .... -> legend position
3405   int legendPosition = pref->addPreference( tr( "PREF_LEGEND_POSITION" ), plot2dLegendGroup,
3406                                             LightApp_Preferences::Selector, "Plot2d", "LegendPos" );
3407   aValuesList.clear();
3408   anIndicesList.clear();
3409   aValuesList   << tr("PREF_LEFT") << tr("PREF_RIGHT") << tr("PREF_TOP") << tr("PREF_BOTTOM");
3410   anIndicesList << 0               << 1                << 2              << 3                ;
3411   pref->setItemProperty( "strings", aValuesList,   legendPosition );
3412   pref->setItemProperty( "indexes", anIndicesList, legendPosition );
3413   // .... -> Symbol type
3414   int legendSymbolType = pref->addPreference( tr( "PREF_LEGEND_SYMBOL_TYPE" ), plot2dLegendGroup,
3415                                             LightApp_Preferences::Selector, "Plot2d", "LegendSymbolType" );
3416   aValuesList.clear();
3417   anIndicesList.clear();
3418   aValuesList   << tr("PREF_MARKER_ON_LINE") << tr("PREF_MARKER_ABOVE_LINE");
3419   anIndicesList << 0                            << 1                        ;
3420   pref->setItemProperty( "strings", aValuesList,   legendSymbolType );
3421   pref->setItemProperty( "indexes", anIndicesList, legendSymbolType );
3422   // .... -> legend font
3423   pref->addPreference( tr( "PREF_LEGEND_FONT" ), plot2dLegendGroup, LightApp_Preferences::Font, "Plot2d", "LegendFont" );
3424   // ... -> font color
3425   pref->addPreference( tr( "PREF_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "LegendFontColor" );
3426   // ... -> selection font color
3427   pref->addPreference( tr( "PREF_SELECTED_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "SelectedLegendFontColor" );
3428   // ... "Legend" group <<end>>
3429
3430   // .. "Plot2d viewer" group <<end>>
3431
3432   // .. "PyViewer" preferences tab <<start>>
3433   int pyeditTab = pref->addPreference( tr( "PREF_TAB_PYEDITOR" ), salomeCat );
3434   // ... "Font settings" group <<start>>
3435   int pyFontGroup = pref->addPreference( tr( "PREF_GROUP_PY_FONT" ), pyeditTab );
3436   int pyFont = pref->addPreference( tr( "PREF_PY_FONT" ), pyFontGroup,
3437                                     LightApp_Preferences::Font, "PyEditor", "Font" );
3438   pref->setItemProperty( "features", QtxFontEdit::Family | QtxFontEdit::Size | QtxFontEdit::UserSize, pyFont );
3439   // ... "Font settings" group <<end>>
3440   // ... "Display settings" group <<start>>
3441   int pyDispGroup = pref->addPreference( tr( "PREF_GROUP_PY_DISPLAY" ), pyeditTab );
3442   pref->setItemProperty( "columns", 2, pyDispGroup );
3443   // ... -> current line highlight
3444   pref->addPreference( tr( "PREF_PY_CURRLINE_HIGHLIGHT" ), pyDispGroup,
3445     LightApp_Preferences::Bool, "PyEditor", "HighlightCurrentLine" );
3446   // ... -> text wrapping
3447   pref->addPreference( tr( "PREF_PY_TEXT_WRAP" ), pyDispGroup,
3448     LightApp_Preferences::Bool, "PyEditor", "TextWrapping" );
3449   // ... -> center cursor on scroll
3450   pref->addPreference( tr( "PREF_PY_CURSON_ON_SCROLL" ), pyDispGroup,
3451     LightApp_Preferences::Bool, "PyEditor", "CenterCursorOnScroll" );
3452   // ... -> line numbers area
3453   pref->addPreference( tr( "PREF_PY_LINE_NUMBS_AREA" ), pyDispGroup,
3454     LightApp_Preferences::Bool, "PyEditor", "LineNumberArea" );
3455   // ... "Display settings" group <<end>>
3456
3457   // ... "Editor settings" group <<start>>
3458   int pyEditGroup = pref->addPreference( tr( "PREF_GROUP_PY_EDITOR" ), pyeditTab );
3459   // ... -> navigation mode
3460   int pyCompletion = pref->addPreference( tr( "PREF_PY_COMPLETION_MODE" ), pyEditGroup,
3461                                           LightApp_Preferences::Selector, "PyEditor", "CompletionPolicy" );
3462   aValuesList.clear();
3463   anIndicesList.clear();
3464   aValuesList   << tr("PREF_PY_NONE") << tr("PREF_PY_AUTO") << tr("PREF_PY_MANUAL") << tr("PREF_PY_ALWAYS");
3465   anIndicesList << 0                  << 1                  << 2                    << 3                   ;
3466   pref->setItemProperty( "strings", aValuesList, pyCompletion );
3467   pref->setItemProperty( "indexes", anIndicesList, pyCompletion );
3468   // ... "Editor settings" group <<end>>
3469
3470   // ... "Tab settings" group <<start>>
3471   int pyTabGroup = pref->addPreference( tr( "PREF_GROUP_PY_TAB" ), pyeditTab );
3472   pref->setItemProperty( "columns", 2, pyTabGroup );
3473   // ... -> tab whitespaces
3474   pref->addPreference( tr( "PREF_PY_TAB_WHITESPACES" ), pyTabGroup,
3475     LightApp_Preferences::Bool, "PyEditor", "TabSpaceVisible" );
3476   // ... -> tab size
3477   pref->addPreference( tr( "PREF_PY_TAB_SIZE" ), pyTabGroup,
3478     LightApp_Preferences::IntSpin, "PyEditor", "TabSize" );
3479   // ... "Tab settings" group <<end>>
3480   // ... "Vertical edge settings" group <<start>>
3481   int pyVertEdgeGroup = pref->addPreference( tr( "PREF_GROUP_VERT_EDGE" ), pyeditTab );
3482   pref->setItemProperty( "columns", 2, pyVertEdgeGroup );
3483   // ... -> vertical edge
3484   pref->addPreference( tr( "PREF_PY_VERT_EDGE" ), pyVertEdgeGroup,
3485     LightApp_Preferences::Bool, "PyEditor", "VerticalEdge" );
3486   // ... -> number of columns
3487   pref->addPreference( tr( "PREF_PY_NUM_COLUMNS" ), pyVertEdgeGroup,
3488     LightApp_Preferences::IntSpin, "PyEditor", "NumberColumns" );
3489   // ... "Vertical edge settings" group <<end>>
3490   // .. "PyEditor" preferences tab <<end>>
3491
3492   // .. "Directories" preferences tab <<start>>
3493   int dirTab = pref->addPreference( tr( "PREF_TAB_DIRECTORIES" ), salomeCat );
3494   // ... --> quick directories list
3495   int dirGroup = pref->addPreference( tr( "PREF_GROUP_DIRECTORIES" ), dirTab );
3496   pref->addPreference( tr( "" ), dirGroup,
3497                        LightApp_Preferences::DirList, "FileDlg", "QuickDirList" );
3498   // .. "Directories" preferences tab <<end>>
3499
3500   // .. "Object browser" preferences tab <<start>>
3501   int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
3502
3503   // ... "Search tool" group <<start>>
3504   int stGroup = pref->addPreference( tr( "PREF_OBJ_BROWSER_SEARCH_TOOL" ), obTab );
3505   // .... --> auto-hide
3506   pref->addPreference( tr( "PREF_AUTO_HIDE_SEARCH_TOOL" ), stGroup, LightApp_Preferences::Bool,
3507                        "ObjectBrowser", "auto_hide_search_tool" );
3508   // ... "Search tool" group <<end>>
3509
3510   // ... "Object browser settings" group <<start>>
3511   int objSetGroup = pref->addPreference( tr( "PREF_GROUP_LOOK_AND_FEEL" ), obTab );
3512   pref->setItemProperty( "columns", 2, objSetGroup );
3513   // .... -> auto size first column
3514   pref->addPreference( tr( "PREF_AUTO_SIZE_FIRST" ), objSetGroup, LightApp_Preferences::Bool,
3515                        "ObjectBrowser", "auto_size_first" );
3516   // .... -> auto size other columns
3517   pref->addPreference( tr( "PREF_AUTO_SIZE" ), objSetGroup, LightApp_Preferences::Bool,
3518                        "ObjectBrowser", "auto_size" );
3519   // .... -> resize columns on expand item
3520   pref->addPreference( tr( "PREF_RESIZE_ON_EXPAND_ITEM" ), objSetGroup, LightApp_Preferences::Bool,
3521                        "ObjectBrowser", "resize_on_expand_item" );
3522   // .... -> browse to published object
3523   int browsePublished = pref->addPreference( tr( "PREF_BROWSE_TO_THE_PUBLISHED_OBJECT" ), objSetGroup, LightApp_Preferences::Selector,
3524                                              "ObjectBrowser", "browse_published_object" );
3525   aValuesList.clear();
3526   anIndicesList.clear();
3527   aValuesList << tr( "PREF_BROWSE_NEVER" ) << tr( "PREF_BROWSE_AFTER_APPLY_AND_CLOSE_ONLY" ) << tr( "PREF_BROWSE_ALWAYS" );
3528   anIndicesList << BP_Never << BP_ApplyAndClose << BP_Always;
3529   pref->setItemProperty( "strings", aValuesList,   browsePublished );
3530   pref->setItemProperty( "indexes", anIndicesList, browsePublished );
3531   // ... "Object browser settings" group <<end>>
3532   // .. "Object browser" preferences tab <<end>>
3533
3534   // .. "Shortcuts" preferences tab <<start>>
3535   int shortcutTab = pref->addPreference( tr( "PREF_TAB_SHORTCUTS" ), salomeCat );
3536   // ... "Shortcuts settings" group <<start>>
3537   int shortcutGroup = pref->addPreference( tr( "PREF_GROUP_SHORTCUTS" ), shortcutTab );
3538   pref->addPreference( tr( "" ), shortcutGroup,
3539                        LightApp_Preferences::ShortcutTree, "shortcuts" );
3540   // ... "Shortcuts settings" group <<end>>
3541   // .. "Shortcuts" preferences tab <<end>>
3542   // . Top-level "SALOME" preferences group <<end>>
3543
3544   pref->retrieve();
3545 }
3546
3547 /*!
3548   Changes appearance of application according to changed preferences
3549   \param sec - section
3550   \param param - name of changed parameter
3551 */
3552 void LightApp_Application::preferencesChanged( const QString& sec, const QString& param )
3553 {
3554   SUIT_ResourceMgr* resMgr = resourceMgr();
3555   if ( !resMgr )
3556     return;
3557
3558   if ( sec == "viewers" && param == "drop_down_buttons" )
3559   {
3560     ViewManagerList vmlist = viewManagers();
3561     foreach( SUIT_ViewManager* vm, vmlist )
3562     {
3563       QVector<SUIT_ViewWindow*> vwlist = vm->getViews();
3564       foreach( SUIT_ViewWindow* vw, vwlist )
3565         if ( vw ) vw->setDropDownButtons( resMgr->booleanValue( "viewers", "drop_down_buttons", true ) );
3566     }
3567   }
3568
3569   if ( sec == QString( "3DViewer" ) && (param == QString( "trihedron_size" ) || param == QString( "relative_size" )))
3570   {
3571     double sz = resMgr->doubleValue( sec, "trihedron_size", -1 );
3572     bool relative = resMgr->booleanValue( sec, "relative_size", true );
3573     QList<SUIT_ViewManager*> lst;
3574 #ifndef DISABLE_OCCVIEWER
3575     viewManagers( OCCViewer_Viewer::Type(), lst );
3576     QListIterator<SUIT_ViewManager*> itOCC( lst );
3577     while ( itOCC.hasNext() && sz >= 0 )
3578     {
3579       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3580       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3581         continue;
3582
3583       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3584       occVM->setTrihedronSize( sz, relative );
3585       occVM->getAISContext()->UpdateCurrentViewer();
3586     }
3587 #endif
3588 #ifndef DISABLE_VTKVIEWER
3589 #ifndef DISABLE_SALOMEOBJECT
3590     viewManagers( SVTK_Viewer::Type(), lst );
3591     QListIterator<SUIT_ViewManager*> itVTK( lst );
3592     while ( itVTK.hasNext() && sz >= 0 )
3593     {
3594       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3595       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3596         continue;
3597
3598       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3599       if( vtkVM )
3600       {
3601         vtkVM->setTrihedronSize( sz, relative );
3602         vtkVM->Repaint();
3603       }
3604     }
3605 #endif
3606 #endif
3607   }
3608
3609   if ( sec == QString( "3DViewer" ) && param == QString( "show_static_trihedron" ) )
3610   {
3611     bool isVisible = resMgr->booleanValue( "3DViewer", "show_static_trihedron", true );
3612     QList<SUIT_ViewManager*> lst;
3613 #ifndef DISABLE_OCCVIEWER
3614     viewManagers( OCCViewer_Viewer::Type(), lst );
3615     QListIterator<SUIT_ViewManager*> itOCC( lst );
3616     while ( itOCC.hasNext() )
3617     {
3618       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3619       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3620         continue;
3621
3622       OCCViewer_Viewer* occVM = dynamic_cast<OCCViewer_Viewer*>( vm );
3623       if( occVM )
3624       {
3625         occVM->setStaticTrihedronDisplayed( isVisible );
3626       }
3627     }
3628 #endif
3629 #ifndef DISABLE_VTKVIEWER
3630 #ifndef DISABLE_SALOMEOBJECT
3631     viewManagers( SVTK_Viewer::Type(), lst );
3632     QListIterator<SUIT_ViewManager*> itVTK( lst );
3633     while ( itVTK.hasNext() )
3634     {
3635       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3636       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3637         continue;
3638
3639       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3640       if( vtkVM )
3641       {
3642         vtkVM->setStaticTrihedronVisible( isVisible );
3643         vtkVM->Repaint();
3644       }
3645     }
3646 #endif
3647 #endif
3648   }
3649
3650   if ( sec == QString( "3DViewer" ) && param == QString( "navigation_mode" ) )
3651   {
3652     int mode = resMgr->integerValue( "3DViewer", "navigation_mode", 0 );
3653     QList<SUIT_ViewManager*> lst;
3654 #ifndef DISABLE_OCCVIEWER
3655     viewManagers( OCCViewer_Viewer::Type(), lst );
3656     QListIterator<SUIT_ViewManager*> itOCC( lst );
3657     while ( itOCC.hasNext() )
3658     {
3659       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3660       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3661         continue;
3662
3663       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3664       occVM->setInteractionStyle( mode );
3665     }
3666 #endif
3667 #ifndef DISABLE_VTKVIEWER
3668 #ifndef DISABLE_SALOMEOBJECT
3669     viewManagers( SVTK_Viewer::Type(), lst );
3670     QListIterator<SUIT_ViewManager*> itVTK( lst );
3671     while ( itVTK.hasNext() )
3672     {
3673       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3674       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3675         continue;
3676
3677       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3678       if( vtkVM ) vtkVM->setInteractionStyle( mode );
3679     }
3680 #endif
3681 #endif
3682   }
3683
3684 #ifndef DISABLE_OCCVIEWER
3685   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_preselection" ) )
3686   {
3687     bool isToEnablePreselection = resMgr->booleanValue( "OCCViewer", "enable_preselection", true );
3688     QList<SUIT_ViewManager*> lst;
3689     viewManagers( OCCViewer_Viewer::Type(), lst );
3690     QListIterator<SUIT_ViewManager*> it( lst );
3691     while ( it.hasNext() )
3692     {
3693       SUIT_ViewModel* vm = it.next()->getViewModel();
3694       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3695         continue;
3696
3697       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3698       occVM->enablePreselection( isToEnablePreselection );
3699     }
3700   }
3701 #endif
3702
3703 #ifndef DISABLE_OCCVIEWER
3704   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_selection" ) )
3705   {
3706     bool isToEnableSelection = resMgr->booleanValue( "OCCViewer", "enable_selection", true );
3707     QList<SUIT_ViewManager*> lst;
3708     viewManagers( OCCViewer_Viewer::Type(), lst );
3709     QListIterator<SUIT_ViewManager*> it( lst );
3710     while ( it.hasNext() )
3711     {
3712       SUIT_ViewModel* vm = it.next()->getViewModel();
3713       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3714         continue;
3715
3716       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3717       occVM->enableSelection( isToEnableSelection );
3718     }
3719   }
3720 #endif
3721
3722 #ifndef DISABLE_OCCVIEWER
3723   if ( sec == QString( "OCCViewer" ) && param == QString( "clipping_color" ) )
3724   {
3725     QColor aColor = resMgr->colorValue( "OCCViewer", "clipping_color", QColor( 50, 50, 50 ) );
3726     QList<SUIT_ViewManager*> lst;
3727     viewManagers( OCCViewer_Viewer::Type(), lst );
3728     QListIterator<SUIT_ViewManager*> it( lst );
3729     while ( it.hasNext() )
3730     {
3731       SUIT_ViewModel* vm = it.next()->getViewModel();
3732       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3733         continue;
3734
3735       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3736       occVM->setClippingColor( aColor );
3737     }
3738   }
3739 #endif
3740
3741 #ifndef DISABLE_OCCVIEWER
3742   if ( sec == QString( "OCCViewer" ) && ( param == QString( "clipping_use_default_texture" ) ||
3743                                           param == QString( "clipping_texture" ) ||
3744                                           param == QString( "clipping_modulate" ) ||
3745                                           param == QString( "clipping_scale" ) ) )
3746   {
3747     bool isDefaultTextureUsed = resMgr->booleanValue( "OCCViewer", "clipping_use_default_texture" );
3748     QString aTexture = resMgr->stringValue( "OCCViewer", "clipping_texture" );
3749     bool isModulated = resMgr->booleanValue( "OCCViewer", "clipping_modulate" );
3750     double aScale = resMgr->doubleValue( "OCCViewer", "clipping_scale" );
3751     QList<SUIT_ViewManager*> lst;
3752     viewManagers( OCCViewer_Viewer::Type(), lst );
3753     QListIterator<SUIT_ViewManager*> it( lst );
3754     while ( it.hasNext() )
3755     {
3756       SUIT_ViewModel* vm = it.next()->getViewModel();
3757       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3758         continue;
3759
3760       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3761       occVM->setClippingTextureParams( isDefaultTextureUsed, aTexture, isModulated, aScale );
3762     }
3763   }
3764 #endif
3765
3766 #ifndef DISABLE_OCCVIEWER
3767   if ( sec == QString( "OCCViewer" ) && param == QString( "projection_mode" ) )
3768   {
3769     int mode = resMgr->integerValue( "OCCViewer", "projection_mode", 0 );
3770     QList<SUIT_ViewManager*> lst;
3771     viewManagers( OCCViewer_Viewer::Type(), lst );
3772     QListIterator<SUIT_ViewManager*> it( lst );
3773     while ( it.hasNext() )
3774     {
3775       SUIT_ViewModel* vm = it.next()->getViewModel();
3776       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3777         continue;
3778
3779       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3780       occVM->setProjectionType( mode );
3781     }
3782   }
3783 #endif
3784
3785
3786 #ifndef DISABLE_OCCVIEWER
3787   if (sec == QString("OCCViewer") && param == QString("adv_selection_mode"))
3788   {
3789     int mode = resMgr->integerValue("OCCViewer", "adv_selection_mode", 0);
3790     QList<SUIT_ViewManager*> lst;
3791     viewManagers(OCCViewer_Viewer::Type(), lst);
3792     QListIterator<SUIT_ViewManager*> it(lst);
3793     while (it.hasNext())
3794     {
3795       SUIT_ViewModel* vm = it.next()->getViewModel();
3796       if (!vm || !vm->inherits("OCCViewer_Viewer"))
3797         continue;
3798
3799       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3800       occVM->setSelectionStyle((OCCViewer_ViewWindow::SelectionStyle)mode);
3801     }
3802   }
3803 #endif
3804
3805
3806 #ifndef DISABLE_OCCVIEWER
3807   if ( sec == QString( "OCCViewer" ) && param == QString( "stereo_type" ) )
3808   {
3809     int mode = resMgr->integerValue( "OCCViewer", "stereo_type", 0 );
3810     QList<SUIT_ViewManager*> lst;
3811     viewManagers( OCCViewer_Viewer::Type(), lst );
3812     QListIterator<SUIT_ViewManager*> it( lst );
3813     while ( it.hasNext() )
3814     {
3815       SUIT_ViewModel* vm = it.next()->getViewModel();
3816       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3817         continue;
3818
3819       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3820       occVM->setStereoType( mode );
3821     }
3822   }
3823 #endif
3824
3825 #ifndef DISABLE_OCCVIEWER
3826   if ( sec == QString( "OCCViewer" ) && param == QString( "anaglyph_filter" ) )
3827   {
3828     int mode = resMgr->integerValue( "OCCViewer", "anaglyph_filter", 0 );
3829     QList<SUIT_ViewManager*> lst;
3830     viewManagers( OCCViewer_Viewer::Type(), lst );
3831     QListIterator<SUIT_ViewManager*> it( lst );
3832     while ( it.hasNext() )
3833     {
3834       SUIT_ViewModel* vm = it.next()->getViewModel();
3835       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3836         continue;
3837
3838       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3839       occVM->setAnaglyphFilter( mode );
3840     }
3841   }
3842 #endif
3843
3844 #ifndef DISABLE_OCCVIEWER
3845   if ( sec == QString( "OCCViewer" ) && ( param == QString( "focus_type" ) ||
3846                                           param == QString( "focus_value" ) ) )
3847   {
3848     int aType = resMgr->integerValue( "OCCViewer", "focus_type" );
3849     double aValue = resMgr->doubleValue( "OCCViewer", "focus_value" );
3850     QList<SUIT_ViewManager*> lst;
3851     viewManagers( OCCViewer_Viewer::Type(), lst );
3852     QListIterator<SUIT_ViewManager*> it( lst );
3853     while ( it.hasNext() )
3854     {
3855       SUIT_ViewModel* vm = it.next()->getViewModel();
3856       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3857         continue;
3858
3859       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3860       occVM->setStereographicFocus( aType, aValue );
3861     }
3862   }
3863 #endif
3864
3865 #ifndef DISABLE_OCCVIEWER
3866   if ( sec == QString( "OCCViewer" ) && ( param == QString( "iod_type" ) ||
3867                                           param == QString( "iod_value" ) ) )
3868   {
3869     int aType = resMgr->integerValue( "OCCViewer", "iod_type" );
3870     double aValue = resMgr->doubleValue( "OCCViewer", "iod_value" );
3871     QList<SUIT_ViewManager*> lst;
3872     viewManagers( OCCViewer_Viewer::Type(), lst );
3873     QListIterator<SUIT_ViewManager*> it( lst );
3874     while ( it.hasNext() )
3875     {
3876       SUIT_ViewModel* vm = it.next()->getViewModel();
3877       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3878         continue;
3879
3880       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3881       occVM->setInterocularDistance( aType, aValue );
3882     }
3883   }
3884 #endif
3885
3886 #ifndef DISABLE_OCCVIEWER
3887   if ( sec == QString( "OCCViewer" ) && param == QString( "reverse_stereo" ) )
3888   {
3889     bool reverse = resMgr->booleanValue( "OCCViewer", "reverse_stereo", false );
3890     QList<SUIT_ViewManager*> lst;
3891     viewManagers( OCCViewer_Viewer::Type(), lst );
3892     QListIterator<SUIT_ViewManager*> it( lst );
3893     while ( it.hasNext() )
3894     {
3895       SUIT_ViewModel* vm = it.next()->getViewModel();
3896       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3897         continue;
3898
3899       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3900       occVM->setReverseStereo( reverse );
3901     }
3902   }
3903 #endif
3904
3905 #ifndef DISABLE_OCCVIEWER
3906   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_vsync" ) )
3907   {
3908     bool enable = resMgr->booleanValue( "OCCViewer", "enable_vsync", true );
3909     QList<SUIT_ViewManager*> lst;
3910     viewManagers( OCCViewer_Viewer::Type(), lst );
3911     QListIterator<SUIT_ViewManager*> it( lst );
3912     while ( it.hasNext() )
3913     {
3914       SUIT_ViewModel* vm = it.next()->getViewModel();
3915       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3916         continue;
3917
3918       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3919       occVM->setVSync( enable );
3920     }
3921   }
3922 #endif
3923
3924 #ifndef DISABLE_OCCVIEWER
3925   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_quad_buffer_support" ) )
3926   {
3927     bool enable = resMgr->booleanValue( "OCCViewer", "enable_quad_buffer_support", false );
3928     QList<SUIT_ViewManager*> lst;
3929     viewManagers( OCCViewer_Viewer::Type(), lst );
3930     QListIterator<SUIT_ViewManager*> it( lst );
3931     while ( it.hasNext() )
3932     {
3933       SUIT_ViewModel* vm = it.next()->getViewModel();
3934       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3935         continue;
3936
3937       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3938       occVM->setQuadBufferSupport( enable );
3939     }
3940   }
3941 #endif
3942
3943 #ifndef DISABLE_OCCVIEWER
3944   if ( sec == QString( "OCCViewer" ) && param.contains( "viewcube" ) )
3945   {
3946     QList<SUIT_ViewManager*> lst;
3947     viewManagers( OCCViewer_Viewer::Type(), lst );
3948     QListIterator<SUIT_ViewManager*> it( lst );
3949     while ( it.hasNext() )
3950     {
3951       SUIT_ViewModel* vm = it.next()->getViewModel();
3952       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3953         continue;
3954
3955       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3956       occVM->setViewCubeParamsFromPreferences();
3957     }
3958   }
3959 #endif
3960
3961   if ( sec == QString( "3DViewer" ) && param == QString( "zooming_mode" ) )
3962   {
3963     int mode = resMgr->integerValue( "3DViewer", "zooming_mode", 0 );
3964     QList<SUIT_ViewManager*> lst;
3965 #ifndef DISABLE_OCCVIEWER
3966     viewManagers( OCCViewer_Viewer::Type(), lst );
3967     QListIterator<SUIT_ViewManager*> itOCC( lst );
3968     while ( itOCC.hasNext() )
3969     {
3970       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3971       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3972         continue;
3973
3974       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3975       occVM->setZoomingStyle( mode );
3976     }
3977 #endif
3978 #ifndef DISABLE_VTKVIEWER
3979 #ifndef DISABLE_SALOMEOBJECT
3980     viewManagers( SVTK_Viewer::Type(), lst );
3981     QListIterator<SUIT_ViewManager*> itVTK( lst );
3982     while ( itVTK.hasNext() )
3983     {
3984       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3985       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3986         continue;
3987
3988       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3989       if( vtkVM ) vtkVM->setZoomingStyle( mode );
3990     }
3991 #endif
3992 #endif
3993   }
3994
3995 #ifndef DISABLE_VTKVIEWER
3996   if ( sec == QString( "VTKViewer" ) && (param == QString( "speed_value" ) || param == QString( "speed_mode" )) )
3997   {
3998     int speed = resMgr->integerValue( "VTKViewer", "speed_value", 10 );
3999     int mode = resMgr->integerValue( "VTKViewer", "speed_mode", 0 );
4000     QList<SUIT_ViewManager*> lst;
4001 #ifndef DISABLE_SALOMEOBJECT
4002     viewManagers( SVTK_Viewer::Type(), lst );
4003     QListIterator<SUIT_ViewManager*> it( lst );
4004     while ( it.hasNext() )
4005     {
4006       SUIT_ViewModel* vm = it.next()->getViewModel();
4007       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4008         continue;
4009
4010       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4011       if( vtkVM ) vtkVM->setIncrementalSpeed( speed, mode );
4012     }
4013 #endif
4014   }
4015 #endif
4016
4017 #ifndef DISABLE_VTKVIEWER
4018   if ( sec == QString( "VTKViewer" ) && param == QString( "projection_mode" ) )
4019   {
4020     int mode = resMgr->integerValue( "VTKViewer", "projection_mode", 0 );
4021     QList<SUIT_ViewManager*> lst;
4022 #ifndef DISABLE_SALOMEOBJECT
4023     viewManagers( SVTK_Viewer::Type(), lst );
4024     QListIterator<SUIT_ViewManager*> it( lst );
4025     while ( it.hasNext() )
4026     {
4027       SUIT_ViewModel* vm = it.next()->getViewModel();
4028       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4029         continue;
4030
4031       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4032       if( vtkVM ) vtkVM->setProjectionMode( mode );
4033     }
4034 #endif
4035   }
4036 #endif
4037
4038 #ifndef DISABLE_VTKVIEWER
4039   if ( sec == QString( "VTKViewer" ) && param == QString( "stereo_type" ) )
4040   {
4041     int mode = resMgr->integerValue( "VTKViewer", "stereo_type", 0 );
4042     QList<SUIT_ViewManager*> lst;
4043 #ifndef DISABLE_SALOMEOBJECT
4044     viewManagers( SVTK_Viewer::Type(), lst );
4045     QListIterator<SUIT_ViewManager*> it( lst );
4046     while ( it.hasNext() )
4047     {
4048       SUIT_ViewModel* vm = it.next()->getViewModel();
4049       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4050         continue;
4051
4052       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4053       if( vtkVM ) vtkVM->setStereoType( mode );
4054     }
4055 #endif
4056   }
4057 #endif
4058
4059 #ifndef DISABLE_VTKVIEWER
4060   if ( sec == QString( "VTKViewer" ) && param == QString( "anaglyph_filter" ) )
4061   {
4062     int mode = resMgr->integerValue( "VTKViewer", "anaglyph_filter", 0 );
4063     QList<SUIT_ViewManager*> lst;
4064 #ifndef DISABLE_SALOMEOBJECT
4065     viewManagers( SVTK_Viewer::Type(), lst );
4066     QListIterator<SUIT_ViewManager*> it( lst );
4067     while ( it.hasNext() )
4068     {
4069       SUIT_ViewModel* vm = it.next()->getViewModel();
4070       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4071         continue;
4072
4073       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4074       if( vtkVM ) vtkVM->setAnaglyphFilter( mode );
4075     }
4076 #endif
4077   }
4078 #endif
4079
4080 #ifndef DISABLE_VTKVIEWER
4081   if ( sec == QString( "VTKViewer" ) && param == QString( "enable_quad_buffer_support" ) )
4082   {
4083     int enable = resMgr->booleanValue( "VTKViewer", "enable_quad_buffer_support", false );
4084     QList<SUIT_ViewManager*> lst;
4085 #ifndef DISABLE_SALOMEOBJECT
4086     viewManagers( SVTK_Viewer::Type(), lst );
4087     QListIterator<SUIT_ViewManager*> it( lst );
4088     while ( it.hasNext() )
4089     {
4090       SUIT_ViewModel* vm = it.next()->getViewModel();
4091       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4092         continue;
4093
4094       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4095       if( vtkVM ) vtkVM->setQuadBufferSupport( enable );
4096     }
4097 #endif
4098   }
4099 #endif
4100
4101 #ifndef DISABLE_VTKVIEWER
4102   if ( sec == QString( "VTKViewer" ) && param == QString( "preselection" ) )
4103   {
4104     int mode = resMgr->integerValue( "VTKViewer", "preselection", 0 );
4105     QList<SUIT_ViewManager*> lst;
4106 #ifndef DISABLE_SALOMEOBJECT
4107     viewManagers( SVTK_Viewer::Type(), lst );
4108     QListIterator<SUIT_ViewManager*> it( lst );
4109     while ( it.hasNext() )
4110     {
4111       SUIT_ViewModel* vm = it.next()->getViewModel();
4112       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4113         continue;
4114
4115       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4116       if( vtkVM ) vtkVM->setPreSelectionMode( mode );
4117     }
4118 #endif
4119   }
4120 #endif
4121
4122 #ifndef DISABLE_VTKVIEWER
4123   if ( sec == QString( "VTKViewer" ) && param == QString( "enable_selection" ) )
4124   {
4125     bool isToEnableSelection = resMgr->booleanValue( "VTKViewer", "enable_selection", true );
4126     QList<SUIT_ViewManager*> lst;
4127 #ifndef DISABLE_SALOMEOBJECT
4128     viewManagers( SVTK_Viewer::Type(), lst );
4129     QListIterator<SUIT_ViewManager*> it( lst );
4130     while ( it.hasNext() )
4131     {
4132       SUIT_ViewModel* vm = it.next()->getViewModel();
4133       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4134         continue;
4135
4136       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4137       if( vtkVM ) vtkVM->enableSelection( isToEnableSelection );
4138     }
4139 #endif
4140   }
4141 #endif
4142
4143 #ifndef DISABLE_VTKVIEWER
4144   if ( sec == QString( "VTKViewer" ) && (param == QString( "spacemouse_func1_btn" ) ||
4145                                          param == QString( "spacemouse_func2_btn" ) ||
4146                                          param == QString( "spacemouse_func5_btn" ) ) )
4147   {
4148     int btn1 = resMgr->integerValue( "VTKViewer", "spacemouse_func1_btn", 1 );
4149     int btn2 = resMgr->integerValue( "VTKViewer", "spacemouse_func2_btn", 2 );
4150     int btn3 = resMgr->integerValue( "VTKViewer", "spacemouse_func5_btn", 9 );
4151     QList<SUIT_ViewManager*> lst;
4152 #ifndef DISABLE_SALOMEOBJECT
4153     viewManagers( SVTK_Viewer::Type(), lst );
4154     QListIterator<SUIT_ViewManager*> it( lst );
4155     while ( it.hasNext() )
4156     {
4157       SUIT_ViewModel* vm = it.next()->getViewModel();
4158       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4159         continue;
4160
4161       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4162       if( vtkVM ) vtkVM->setSpacemouseButtons( btn1, btn2, btn3 );
4163     }
4164 #endif
4165   }
4166 #endif
4167   if( sec=="ObjectBrowser" )
4168   {
4169     SUIT_DataBrowser* ob = objectBrowser();
4170     if ( !ob )
4171       return;
4172
4173     if ( param=="auto_size_first" )
4174     {
4175       bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
4176       ob->setAutoSizeFirstColumn( autoSizeFirst );
4177       if ( autoSizeFirst )
4178         ob->adjustFirstColumnWidth();
4179     }
4180     else if ( param=="auto_size" ) {
4181       bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
4182       ob->setAutoSizeColumns(autoSize);
4183       if ( autoSize )
4184         ob->adjustColumnsWidth();
4185     }
4186     else if ( param=="resize_on_expand_item" ) {
4187       bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", false );
4188       ob->setResizeOnExpandItem(resizeOnExpandItem);
4189     }
4190     else if ( param == "auto_hide_search_tool" ) {
4191       ob->searchTool()->enableAutoHide( resMgr->booleanValue( "ObjectBrowser", "auto_hide_search_tool" ) );
4192     }
4193   }
4194
4195   if( sec=="Study" )
4196   {
4197     if( param=="auto_save_interval" ) {
4198       myAutoSaveTimer->stop();
4199       int autoSaveInterval = resMgr->integerValue( "Study", "auto_save_interval", 0 );
4200       if ( activeStudy() && autoSaveInterval > 0 ) myAutoSaveTimer->start( autoSaveInterval*60000 );
4201     }
4202   }
4203
4204 #ifndef DISABLE_PYCONSOLE
4205   if( sec=="PyConsole" && pythonConsole() )
4206   {
4207     if ( param=="font" ) {
4208       pythonConsole()->setFont( resMgr->fontValue( "PyConsole", "font" ) );
4209     }
4210     else if ( param=="show_banner" ) {
4211       pythonConsole()->setIsShowBanner( resMgr->booleanValue( "PyConsole", "show_banner", true ) );
4212     }
4213     else if ( param=="auto_completion" ) {
4214       pythonConsole()->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
4215     }
4216   }
4217 #endif
4218
4219   if( sec=="MRU" )
4220   {
4221     QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4222     if ( mru ) {
4223       if ( param == "visible_count" )
4224         mru->setVisibleCount( resMgr->integerValue( "MRU", "visible_count", 5 ) );    // 5 MRU items by default
4225       else if ( param == "max_count" )
4226         mru->setHistoryCount( resMgr->integerValue( "MRU", "max_count", -1 ) );       // unlimited history by default
4227       else if ( param == "insert_mode" )
4228         mru->setInsertMode( resMgr->integerValue( "MRU", "insert_mode", 0 ) );        // QtxMRUAction::MoveFirst by default
4229       else if ( param == "link_type" )
4230         mru->setLinkType( resMgr->integerValue( "MRU", "link_type", 0 ) );            // QtxMRUAction::LinkAuto by default
4231       else if ( param == "show_clear" )
4232         mru->setClearPossible( resMgr->booleanValue( "MRU", "show_clear", false ) );  // do not show "Clear" item by default
4233       else if ( param == "show_mru" )
4234         mru->setVisible( resMgr->booleanValue( "MRU", "show_mru", false ) );          // do not show MRU menu item by default
4235     }
4236   }
4237   if ( sec == "language" && param == "language" )
4238   {
4239     // VSR 18.06.2015 : commented out : single warning dialog box is now shown by the LightApp_PreferencesDlg
4240     //SUIT_MessageBox::information( desktop(), tr( "WRN_WARNING" ), tr( "LANG_CHANGED" ) );
4241   }
4242   if ( sec == "language" && param == "locale")
4243   {
4244     // VSR 18.06.2015: commented out : single warning dialog box is now shown by the LightApp_PreferencesDlg
4245     //SUIT_MessageBox::information( desktop(), tr( "WRN_WARNING" ), tr( "LOCALE_CHANGED" ) );
4246   }
4247   if ( sec == "desktop" && param == "opaque_resize" ) {
4248     bool opaqueResize = resMgr->booleanValue( "desktop", "opaque_resize", false );
4249     // RNV: This code has been commented, because clearing of the QMainWindow::AnimatedDocks option
4250     //      leads to strange behaviour of the dockable windows (at least at qt-5.6.1):
4251     //      any dockable window can't be docked to the another area, except initial area.
4252     //      It is possible to move window to another area, but it always returns to the initial area.
4253     //
4254     //    QMainWindow::DockOptions dopts = desktop()->dockOptions();
4255     //    if ( opaqueResize ) dopts |= QMainWindow::AnimatedDocks;
4256     //     else                dopts &= ~QMainWindow::AnimatedDocks;
4257     //    desktop()->setDockOptions( dopts );
4258     desktop()->setOpaqueResize( opaqueResize );
4259     if ( dynamic_cast<STD_TabDesktop*>( desktop() ) )
4260       dynamic_cast<STD_TabDesktop*>( desktop() )->workstack()->setOpaqueResize( opaqueResize );
4261   }
4262
4263 #ifndef DISABLE_PLOT2DVIEWER
4264   QList<SUIT_ViewManager*> lst;
4265   viewManagers( Plot2d_Viewer::Type(), lst );
4266   QListIterator<SUIT_ViewManager*> itPlot2d( lst );
4267   while ( itPlot2d.hasNext() ) {
4268     SUIT_ViewManager* viewMgr = itPlot2d.next();
4269     SUIT_ViewModel* vm = viewMgr->getViewModel();
4270     if ( !vm || !vm->inherits( "Plot2d_Viewer" ) )
4271       continue;
4272
4273     //Plot2d_Viewer* Plot2dVM = dynamic_cast<Plot2d_Viewer*>( vm );
4274
4275     viewMgr->setViewModel( vm  );
4276     Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( viewMgr->getActiveView() );
4277     if( wnd ) {
4278       Plot2d_ViewFrame* frame = wnd->getViewFrame();
4279       frame->SetPreference();
4280     }
4281   }
4282 #endif
4283 }
4284
4285 /*!
4286   Loads preferences
4287 */
4288 void LightApp_Application::loadPreferences()
4289 {
4290   CAM_Application::loadPreferences();
4291
4292   SUIT_ResourceMgr* aResMgr = resourceMgr();
4293
4294   if ( !aResMgr )
4295     return;
4296
4297   static bool mru_load = true;
4298   if ( mru_load )
4299   {
4300     QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4301     if ( mru ) {
4302       mru->setVisible( aResMgr->booleanValue( "MRU", "show_mru", false ) );         // do not show MRU menu item by default
4303       mru->setVisibleCount( aResMgr->integerValue( "MRU", "visible_count", 5 ) );   // 5 MRU items by default
4304       mru->setHistoryCount( aResMgr->integerValue( "MRU", "max_count", -1 ) );      // unlimited history by default
4305       mru->setInsertMode( aResMgr->integerValue( "MRU", "insert_mode", 0 ) );       // QtxMRUAction::MoveFirst by default
4306       mru->setLinkType( aResMgr->integerValue( "MRU", "link_type", 0 ) );           // QtxMRUAction::LinkAuto by default
4307       mru->setClearPossible( aResMgr->booleanValue( "MRU", "show_clear", false ) ); // do not show "Clear" item by default
4308       mru->loadLinks( aResMgr, "MRU" );
4309     }
4310     mru_load = false;
4311   }
4312
4313   myWinVis.clear();
4314   QStringList mods = aResMgr->parameters( "windows_visibility" );
4315   for ( QStringList::const_iterator itr = mods.begin(); itr != mods.end(); ++itr )
4316   {
4317     QByteArray arr;
4318     if ( aResMgr->value( "windows_visibility", *itr, arr ) )
4319       myWinVis.insert( *itr, arr );
4320   }
4321
4322   if ( desktop() ) {
4323     desktop()->retrieveGeometry( aResMgr->stringValue( "desktop", "geometry" ) );
4324     bool opaqueResize = aResMgr->booleanValue( "desktop", "opaque_resize", false );
4325     //    QMainWindow::DockOptions dopts = desktop()->dockOptions();
4326     //    if ( opaqueResize ) dopts |= QMainWindow::AnimatedDocks;
4327     //    else                dopts &= ~QMainWindow::AnimatedDocks;
4328     //    desktop()->setDockOptions( dopts );
4329     desktop()->setOpaqueResize( opaqueResize );
4330     if ( dynamic_cast<STD_TabDesktop*>( desktop() ) )
4331       dynamic_cast<STD_TabDesktop*>( desktop() )->workstack()->setOpaqueResize( opaqueResize );
4332   }
4333 }
4334
4335 /*!
4336   Saves preferences
4337 */
4338 void LightApp_Application::savePreferences()
4339 {
4340   CAM_Application::savePreferences();
4341
4342   saveDockWindowsState();
4343
4344   SUIT_ResourceMgr* aResMgr = resourceMgr();
4345
4346   if ( !aResMgr )
4347     return;
4348
4349   QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4350   if ( mru )
4351     mru->saveLinks( aResMgr, "MRU" );
4352
4353   for ( WinVis::const_iterator itr = myWinVis.begin(); itr != myWinVis.end(); ++itr )
4354     aResMgr->setValue( "windows_visibility", itr.key(), itr.value() );
4355
4356   if ( desktop() )
4357     aResMgr->setValue( "desktop", "geometry", desktop()->storeGeometry() );
4358
4359 #if GUI_DEVELOPMENT > 0
4360   aResMgr->setValue( "salome", "version", QString(GUI_VERSION_STR)+"dev" );
4361 #else
4362   aResMgr->setValue( "salome", "version", QString(GUI_VERSION_STR) );
4363 #endif
4364
4365   aResMgr->save();
4366 }
4367
4368 /*!
4369   Updates desktop title
4370 */
4371 void LightApp_Application::updateDesktopTitle()
4372 {
4373   QString aTitle = applicationName();
4374   QString aVer = applicationVersion();
4375   if ( !aVer.isEmpty() )
4376     aTitle += QString( " " ) + aVer;
4377
4378   if ( activeStudy() ) {
4379     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
4380     aTitle += QString( " - [%1]" ).arg( sName );
4381   }
4382
4383   desktop()->setWindowTitle( aTitle );
4384 }
4385
4386 /*!
4387   \brief Get map of the operations which can be performed
4388   on the module activation.
4389
4390   The method should return the map of the kind \c {<id>:<name>}
4391   where \c <id> is an integer identifier of the operation and
4392   \c <name> is a title for the button to be added to the
4393   dialog box. After user selects the required operation by the
4394   clicking the corresponding button in the dialog box, its identifier
4395   is passed to the moduleActionSelected() method to process
4396   the made choice.
4397
4398   \return map of the operations
4399   \sa moduleActionSelected()
4400 */
4401 QMap<int, QString> LightApp_Application::activateModuleActions() const
4402 {
4403   QMap<int, QString> opmap;
4404   opmap.insert( NewStudyId,  tr( "ACTIVATE_MODULE_OP_NEW" ) );
4405   opmap.insert( OpenStudyId, tr( "ACTIVATE_MODULE_OP_OPEN" ) );
4406   return opmap;
4407 }
4408
4409 /*!
4410   \brief Called when the used selectes required operation chosen
4411   from "Activate module" dialog box.
4412
4413   Performs the required operation according to the user choice.
4414
4415   \param id operation identifier
4416   \sa activateModuleActions()
4417 */
4418 void LightApp_Application::moduleActionSelected( const int id )
4419 {
4420   switch ( id ) {
4421   case NewStudyId:
4422     onNewDoc();
4423     break;
4424   case OpenStudyId:
4425     onOpenDoc();
4426     break;
4427   default:
4428     break;
4429   }
4430 }
4431
4432 /*!
4433   Updates windows after close document
4434 */
4435 void LightApp_Application::afterCloseDoc()
4436 {
4437   updateWindows();
4438
4439   CAM_Application::afterCloseDoc();
4440 }
4441
4442 /*!
4443   Updates actions of active module
4444 */
4445 void LightApp_Application::updateModuleActions()
4446 {
4447   emit moduleActivated( activeModule() ? activeModule()->moduleName() : QString() );
4448 }
4449
4450 bool LightApp_Application::checkModule( const QString& title )
4451 {
4452   if ( title.isEmpty() )
4453     return false;
4454
4455   QString library = moduleLibrary( title, true );
4456   if ( library.isEmpty() )
4457     return false;
4458
4459   QString name = moduleName( title );
4460
4461   bool isPyModule = library.contains( "SalomePyQtGUI" ) || library.contains( "SalomePyQtGUILight" );
4462
4463   QStringList paths;
4464 #if defined(WIN32)
4465   paths = QString( Qtx::getenv( "PATH" ) ).split( ";", QString::SkipEmptyParts );
4466 #elif defined(__APPLE__)
4467   paths = QString( Qtx::getenv( "DYLD_LIBRARY_PATH" ) ).split( ":", QString::SkipEmptyParts );
4468 #else
4469   paths = QString( Qtx::getenv( "LD_LIBRARY_PATH" ) ).split( ":", QString::SkipEmptyParts );
4470 #endif
4471
4472   bool isFound = false;
4473   QStringList::const_iterator it;
4474   for ( it = paths.begin(); it != paths.end() && !isFound; ++it )
4475   {
4476     isFound = QFileInfo( Qtx::addSlash( *it ) + library ).exists();
4477   }
4478
4479   if ( !isFound )
4480   {
4481     INFOS( std::endl <<
4482            "****************************************************************" << std::endl <<
4483            "     Warning: library " << qPrintable( library ) << " is not found!" << std::endl <<
4484            "     Module " << qPrintable( title ) << " will not be available in GUI mode!" << std::endl <<
4485            "****************************************************************" << std::endl);
4486     return false;
4487   }
4488
4489   if ( isPyModule )
4490   {
4491     QString pyModule = QString( "%1GUI.py" ).arg( name );
4492 #if defined(WIN32)
4493     paths = QString( Qtx::getenv( "PYTHONPATH" ) ).split( ";", QString::SkipEmptyParts );
4494 #else
4495     paths = QString( Qtx::getenv( "PYTHONPATH" ) ).split( ":", QString::SkipEmptyParts );
4496 #endif
4497     isFound = false;
4498     for ( it = paths.begin(); it != paths.end() && !isFound; ++it )
4499     {
4500       isFound = QFileInfo( Qtx::addSlash( *it ) + pyModule ).exists();
4501     }
4502
4503     if ( !isFound )
4504     {
4505       INFOS( std::endl <<
4506              "****************************************************************" << std::endl <<
4507              "     Warning: Python module " << qPrintable( pyModule ) << " is not found!" << std::endl <<
4508              "     Module " << qPrintable( title ) << " will not be available in GUI mode!" << std::endl <<
4509              "****************************************************************" << std::endl);
4510       return false;
4511     }
4512   }
4513
4514   return true;
4515 }
4516
4517 /*!
4518   Gets current windows.
4519   \param winMap - output current windows map.
4520 */
4521 void LightApp_Application::currentWindows( QMap<int, int>& winMap ) const
4522 {
4523   winMap.clear();
4524   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
4525     ((LightApp_Module*)activeModule())->windows( winMap );
4526   else
4527     defaultWindows( winMap );
4528 }
4529
4530 /*!
4531   Gets current view managers.
4532   \param lst - output current view managers list.
4533 */
4534 void LightApp_Application::currentViewManagers( QStringList& lst ) const
4535 {
4536   lst.clear();
4537   if ( !activeStudy() )
4538     return;
4539
4540   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
4541     ((LightApp_Module*)activeModule())->viewManagers( lst );
4542   else
4543     defaultViewManagers( lst );
4544 }
4545
4546 /*!
4547   Updates windows
4548 */
4549 void LightApp_Application::updateWindows()
4550 {
4551   QMap<int, int> winMap;
4552   currentWindows( winMap );
4553
4554   for ( QMap<int, int>::ConstIterator it = winMap.begin(); it != winMap.end(); ++it )
4555   {
4556     if ( !dockWindow( it.key() ) )
4557       getWindow( it.key() );
4558   }
4559
4560   for ( WinMap::ConstIterator it = myWin.begin(); it != myWin.end(); ++it )
4561   {
4562     QWidget* wid = it.value();
4563     if ( !wid )
4564       continue;
4565     if ( winMap.contains( it.key() ) )
4566       wid->setVisible( true );
4567     else if ( !activeStudy() )
4568       delete wid;
4569     else
4570       wid->setVisible( false );
4571   }
4572
4573   loadDockWindowsState();
4574
4575   if ( !activeModule() && infoPanel() )
4576   {
4577     infoPanel()->clear();
4578     infoPanel()->setTitle( tr( "INFO_WELCOME_TO_SALOME" ) );
4579
4580     int grp = infoPanel()->addGroup( tr( "INFO_GETTING_STARTED" ) );
4581     infoPanel()->addAction( action( FileNewId ), grp );
4582     infoPanel()->addLabel( action( FileNewId )->statusTip(), grp );
4583     infoPanel()->addAction( action( FileOpenId ), grp );
4584     infoPanel()->addLabel( action( FileOpenId )->statusTip(), grp );
4585     if ( HAS_TUTORIAL_URL ) {
4586       infoPanel()->addAction( action( TutorialsId ), grp );
4587       infoPanel()->addLabel( action( TutorialsId )->statusTip(), grp );
4588     }
4589     infoPanel()->addAction( action( VideosId ), grp );
4590     infoPanel()->addLabel( action( VideosId )->statusTip(), grp );
4591
4592     LightApp_ModuleAction* ma = qobject_cast<LightApp_ModuleAction*>(action(ModulesListId));
4593     if ( ma && ma->count() > 0 )
4594     {
4595       grp = infoPanel()->addGroup( tr( "INFO_AVAILABLE_MODULES" ) );
4596       foreach ( QString mname, ma->modules() )
4597       {
4598         infoPanel()->addAction( ma->moduleAction( mname ), grp );
4599         if ( !moduleDescription( mname ).isEmpty() )
4600           infoPanel()->addLabel( moduleDescription( mname ), grp );
4601       }
4602     }
4603   }
4604 }
4605
4606 /*!
4607   Updates view managers
4608 */
4609 void LightApp_Application::updateViewManagers()
4610 {
4611   QStringList lst;
4612   currentViewManagers( lst );
4613
4614   for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it )
4615     getViewManager( *it, true );
4616 }
4617
4618 /*!
4619   Loads windows geometry
4620 */
4621 void LightApp_Application::loadDockWindowsState()
4622 {
4623   if ( !desktop() )
4624     return;
4625   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
4626   bool storeWin = aResMgr->booleanValue( "Study", "store_positions", true );
4627   bool storeTb = aResMgr->booleanValue( "Study", "store_tool_positions", true );
4628
4629   QString modName;
4630   if ( activeModule() )
4631     modName = activeModule()->name();
4632   else if ( activeStudy() )
4633     modName = "nomodule";
4634
4635   QtxResourceMgr::WorkingMode prevMode = aResMgr->setWorkingMode( QtxResourceMgr::IgnoreUserValues );
4636   QByteArray aDefaultState;
4637   aResMgr->value( "windows_geometry", modName, aDefaultState );
4638   QByteArray aDefaultVisibility;
4639   aResMgr->value( "windows_visibility", modName, aDefaultVisibility );
4640   bool hasDefaultVisibility = !aDefaultVisibility.isEmpty();
4641   aResMgr->setWorkingMode( prevMode );
4642
4643   if( !storeWin && !storeTb && aDefaultState.isEmpty() && !hasDefaultVisibility)
4644     return;
4645
4646   if ( aResMgr->hasValue("windows_geometry" ,modName ) ) {
4647     long version = Qtx::versionToId( aResMgr->stringValue( "windows_geometry_version", modName, "" ) );
4648     QByteArray arr;
4649     if ( version > Qtx::versionToId( "7.4.1" ) )
4650       aResMgr->value( "windows_geometry", modName , arr );
4651     else
4652       arr = aDefaultState;
4653     QByteArray aTargetArray = processState(arr, storeWin, storeTb, true, aDefaultState);
4654     desktop()->restoreState( aTargetArray );
4655   }
4656
4657   QStringList mainToolbarsNames;
4658   mainToolbarsNames << "SalomeStandard" << "SalomeModules";
4659   QList<QToolBar*> mainToolbars = findToolBars( mainToolbarsNames );
4660   foreach( QToolBar* tb, mainToolbars ) tb->setVisible( true );
4661   /*
4662   if ( !myWinVis.contains( modName ) && aDefaultVisibility.isEmpty())
4663     return;
4664
4665   QMap<QString, bool> *tbMap = 0;
4666   QMap<QString, bool> *dwMap = 0;
4667
4668   QMap<QString, bool> userTbMap, userDwMap;
4669   dockWindowsState( myWinVis[modName], userTbMap, userDwMap );
4670
4671   QMap<QString, bool> defaultTbMap, defaultDwMap;
4672   if(hasDefaultVisibility) {
4673     dockWindowsState( aDefaultVisibility, defaultTbMap, defaultDwMap);
4674   }
4675
4676   if(storeTb) {
4677     tbMap =  &userTbMap;
4678   } else {
4679     if(hasDefaultVisibility){
4680       tbMap =  &defaultTbMap;
4681     }
4682   }
4683
4684   if(storeWin) {
4685     dwMap =  &userDwMap;
4686   } else {
4687     if(hasDefaultVisibility){
4688       dwMap =  &defaultDwMap;
4689     }
4690   }
4691
4692   if(tbMap) {
4693     QList<QToolBar*> tbList = findToolBars();
4694     for ( QList<QToolBar*>::iterator tit = tbList.begin(); tit != tbList.end(); ++tit )
4695       {
4696         QToolBar* tb = *tit;
4697         if ( tbMap->contains( tb->objectName() ) ) {
4698           tb->setVisible( (*tbMap)[tb->objectName()] );
4699         }
4700       }
4701   }
4702
4703   if(dwMap) {
4704     QList<QDockWidget*> dwList = desktop()->findChildren<QDockWidget*>();
4705     for ( QList<QDockWidget*>::iterator dit = dwList.begin(); dit != dwList.end(); ++dit )
4706       {
4707         QDockWidget* dw = *dit;
4708
4709         QObject* po = Qtx::findParent( dw, "QMainWindow" );
4710         if ( po != desktop() )
4711           continue;
4712
4713         if ( dwMap->contains( dw->objectName() ) )
4714           dw->setVisible( (*dwMap)[dw->objectName()] );
4715       }
4716   }
4717   */
4718 }
4719
4720
4721 /*!
4722   Saves windows geometry
4723 */
4724 void LightApp_Application::saveDockWindowsState()
4725 {
4726   if ( !desktop() )
4727     return;
4728
4729   bool storeWin = resourceMgr()->booleanValue( "Study", "store_positions", true );
4730   bool storeTb = resourceMgr()->booleanValue( "Study", "store_tool_positions", true );
4731
4732   if( !storeWin && !storeTb )
4733     return;
4734
4735   QString modName;
4736   if ( activeModule() )
4737     modName = activeModule()->name();
4738   else if ( activeStudy() )
4739     modName = "nomodule";
4740
4741   QString versionId = GUI_VERSION_STR;
4742 #if GUI_DEVELOPMENT > 0
4743   versionId += "dev";
4744 #endif
4745
4746   QByteArray arr = desktop()->saveState();
4747   resourceMgr()->setValue( "windows_geometry", modName, processState(arr, storeWin, storeTb, false) );
4748   resourceMgr()->setValue( "windows_geometry_version", modName, versionId );
4749
4750   QByteArray visArr;
4751   if ( myWinVis.contains( modName ) )
4752     visArr = myWinVis[modName];
4753
4754   QMap<QString, bool> tbMap, dwMap;
4755   dockWindowsState( visArr, tbMap, dwMap );
4756
4757   QList<QToolBar*> tbList = desktop()->findChildren<QToolBar*>();
4758   for ( QList<QToolBar*>::iterator it = tbList.begin(); it != tbList.end(); ++it )
4759   {
4760     QToolBar* tb = *it;
4761     tbMap.insert( tb->objectName(), tb->toggleViewAction()->isChecked() );
4762   }
4763
4764   QList<QDockWidget*> dwList = desktop()->findChildren<QDockWidget*>();
4765   for ( QList<QDockWidget*>::iterator it = dwList.begin(); it != dwList.end(); ++it )
4766   {
4767     QDockWidget* wid = *it;
4768     dwMap.insert( wid->objectName(), wid->toggleViewAction()->isChecked() );
4769   }
4770
4771   visArr = dockWindowsState( tbMap, dwMap );
4772
4773   myWinVis.insert( modName, visArr );
4774 }
4775
4776 QByteArray LightApp_Application::dockWindowsState( const QMap<QString, bool>& tb, const QMap<QString, bool>& dw ) const
4777 {
4778   QByteArray visArr;
4779   QDataStream stream( &visArr, QIODevice::WriteOnly );
4780
4781   stream << (uchar)ToolBarMarker;
4782   stream << tb.size();
4783   for ( QMap<QString, bool>::const_iterator tit = tb.begin(); tit != tb.end(); ++tit )
4784   {
4785     stream << tit.key();
4786     stream << (uchar)( tit.value() ? 1 : 0 );
4787   }
4788
4789   stream << (uchar)DockWidgetMarker;
4790   stream << dw.size();
4791   for ( QMap<QString, bool>::const_iterator wit = dw.begin(); wit != dw.end(); ++wit )
4792   {
4793     stream << wit.key();
4794     stream << (uchar)( wit.value() ? 1 : 0 );
4795   }
4796
4797   return visArr;
4798 }
4799
4800 void LightApp_Application::dockWindowsState( const QByteArray& arr, QMap<QString, bool>& tb, QMap<QString, bool>& dw ) const
4801 {
4802   tb.clear();
4803   dw.clear();
4804
4805   QByteArray visArr = arr;
4806   QDataStream stream( &visArr, QIODevice::ReadOnly );
4807
4808   uchar marker;
4809   stream >> marker;
4810   if ( marker != ToolBarMarker )
4811     return;
4812
4813   int lines;
4814   stream >> lines;
4815   for ( int i = 0; i < lines; ++i )
4816   {
4817     QString objectName;
4818     stream >> objectName;
4819     uchar shown;
4820     stream >> shown;
4821     tb.insert( objectName, shown );
4822   }
4823
4824   stream >> marker;
4825   if ( marker != DockWidgetMarker )
4826     return;
4827
4828   stream >> lines;
4829   for ( int j = 0; j < lines; ++j )
4830   {
4831     QString objectName;
4832     stream >> objectName;
4833     uchar shown;
4834     stream >> shown;
4835     dw.insert( objectName, shown );
4836   }
4837 }
4838
4839 QPixmap LightApp_Application::moduleIcon( const QString& moduleTitle, const int size ) const
4840 {
4841   QPixmap icon;
4842   if ( resourceMgr() )
4843   {
4844     QPixmap defaultIcon = resourceMgr()->loadPixmap( "LightApp", tr( "APP_MODULE_ICO" ), QPixmap( imageEmptyIcon ) );
4845     QString iconName = resourceMgr()->stringValue( moduleName( moduleTitle ), "icon", QString() );
4846     icon = resourceMgr()->loadPixmap( moduleName( moduleTitle ), iconName, defaultIcon );
4847     if ( size > 0 )
4848       icon = Qtx::scaleIcon( icon, size );
4849   }
4850   return icon;
4851 }
4852
4853 /*!
4854   Inserts items in popup, which necessary for current application
4855 */
4856 void LightApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
4857 {
4858   //Add "Rename" item
4859   LightApp_SelectionMgr* selMgr = LightApp_Application::selectionMgr();
4860   bool cacheIsOn = selMgr->isSelectionCacheEnabled();
4861   selMgr->setSelectionCacheEnabled( true );
4862
4863   SUIT_DataBrowser* ob = objectBrowser();
4864
4865   CAM_Application::contextMenuPopup( type, thePopup, title );
4866
4867   if ( ob && type == ob->popupClientType() ) {
4868     thePopup->addSeparator();
4869     QAction* a = thePopup->addAction( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
4870     if ( ob->shortcutKey(SUIT_DataBrowser::UpdateShortcut) )
4871       a->setShortcut( ob->shortcutKey(SUIT_DataBrowser::UpdateShortcut) );
4872   }
4873
4874 #ifndef DISABLE_SALOMEOBJECT
4875   if ( selMgr && ob ) {
4876     SALOME_ListIO selected;
4877     selMgr->selectedObjects( selected );
4878     if(selected.Extent() == 1){
4879       Handle(SALOME_InteractiveObject) anIObject = selected.First();
4880       SUIT_DataObject* obj = findObject(anIObject->getEntry());
4881       if(obj && obj->renameAllowed()) {
4882         QAction* a = new QAction(tr("MEN_RENAME_OBJ"), thePopup);
4883         connect( a, SIGNAL( triggered(bool) ), ob, SLOT( onStartEditing() ) );
4884         if ( ob->shortcutKey(SUIT_DataBrowser::RenameShortcut) )
4885           a->setShortcut( ob->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
4886
4887         QList<QAction*> acts = thePopup->actions();
4888         QAction* firstAction = acts.count() > 0 ? acts.first() : 0;
4889         thePopup->insertAction(firstAction,a);
4890       }
4891     }
4892   }
4893 #endif
4894
4895   selMgr->setSelectionCacheEnabled( cacheIsOn );
4896 }
4897
4898 /*!
4899   Create empty study
4900 */
4901 void LightApp_Application::createEmptyStudy()
4902 {
4903   CAM_Application::createEmptyStudy();
4904
4905   if ( objectBrowser() )
4906     objectBrowser()->updateTree();
4907
4908   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
4909   if ( aResMgr && activeStudy() ) {
4910     int autoSaveInterval = aResMgr->integerValue( "Study", "auto_save_interval", 0 );
4911     if ( autoSaveInterval > 0 ) myAutoSaveTimer->start( autoSaveInterval*60000 );
4912   }
4913 }
4914
4915 /*!Set desktop:*/
4916 void LightApp_Application::setDesktop( SUIT_Desktop* desk )
4917 {
4918   CAM_Application::setDesktop( desk );
4919
4920   if ( desk ) {
4921     connect( desk, SIGNAL( message( const QString& ) ),
4922              this, SLOT( onDesktopMessage( const QString& ) ), Qt::UniqueConnection );
4923     connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
4924              this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
4925     /* connect( desk, SIGNAL( windowMoved( SUIT_ViewWindow* ) ),
4926              this, SLOT( onWindowMoved( SUIT_ViewWindow* ) ), Qt::UniqueConnection ); */
4927   }
4928 }
4929
4930 /*!
4931   Activates module
4932   \param mod - module to be activated
4933 */
4934 bool LightApp_Application::activateModule( CAM_Module* mod )
4935 {
4936   bool res = CAM_Application::activateModule( mod );
4937
4938   if ( objectBrowser() )
4939     objectBrowser()->updateTree();
4940
4941   return res;
4942 }
4943
4944 /*!
4945   \return keyborad accelerators manager object
4946 */
4947 SUIT_Accel* LightApp_Application::accel() const
4948 {
4949   return myAccel;
4950 }
4951
4952 /*!
4953   Removes dead widget container from map
4954 */
4955 void LightApp_Application::onWCDestroyed( QObject* ob )
4956 {
4957   // remove destroyed widget container from windows map
4958   for ( WinMap::ConstIterator itr = myWin.begin(); itr != myWin.end(); ++itr )
4959   {
4960     if ( itr.value() != ob )
4961       continue;
4962
4963     int key = itr.key();
4964     myWin.remove( key );
4965     break;
4966   }
4967 }
4968
4969 void LightApp_Application::onMRUActivated( const QString& name )
4970 {
4971   SUIT_Session* s = SUIT_Session::session();
4972   if ( s && s->activeApplication() == this )
4973     onOpenDoc( name );
4974 }
4975
4976 void LightApp_Application::onStylePreferences()
4977 {
4978 #ifdef USE_SALOME_STYLE
4979   Style_PrefDlg dlg( desktop() );
4980   dlg.exec();
4981
4982   resourceMgr()->setValue( "Style", "use_salome_style", Style_Salome::isActive() );
4983 #endif // USE_SALOME_STYLE
4984 }
4985
4986 void LightApp_Application::onFullScreen(){
4987   if(myScreenHelper) {
4988     if(desktop()->isFullScreen())
4989       myScreenHelper->switchToNormalScreen();
4990     else
4991       myScreenHelper->switchToFullScreen();
4992   }
4993 }
4994
4995 /*!
4996   Connects just added view manager
4997 */
4998 void LightApp_Application::addViewManager( SUIT_ViewManager* vm )
4999 {
5000   connect( vm, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
5001            this, SLOT( onCloseView( SUIT_ViewManager* ) ) );
5002   CAM_Application::addViewManager( vm );
5003 }
5004
5005 /*!
5006   Remove view manager from memory
5007 */
5008 void LightApp_Application::removeViewManager( SUIT_ViewManager* vm )
5009 {
5010   disconnect( vm, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
5011            this, SLOT( onCloseView( SUIT_ViewManager* ) ) );
5012   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5013   if (aStudy )
5014     aStudy->removeObjectProperties( vm->getGlobalId() );
5015
5016   CAM_Application::removeViewManager( vm );
5017
5018   LightApp_SelectionMgr* selMgr = selectionMgr();
5019   QList<SUIT_Selector*> selectors;
5020   selMgr->selectors( selectors );
5021   foreach( SUIT_Selector* selector, selectors ) {
5022     if ( selector->owner() == vm->getViewModel() ) {
5023       delete selector;
5024     }
5025   }
5026
5027   // IPAL22894: Crash on closing OCC view
5028   //delete vm;
5029   vm->deleteLater();
5030 }
5031
5032 /*!
5033   Renames active window of desktop
5034 */
5035 void LightApp_Application::onRenameWindow()
5036 {
5037   if( !desktop() )
5038     return;
5039
5040   QWidget* w = desktop()->activeWindow();
5041   if( !w )
5042     return;
5043
5044   bool ok;
5045   QString name = QInputDialog::getText( w, tr( "TOT_RENAME" ), tr( "PRP_RENAME" ), QLineEdit::Normal, w->windowTitle(), &ok );
5046   if( ok && !name.isEmpty() )
5047     w->setWindowTitle( name );
5048 }
5049
5050 /*!
5051   Closes active window of desktop
5052 */
5053 void LightApp_Application::onCloseWindow()
5054 {
5055   if( !desktop() )
5056     return;
5057
5058   QWidget* w = desktop()->activeWindow();
5059   if( !w )
5060     return;
5061
5062   w->close();
5063 }
5064
5065 /*!
5066   Closes all windows of desktop
5067 */
5068 void LightApp_Application::onCloseAllWindow()
5069 {
5070   STD_TabDesktop* desk = dynamic_cast<STD_TabDesktop*>( desktop() );
5071   if( !desk )
5072     return;
5073
5074   QList<SUIT_ViewWindow*> wndList = desk->windows();
5075   SUIT_ViewWindow* wnd;
5076   foreach( wnd, wndList )
5077   {
5078     if ( wnd )
5079       wnd->close();
5080   }
5081 }
5082
5083 /*!
5084   Groups all windows of desktop
5085 */
5086 void LightApp_Application::onGroupAllWindow()
5087 {
5088   STD_TabDesktop* desk = dynamic_cast<STD_TabDesktop*>( desktop() );
5089   if( !desk )
5090     return;
5091
5092   QtxWorkstack* wgStack = desk->workstack();
5093   if ( wgStack )
5094     wgStack->stack();
5095 }
5096
5097 /*!
5098   \return default name for an active study
5099 */
5100 void LightApp_Application::setDefaultStudyName( const QString& theName )
5101 {
5102   QStringList anInfoList;
5103   modules( anInfoList, false );
5104
5105   LightApp_Study* aStudy = (LightApp_Study*)activeStudy();
5106   if( anInfoList.count() == 1 && // to avoid a conflict between different modules
5107       !aStudy->isSaved() )
5108   {
5109     aStudy->setStudyName( theName );
5110     updateDesktopTitle();
5111   }
5112 }
5113
5114 /*!
5115   Custom event handler
5116 */
5117 bool LightApp_Application::event( QEvent* e )
5118 {
5119   if( e && e->type()==2000 )
5120   {
5121     SALOME_CustomEvent* ce = ( SALOME_CustomEvent* )e;
5122     QString* d = ( QString* )ce->data();
5123     if( SUIT_MessageBox::question(0, tr("WRN_WARNING"),
5124                                   d ? *d : "",
5125                                   SUIT_MessageBox::Yes | SUIT_MessageBox::No,
5126                                   SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes )
5127     {
5128       QStringList path;
5129       path << tr( "PREF_CATEGORY_SALOME" ) << tr( "PREF_TAB_GENERAL" )
5130            << tr( "PREF_GROUP_EXT_BROWSER" ) << tr( "PREF_APP" );
5131       showPreferences( path );
5132     }
5133     if( d )
5134       delete d;
5135     return true;
5136   }
5137   return CAM_Application::event( e );
5138 }
5139
5140 /*! Check data object */
5141 bool LightApp_Application::checkDataObject(LightApp_DataObject* theObj)
5142 {
5143   if (theObj)
5144     {
5145       bool isSuitable = !theObj->entry().isEmpty() &&
5146                         !theObj->componentDataType().isEmpty() &&
5147                         !theObj->name().isEmpty();
5148       return isSuitable;
5149     }
5150
5151   return false;
5152 }
5153
5154 int LightApp_Application::openChoice( const QString& aName )
5155 {
5156   int choice = CAM_Application::openChoice( aName );
5157
5158   if ( choice == OpenExist ) // The document is already open.
5159   {
5160     // Do you want to reload it?
5161     if ( SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYOPEN" ).arg( aName ),
5162                                     SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No ) == SUIT_MessageBox::Yes )
5163       choice = OpenReload;
5164   }
5165
5166   return choice;
5167 }
5168
5169 bool LightApp_Application::openAction( const int choice, const QString& aName )
5170 {
5171   bool res = false;
5172   switch ( choice )
5173   {
5174   case OpenReload:
5175     {
5176       STD_Application* app = 0;
5177       SUIT_Session* session = SUIT_Session::session();
5178       QList<SUIT_Application*> appList = session->applications();
5179       for ( QList<SUIT_Application*>::iterator it = appList.begin(); it != appList.end() && !app; ++it )
5180       {
5181         if ( (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName )
5182           app = ::qobject_cast<STD_Application*>( *it );
5183       }
5184
5185       if ( app )
5186       {
5187         app->onCloseDoc( false );
5188         appList = session->applications();
5189         STD_Application* other = 0;
5190         for ( QList<SUIT_Application*>::iterator it = appList.begin(); it != appList.end() && !other; ++it )
5191           other = ::qobject_cast<STD_Application*>( *it );
5192
5193         if ( other )
5194           res = other->onOpenDoc( aName );
5195       }
5196     }
5197     break;
5198   default:
5199     res = CAM_Application::openAction( choice, aName );
5200     break;
5201   }
5202
5203   return res;
5204 }
5205
5206 QStringList LightApp_Application::viewManagersTypes() const
5207 {
5208   QStringList aTypesList;
5209   aTypesList += myUserWmTypes;
5210 #ifndef DISABLE_GLVIEWER
5211   aTypesList<<GLViewer_Viewer::Type();
5212 #endif
5213 #ifndef DISABLE_PLOT2DVIEWER
5214   aTypesList<<Plot2d_Viewer::Type();
5215 #endif
5216 #ifndef DISABLE_QXGRAPHVIEWER
5217   aTypesList<<QxScene_Viewer::Type();
5218 #endif
5219 #ifndef DISABLE_PVVIEWER
5220   aTypesList<<PVViewer_Viewer::Type();
5221 #endif
5222 #ifndef DISABLE_PYVIEWER
5223   aTypesList<<PyViewer_Viewer::Type();
5224 #endif
5225 #ifndef DISABLE_OCCVIEWER
5226   aTypesList<<OCCViewer_Viewer::Type();
5227 #endif
5228 #ifndef DISABLE_VTKVIEWER
5229  #ifndef DISABLE_SALOMEOBJECT
5230   aTypesList<<SVTK_Viewer::Type();
5231  #else
5232   aTypesList<<VTKViewer_Viewer::Type();
5233  #endif
5234 #endif
5235 #ifndef DISABLE_PV3DVIEWER
5236   aTypesList<<PV3DViewer_ViewModel::Type();
5237 #endif
5238   return aTypesList;
5239 }
5240 /*!
5241  * Removes all view managers of known types
5242  * Other view managers are ignored
5243  */
5244 void LightApp_Application::clearKnownViewManagers()
5245 {
5246   QStringList aTypesList = viewManagersTypes();
5247   QList<SUIT_ViewManager*> aMgrList;
5248   viewManagers( aMgrList );
5249   foreach (SUIT_ViewManager* aMgr, aMgrList) {
5250     if (aTypesList.contains(aMgr->getType()))
5251       removeViewManager(aMgr);
5252   }
5253 }
5254
5255 /*!
5256   Copy of current selection
5257  */
5258 void LightApp_Application::onCopy()
5259 {
5260   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
5261   if( m )
5262     m->copy();
5263 }
5264
5265 /*!
5266   Paste of current data in clipboard
5267  */
5268 void LightApp_Application::onPaste()
5269 {
5270   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
5271   if( m )
5272     m->paste();
5273 }
5274
5275 /*!
5276   Browse (i.e. set focus on) the published objects
5277   \param theIsApplyAndClose - flag indicating that the dialog for creating objects
5278                               has been accepted by Ok (or Apply & Close) button
5279   \param theIsOptimizedBrowsing - flag switching to optimized browsing mode
5280                                   (to select the first published object only)
5281   \return entry of the selected object
5282  */
5283 QString LightApp_Application::browseObjects( const QStringList& theEntryList,
5284                                              const bool theIsApplyAndClose,
5285                                              const bool theIsOptimizedBrowsing )
5286 {
5287   QString aResult;
5288   if( SUIT_ResourceMgr* aResourceMgr = resourceMgr() )
5289   {
5290     int aBrowsePolicy = aResourceMgr->integerValue( "ObjectBrowser", "browse_published_object", (int)BP_Never );
5291     switch( aBrowsePolicy )
5292     {
5293       case BP_Never:
5294         return aResult;
5295       case BP_ApplyAndClose:
5296         if( !theIsApplyAndClose )
5297           return aResult;
5298       case BP_Always:
5299       default:
5300         break;
5301     }
5302   }
5303
5304   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( activeStudy() );
5305   if( !aStudy )
5306     return aResult;
5307
5308   SUIT_DataBrowser* anOB = objectBrowser();
5309   if( !anOB )
5310     return aResult;
5311
5312   SUIT_AbstractModel* aModel = dynamic_cast<SUIT_AbstractModel*>( anOB->model() );
5313   if( !aModel )
5314     return aResult;
5315
5316   QStringListIterator anIter( theEntryList );
5317   if( theIsOptimizedBrowsing )
5318   {
5319     // go to the last entry
5320     anIter.toBack();
5321     if( anIter.hasPrevious() )
5322       anIter.previous();
5323   }
5324
5325   // scroll to each entry in the list
5326   // (in optimized mode - to the last entry only)
5327   QString anEntry;
5328   LightApp_DataObject* anObject = 0;
5329   while( anIter.hasNext() )
5330   {
5331     anEntry = anIter.next();
5332     if( !anEntry.isEmpty() )
5333     {
5334       anObject = aStudy->findObjectByEntry( anEntry );
5335       if( anObject )
5336       {
5337         QModelIndex anIndex = aModel->index( anObject );
5338         anOB->treeView()->scrollTo( anIndex );
5339       }
5340     }
5341   }
5342
5343   // always select the last object
5344   if( anObject && !anEntry.isEmpty() )
5345   {
5346     QList<SUIT_Selector*> aSelectorList;
5347     selectionMgr()->selectors( "ObjectBrowser", aSelectorList );
5348     if( !aSelectorList.isEmpty() )
5349     {
5350       if( LightApp_OBSelector* aSelector = dynamic_cast<LightApp_OBSelector*>( aSelectorList.first() ) )
5351       {
5352         bool anIsAutoBlock = aSelector->autoBlock();
5353
5354         // temporarily disable auto block, to emit LightApp_SelectionMgr::currentSelectionChanged() signal
5355         aSelector->setAutoBlock( false );
5356
5357         SUIT_DataOwnerPtrList aList;
5358 #ifndef DISABLE_SALOMEOBJECT
5359         Handle(SALOME_InteractiveObject) aSObj = new SALOME_InteractiveObject
5360           ( anObject->entry().toUtf8().constData(),
5361             anObject->componentDataType().toLatin1().constData(),
5362             anObject->name().toUtf8().constData() );
5363         LightApp_DataOwner* owner = new LightApp_DataOwner( aSObj  );
5364 #else
5365         LightApp_DataOwner* owner = new LightApp_DataOwner( anEntry );
5366 #endif
5367
5368         aList.append( owner );
5369         selectionMgr()->setSelected( aList );
5370         aResult = anEntry;
5371
5372         // restore auto block flag
5373         aSelector->setAutoBlock( anIsAutoBlock );
5374       }
5375     }
5376   }
5377
5378   return aResult;
5379 }
5380
5381 SUIT_DataObject* LightApp_Application::findObject( const QString& id ) const
5382 {
5383   LightApp_Study* study = dynamic_cast<LightApp_Study*>( activeStudy() );
5384   return study ? study->findObjectByEntry( id ) : 0;
5385 }
5386
5387 /*!
5388   Checks that an object can be renamed.
5389   \param entry entry of the object
5390   \brief Return \c true if object can be renamed
5391 */
5392 bool LightApp_Application::renameAllowed( const QString& /*entry*/) const {
5393   return false;
5394 }
5395
5396 /*!
5397   Rename object by entry.
5398   \param entry entry of the object
5399   \param name new name of the object
5400   \brief Return \c true if rename operation finished successfully, \c false otherwise.
5401 */
5402 bool LightApp_Application::renameObject( const QString& /*entry*/, const QString& /*name*/ ) {
5403   return false;
5404 }
5405
5406 /*! Process standard messages from desktop */
5407 void LightApp_Application::onDesktopMessage( const QString& message )
5408 {
5409   const QString sectionSeparator = "/";
5410
5411   if ( message.toLower() == "updateobjectbrowser" ||
5412        message.toLower() == "updateobjbrowser" ) {
5413     // update object browser
5414     updateObjectBrowser();
5415   }
5416   else if ( message.toLower().startsWith( "activate_viewer" ) ) {
5417     QString vtype = message.split( sectionSeparator ).last();
5418     if ( !vtype.isEmpty() )
5419       getViewManager( vtype, true );
5420   }
5421   else if ( message.toLower().startsWith("register_module_in_study" ) ) {
5422     QString moduleName = message.split( sectionSeparator ).last();
5423     // Check name of current activating module name in order to avoid ciclik
5424     // call because of messages
5425     if (!property("activateModule").toBool()) {
5426       CAM_Module* mod = module(moduleName);
5427       if (!mod)
5428         mod = module(moduleTitle(moduleName));
5429       if (!mod) {
5430         mod = loadModule(moduleName);
5431         if (!mod)
5432           mod = loadModule(moduleTitle(moduleName));
5433         if (mod) {
5434           addModule(mod);
5435         }
5436       }
5437       if (mod) {
5438         CAM_Study* anActiveStudy = dynamic_cast<CAM_Study*>(activeStudy());
5439         if (anActiveStudy) {
5440           mod->connectToStudy(anActiveStudy);
5441           LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>(mod->dataModel());
5442           if(aDM) {
5443             aDM->initRootObject();
5444           }
5445         }
5446       }
5447     }
5448   }
5449   else {
5450     QStringList data = message.split( sectionSeparator );
5451     if ( data.count() > 1 ) {
5452       QString msgType = data[0].trimmed();
5453       LightApp_Module* sMod = 0;
5454       CAM_Module* mod = module( msgType );
5455       if ( !mod )
5456         mod = module( moduleTitle( msgType ) );
5457       if ( mod && mod->inherits( "LightApp_Module" ) )
5458         sMod = (LightApp_Module*)mod;
5459
5460       if ( msgType.toLower() == "preferences" ) {
5461         // requested preferences change: should be given as "preferences/<section>/<name>/<value>"
5462         // for example "preferences/Study/multi_file_dump/true"
5463         if ( data.count() > 3 ) {
5464           QString section = data[1].trimmed();
5465           QString param   = data[2].trimmed();
5466           QString value   = QStringList( data.mid(3) ).join( sectionSeparator );
5467           resourceMgr()->setValue( section, param, value );
5468         }
5469       }
5470       else if ( sMod ) {
5471         // received message for the module
5472         QString msg = QStringList( data.mid(1) ).join( sectionSeparator );
5473         sMod->message( msg );
5474       }
5475     }
5476   }
5477 }
5478
5479 void LightApp_Application::onInfoPanelShown()
5480 {
5481   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
5482     ((LightApp_Module*)activeModule())->updateInfoPanel();
5483 }
5484
5485 /*!
5486   Internal method.
5487   Returns all top level toolbars.
5488   Note : Result list contains only main window toolbars, not including toolbars from viewers.
5489 */
5490 QList<QToolBar*> LightApp_Application::findToolBars( const QStringList& names )
5491 {
5492   QList<QToolBar*> aResult;
5493   QList<QToolBar*> tbList = desktop()->findChildren<QToolBar*>();
5494   for ( QList<QToolBar*>::iterator tit = tbList.begin(); tit != tbList.end(); ++tit ) {
5495     QToolBar* tb = *tit;
5496     QObject* po = Qtx::findParent( tb, "QMainWindow" );
5497     if ( po != desktop() )
5498       continue;
5499     if ( names.isEmpty() || names.contains( tb->objectName() ) )
5500       aResult.append(tb);
5501   }
5502   return aResult;
5503 }
5504
5505 /*!
5506   Internal method to parse toolbars and dockable windows state.
5507 */
5508 QByteArray LightApp_Application::processState(QByteArray& input,
5509                                               const bool processWin,
5510                                               const bool processTb,
5511                                               const bool isRestoring,
5512                                               QByteArray defaultState) {
5513
5514   QByteArray aRes;
5515   bool hasDefaultState  = !defaultState.isEmpty();
5516   bool isDockWinWriten = false;
5517   int nbDocWin = -1;
5518   //Write date from users settings
5519   if(isRestoring){
5520     QDataStream tmpInputData(&input, QIODevice::ReadOnly);
5521     int marker, version;
5522     uchar dockmarker;
5523     tmpInputData >> marker;
5524     tmpInputData >> version;
5525     tmpInputData >> dockmarker;
5526     tmpInputData >> nbDocWin;
5527   }
5528   if(processWin && processTb && !isRestoring) {
5529     aRes = input;
5530   } else if(!processWin && !processTb ) {
5531     if(hasDefaultState)
5532       aRes = defaultState;
5533   } else {
5534     QDataStream aData(&aRes, QIODevice::WriteOnly);
5535     QList<QToolBar*> aToolBars = findToolBars();
5536
5537     QStringList aNames;
5538     for ( QList<QToolBar*>::iterator tit = aToolBars.begin(); tit != aToolBars.end(); ++tit ) {
5539       QToolBar* tb = *tit;
5540       aNames.append(tb->objectName());
5541     }
5542
5543     int toolBarMarkerIndex = getToolbarMarkerIndex(input,aNames);
5544     if(toolBarMarkerIndex < 0)
5545       return aRes;
5546     QDataStream anInputData(&input, QIODevice::ReadOnly);
5547
5548     int toolBarMarkerIndexDef = 0;
5549     if(hasDefaultState) {
5550       toolBarMarkerIndexDef = getToolbarMarkerIndex(defaultState, aNames);
5551       if(toolBarMarkerIndexDef < 0)
5552         return aRes;
5553     }
5554     QDataStream anInputDataDef(&defaultState, QIODevice::ReadOnly);
5555
5556     QDataStream* aTargetData = 0;
5557     int          aTargetIndex = -1;
5558
5559     QByteArray currentArr = desktop()->saveState();
5560     QDataStream anInputDataCur(&currentArr, QIODevice::ReadOnly);
5561     bool useInputData = !isRestoring || (isRestoring && nbDocWin > 0);
5562     if(processWin && useInputData) {
5563       aTargetData = &anInputData;
5564       aTargetIndex = toolBarMarkerIndex;
5565     } else {
5566       //Write date from default settings
5567       if(hasDefaultState) {
5568         aTargetData = &anInputDataDef;
5569         aTargetIndex = toolBarMarkerIndexDef;
5570       } else {
5571         //If no default state, write current snapshot of the dockable windows
5572         if(isRestoring) {
5573           aTargetData = &anInputDataCur;
5574           int toolBarMarkerIndexCur = getToolbarMarkerIndex(currentArr, aNames);
5575           aTargetIndex = toolBarMarkerIndexCur;
5576         }
5577       }
5578     }
5579
5580     if(aTargetData && aTargetIndex >= 0 ) {
5581       aTargetData->device()->seek(0);
5582       while( aTargetData->device()->pos() < aTargetIndex ) {
5583         uchar ch;
5584         *aTargetData >> ch;
5585         aData<<ch;
5586       }
5587       isDockWinWriten = true;
5588     }
5589
5590     aTargetData = 0;
5591     aTargetIndex = -1;
5592
5593     if(processTb) {
5594       aTargetData = &anInputData;
5595       aTargetIndex = toolBarMarkerIndex;
5596     } else {
5597       if(hasDefaultState) {
5598         aTargetData = &anInputDataDef;
5599         aTargetIndex = toolBarMarkerIndexDef;
5600       }
5601     }
5602
5603     if(aTargetData && aTargetIndex >= 0) {
5604       int index;
5605       if(!isDockWinWriten ) {
5606         //Write version marker
5607         int marker, version;
5608         aTargetData->device()->seek(0);
5609         *aTargetData >> marker;
5610         *aTargetData >> version;
5611         aData << marker;
5612         aData << version;
5613         aData << (uchar) QDockWidgetMarker;
5614         aData << (int) 0;
5615         int shift = 4*sizeof(int) + sizeof(QSize);
5616         index = aTargetIndex - shift;
5617       } else {
5618         index = aTargetIndex;
5619       }
5620
5621       aTargetData->device()->seek(index);
5622       while(!aTargetData->atEnd()) {
5623         uchar ch;
5624         *aTargetData >> ch;
5625         aData << ch;
5626       }
5627     } else { // Not treat toolbars
5628       aData << (uchar) QToolBarMarker;
5629       aData << (int) 0; //Nb toolbars = 0
5630     }
5631   }
5632   return aRes;
5633 }
5634
5635 /*!
5636   \brief Emits operationFinished signal.
5637   \param theModuleName the name of the module which perfomed the operation
5638   \param theOperationName the operation name
5639   \param theEntryList the list of the created objects entries
5640 */
5641 void LightApp_Application::emitOperationFinished( const QString& theModuleName,
5642                                                   const QString& theOperationName,
5643                                                   const QStringList& theEntryList )
5644 {
5645   emit operationFinished( theModuleName, theOperationName, theEntryList );
5646 }
5647
5648 /*!
5649   Update visibility state of given objects
5650 */
5651 void LightApp_Application::updateVisibilityState( DataObjectList& theList,
5652                                                   SUIT_ViewModel* theViewModel )
5653 {
5654   if ( !theViewModel || theList.isEmpty() ) return;
5655
5656   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5657   if ( !aStudy ) return;
5658
5659   SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
5660
5661   for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
5662     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
5663
5664     if ( !obj || aStudy->isComponent( obj->entry() ) )
5665       continue;
5666
5667     QString mname = aStudy->componentDataType(obj->entry());
5668     LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(mname, false);
5669     if ( aDisplayer ) {
5670       Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
5671       if ( aDisplayer->canBeDisplayed( obj->entry(), theViewModel->getType() ) ) {
5672         if ( aDisplayer->IsDisplayed( obj->entry(), aView ) )
5673           anObjState = Qtx::ShownState;
5674         else
5675           anObjState = Qtx::HiddenState;
5676       }
5677       aStudy->setVisibilityState( obj->entry(), anObjState );
5678     }
5679   }
5680 }
5681
5682 /*!
5683   Update presentations of all displayed objects of theComponent in specified viewers
5684 */
5685 void LightApp_Application::updatePresentations( const QString& theComponent,
5686                                                 const QStringList& theViewManagerTypes )
5687 {
5688   LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(theComponent, false);
5689   if ( aDisplayer ) {
5690     LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5691     DataObjectList aComps;
5692     bool isFound = false;
5693     aStudy->root()->children( aComps );
5694     DataObjectList::const_iterator aCompsIt = aComps.begin();
5695     for ( ; aCompsIt != aComps.end() && !isFound; aCompsIt++ ) {
5696       LightApp_DataObject* aComp = dynamic_cast<LightApp_DataObject*>( *aCompsIt );
5697       if ( aComp && aComp->componentDataType() ==  theComponent) {
5698         isFound = true;
5699         DataObjectList anObjs;
5700         aComp->children(anObjs, true);
5701
5702         QList<SUIT_ViewManager*> aViewMgrs;
5703         QStringList::const_iterator itVMTypes = theViewManagerTypes.begin();
5704         for ( ; itVMTypes != theViewManagerTypes.end(); ++itVMTypes )
5705           viewManagers( *itVMTypes, aViewMgrs );
5706
5707         DataObjectList::const_iterator itObjs = anObjs.begin();
5708         for ( ; itObjs != anObjs.end(); itObjs++ ) {
5709           LightApp_DataObject* anObj = dynamic_cast<LightApp_DataObject*>( *itObjs );
5710           QString anEntry = anObj->entry();
5711
5712           QListIterator<SUIT_ViewManager*> itViewMgrs( aViewMgrs );
5713           while ( itViewMgrs.hasNext()) {
5714             SUIT_ViewModel* aVM = itViewMgrs.next()->getViewModel();
5715             if ( aVM ) {
5716               SALOME_View* aView = dynamic_cast<SALOME_View*>(aVM);
5717               if ( aView ) {
5718                 bool isDisp = aDisplayer->IsDisplayed( anEntry, aView );
5719                 aDisplayer->Erase( anEntry, true, false, aView );
5720                 if ( isDisp ) {
5721                   aDisplayer->Display( anEntry, false, aView );
5722                 }
5723               }
5724             }
5725           }
5726         }
5727       }
5728     }
5729   }
5730 }
5731
5732 /*!
5733  * Called when window activated
5734  */
5735 void LightApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
5736 {
5737   SUIT_DataBrowser* anOB = objectBrowser();
5738   if ( !anOB )
5739     return;
5740   SUIT_DataObject* rootObj = anOB->root();
5741   if ( !rootObj )
5742     return;
5743
5744   DataObjectList listObj = rootObj->children( true );
5745
5746   SUIT_ViewModel* vmod = 0;
5747   if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
5748     vmod = vman->getViewModel();
5749   updateVisibilityState( listObj, vmod );
5750 }
5751
5752 /*!
5753   Called then view manager removed
5754 */
5755 void LightApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
5756 {
5757   ViewManagerList lst;
5758   viewManagers( lst );
5759   if ( lst.count() == 1) { // in case if closed last view window
5760     LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( activeStudy() );
5761     if ( aStudy )
5762       aStudy->setVisibilityStateForAll( Qtx::UnpresentableState );
5763   }
5764 }
5765
5766 /*!
5767   Check existing document.
5768 */
5769 bool LightApp_Application::checkExistingDoc( bool closeExistingDoc )
5770 {
5771   bool result = true;
5772   if( activeStudy() ) {
5773     int answer = !activeStudy()->isModified() ? 1 :
5774                  SUIT_MessageBox::question( desktop(),
5775                                             tr( "APPCLOSE_CAPTION" ),
5776                                             tr( "STUDYCLOSE_DESCRIPTION" ),
5777                                             tr( "APPCLOSE_SAVE" ),
5778                                             tr( "APPCLOSE_CLOSE" ),
5779                                             tr( "APPCLOSE_CANCEL" ), 0 );
5780     if(answer == 0) {
5781       if ( activeStudy()->isSaved() ) {
5782         onSaveDoc();
5783                 if (closeExistingDoc) {
5784                         closeDoc(false);
5785                 }
5786       } else if ( onSaveAsDoc() ) {
5787          if (closeExistingDoc) {
5788            if( !closeDoc( false ) ) {
5789              result = false;
5790            }
5791         }
5792       } else {
5793         result = false;
5794       }
5795     }
5796     else if( answer == 1 ) {
5797       if (closeExistingDoc) {
5798         closeDoc( false );
5799       }
5800     } else if( answer == 2 ) {
5801       result = false;
5802     }
5803   }
5804   return result;
5805 }
5806
5807 #ifndef DISABLE_PYCONSOLE
5808
5809 PyConsole_Interp* LightApp_Application::getPyInterp()
5810 {
5811   static PyConsole_Interp* myInterp = 0;
5812   if ( !myInterp ) {
5813     myInterp = createPyInterp();
5814     myInterp->initialize();
5815   }
5816   return myInterp;
5817 }
5818
5819 PyConsole_Interp* LightApp_Application::createPyInterp()
5820 {
5821   return new PyConsole_Interp();
5822 }
5823
5824 #endif // DISABLE_PYCONSOLE
5825
5826 void LightApp_Application::createHelpItems( const QString& modTitle )
5827 {
5828   if ( modTitle.isEmpty() )
5829     return;
5830
5831   QString userGuide = "User's Guide";
5832   QString devGuide = "Developer's Guide";
5833
5834   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 );
5835
5836   createMenu( userGuide, helpMenu, -1, 5 );
5837   createMenu( devGuide, helpMenu, -1, 5 );
5838
5839   IMap <QString, QString> helpData;                                 // list of help files for the module
5840   QString helpSubMenu;                                              // help submenu name (empty if not needed)
5841   QString modName = moduleName( modTitle );                         // module name
5842   if ( modName.isEmpty() ) modName = modTitle;                      // for KERNEL and GUI
5843   QString rootDir = QString( "%1_ROOT_DIR" ).arg( modName );        // module root dir env variable
5844   QString modDir = Qtx::getenv( rootDir.toUtf8().constData() );     // module root dir path
5845   QString docSection;
5846   if ( resourceMgr()->hasValue( modName, "documentation" ) )
5847     docSection = resourceMgr()->stringValue( modName, "documentation" );
5848   else if ( resourceMgr()->hasSection( modName + "_documentation" ) )
5849     docSection = modName + "_documentation";
5850   if ( !docSection.isEmpty() )
5851   {
5852     helpSubMenu = resourceMgr()->stringValue( docSection, "sub_menu", "" );
5853     if ( helpSubMenu.contains( "%1" ) )
5854       helpSubMenu = helpSubMenu.arg( modTitle );
5855     foreach( QString paramName, resourceMgr()->parameters( docSection ) )
5856     {
5857       QString key = paramName.contains( "%1" ) ? paramName.arg( modTitle ) : paramName;
5858       QString helpItem = getHelpItem( docSection, paramName );
5859       if ( !helpItem.isEmpty() )
5860         helpData.insert( key, helpItem );
5861     }
5862   }
5863
5864   if ( helpData.isEmpty() && !modDir.isEmpty() )
5865   {
5866     QStringList idxLst = QStringList() << modDir << "share" << "doc" << "salome" << "gui" << modName << "index.html";
5867     QString indexFile = idxLst.join( QDir::separator() );          // index file
5868     if ( QFile::exists( indexFile ) )
5869       helpData.insert( tr( "%1 module Users's Guide" ).arg( modTitle ), indexFile );
5870   }
5871
5872   IMapConstIterator<QString, QString > fileIt;
5873   for ( fileIt = helpData.begin(); fileIt != helpData.end(); fileIt++ )
5874   {
5875     QString helpItemPath = fileIt.key();
5876     // remove all '//' occurances
5877     while ( helpItemPath.contains( "//" ) )
5878       helpItemPath.replace( "//", "" );
5879     // obtain submenus hierarchy if given
5880     QStringList smenus = helpItemPath.split( "/" );
5881     helpItemPath = smenus.takeLast();
5882     // workaround for User's Guide and Developer's Guide to avoid having single item in module's submenu.
5883     if ( helpItemPath == userGuide || helpItemPath == devGuide )
5884     {
5885       QString menuPath = smenus.join( "/" );
5886       QStringList allKeys = helpData.keys();
5887       QStringList total = allKeys.filter( QRegExp( QString( "^%1" ).arg( menuPath ) ) );
5888       if ( total.count() == 1 && smenus.count() > 0 )
5889         helpItemPath = smenus.takeLast();
5890     }
5891     QPixmap helpIcon = fileIt.value().startsWith( "http", Qt::CaseInsensitive ) ?
5892       resourceMgr()->loadPixmap( "STD", tr( "ICON_WWW" ), false ) :
5893       resourceMgr()->loadPixmap( "STD", tr( "ICON_HELP" ), false );
5894     QAction* a = createAction( -1, helpItemPath, helpIcon, helpItemPath, helpItemPath,
5895                                0, desktop(), false, this, SLOT( onHelpContentsModule() ) );
5896     a->setData( fileIt.value() );
5897     if ( !helpSubMenu.isEmpty() )
5898       smenus.prepend( helpSubMenu );
5899     // create sub-menus hierarchy
5900     int menuId = helpMenu;
5901     foreach ( QString subMenu, smenus )
5902       menuId = createMenu( subMenu, menuId, -1, 5 );
5903     createMenu( a, menuId, -1, ( menuId != helpMenu && ( helpItemPath == userGuide || helpItemPath == devGuide ) ) ? 0 : 5 );
5904     if ( !myHelpItems.contains( modName ) )
5905       myHelpItems[modName] = IdList();
5906     myHelpItems[modName].append( actionId( a ) );
5907   }
5908 }
5909
5910 void LightApp_Application::removeHelpItems( const QString& modTitle )
5911 {
5912   QString modName = moduleName( modTitle );
5913   if ( myHelpItems.contains( modName ) )
5914   {
5915     foreach( int id, myHelpItems[modName] )
5916       setMenuShown( id, false );
5917     myHelpItems.remove( modName );
5918   }
5919 }