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