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