]> SALOME platform Git repositories - modules/gui.git/blob - src/LightApp/LightApp_Application.cxx
Salome HOME
7df31635f2fdc5363d0d73b3048f80fe8f56626f
[modules/gui.git] / src / LightApp / LightApp_Application.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File:      LightApp_Application.cxx
24 // Created:   6/20/2005 18:39:45 PM
25 // Author:    Natalia Donis
26 #ifdef WIN32
27 // E.A. : On windows with python 2.6, there is a conflict
28 // E.A. : between pymath.h and Standard_math.h which define
29 // E.A. : some same symbols : acosh, asinh, ...
30   #include <Standard_math.hxx>
31   #ifndef DISABLE_PYCONSOLE
32     #include <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                                                   const int accel )
641 {
642   QString vtlt = tr( QString( "NEW_WINDOW_%1" ).arg( suffix ).toLatin1().constData() );
643   QString tip = tr( "CREATING_NEW_WINDOW" ).arg( vtlt.remove( "&" ) );
644   QAction* a = createAction( id,                      // menu action id
645                              tip,                     // status tip
646                              QIcon(),                 // icon
647                              vtlt,                    // menu text
648                              tip,                     // tooltip
649                              accel,                   // shortcut
650                              desktop(),               // parent
651                              false,                   // toggle flag
652                              this,                    // receiver
653                              SLOT( onNewWindow() ) ); // slot
654   createMenu( a, parentId, -1 );
655 }
656
657 /*!Create actions:*/
658
659 void LightApp_Application::createActions()
660 {
661   CAM_Application::createActions();
662
663   SUIT_Desktop* desk = desktop();
664   SUIT_ResourceMgr* resMgr = resourceMgr();
665
666   // Preferences
667   createAction( PreferencesId, tr( "TOT_DESK_PREFERENCES" ), QIcon(),
668                 tr( "MEN_DESK_PREFERENCES" ), tr( "PRP_DESK_PREFERENCES" ),
669                 Qt::CTRL+Qt::Key_P, desk, false, this, SLOT( onPreferences() ) );
670
671   // Help menu
672
673   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 );
674
675   QString url;
676
677   // a) Link to web site
678   if ( HAS_WWW_URL ) {
679     url = resMgr->stringValue("GUI", "site_url");
680     if ( !url.isEmpty() ) {
681       QString title = tr ( "SALOME_SITE" );
682       QAction* as = createAction( WebSiteId, title,
683                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
684                                   title, title,
685                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
686       as->setData( url );
687       createMenu( as, helpMenu, -1, 0 );
688     }
689   }
690
691   // b) Link to Forum
692   if ( HAS_FORUM_URL ) {
693     url = resMgr->stringValue("GUI", "forum_url");
694     if ( !url.isEmpty() ) {
695       QString title = tr ( "SALOME_FORUM" );
696       QAction* af = createAction( ForumId, title,
697                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
698                                   title, title,
699                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
700       af->setData( url );
701       createMenu( af, helpMenu, -1, 0 );
702     }
703   }
704
705   // c) Link to YouTube channel
706   if ( HAS_YOUTUBE_URL ) {
707     url = resMgr->stringValue("GUI", "channel_url");
708     if ( !url.isEmpty() ) {
709       createMenu( separator(), helpMenu, -1, 0 );
710       QString title = tr ( "SALOME_VIDEO_TUTORIALS" );
711       QAction* av = createAction( VideosId, title,
712                                   resMgr->loadPixmap( "LightApp", tr( "ICON_LIFE_RIGN" ), false ),
713                                   title, tr( "PRP_SALOME_VIDEO_TUTORIALS" ),
714                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
715       av->setData( url );
716       createMenu( av, helpMenu, -1, 0 );
717     }
718   }
719
720   // d) Link to Tutorials
721   if ( HAS_TUTORIAL_URL ) {
722     url = resMgr->stringValue("GUI", "tutorials_url");
723     if ( !url.isEmpty() ) {
724       QString title = tr ( "SALOME_TUTORIALS" );
725       QAction* as = createAction( TutorialsId, title,
726                                   resMgr->loadPixmap( "LightApp", tr( "ICON_WWW" ), false ),
727                                   title, tr( "PRP_SALOME_TUTORIALS" ),
728                                   0, desk, false, this, SLOT( onHelpContentsModule() ) );
729       as->setData( url );
730       createMenu( as, helpMenu, -1, 0 );
731     }
732   }
733
734   // e) Help for modules
735
736   QStringList aModuleList;
737   modules( aModuleList, false );
738   aModuleList.prepend( "GUI" );
739   aModuleList.prepend( "KERNEL" );
740
741   foreach( QString aModule, aModuleList )
742     createHelpItems( aModule );
743
744   // f) Additional help items
745
746   int id = LightApp_Application::UserID + FIRST_HELP_ID + 1000;
747   createMenu( separator(), helpMenu, -1, 10 );
748
749   QStringList addHelpItems = resMgr->parameters( "add_help" );
750   foreach ( QString paramName, addHelpItems ) {
751     QString helpItem = getHelpItem( "add_help", paramName );
752     if ( !helpItem.isEmpty() )
753     {
754       QPixmap helpIcon = helpItem.startsWith( "http", Qt::CaseInsensitive ) ?
755         resMgr->loadPixmap( "STD", tr( "ICON_WWW" ), false ) : resMgr->loadPixmap( "STD", tr( "ICON_HELP" ), false );
756       QAction* a = createAction( id++, paramName, helpIcon, paramName, paramName,
757                                  0, desk, false, this, SLOT( onHelpContentsModule() ) );
758       a->setData( helpItem );
759       createMenu( a, helpMenu, -1, 10 );
760     }
761   }
762
763   //! MRU
764   static QtxMRUAction* mru = new QtxMRUAction( tr( "TOT_DESK_MRU" ), tr( "MEN_DESK_MRU" ), 0 );
765   connect( mru, SIGNAL( activated( const QString& ) ), this, SLOT( onMRUActivated( const QString& ) ) );
766   registerAction( MRUId, mru );
767
768   // List of modules
769   LightApp_ModuleAction* moduleAction = new LightApp_ModuleAction( resMgr, desk );
770   registerAction( ModulesListId, moduleAction );
771   // a. here we add regular modules (specified to GUI via --modules cmd line option, or default list from configuration)
772   // b. custom modules are added in customize() method
773   QStringList modList;
774   modules( modList, false );
775   foreach ( QString aModule, modList )
776     moduleAction->insertModule( aModule, moduleIcon( aModule, 20 ) ); // scale icon to 20x20 pix
777
778   connect( this, SIGNAL( moduleActivated( QString ) ),
779            moduleAction, SLOT( setActiveModule( QString ) ) );
780   connect( moduleAction, SIGNAL( moduleActivated( const QString& ) ),
781            this, SLOT( onModuleActivation( const QString& ) ) );
782   connect( moduleAction, SIGNAL( adding() ),
783            this, SLOT( onExtAdding() ) );
784   connect( moduleAction, SIGNAL( removing( QString ) ),
785            this, SLOT( onExtRemoving( QString ) ) );
786   connect( moduleAction, SIGNAL(showExtInfo()),
787            this, SLOT(onShowExtInfo()));
788
789   addExtensionsActions(moduleAction);
790
791   // New window
792   int windowMenu = createMenu( tr( "MEN_DESK_WINDOW" ), -1, MenuWindowId, 100 );
793   int newWinMenu = createMenu( tr( "MEN_DESK_NEWWINDOW" ), windowMenu, -1, 0 );
794
795   createAction( CloseId, tr( "TOT_CLOSE" ), QIcon(), tr( "MEN_DESK_CLOSE" ), tr( "PRP_CLOSE" ),
796                 Qt::CTRL+Qt::Key_F4, desk, false, this, SLOT( onCloseWindow() ) );
797   createAction( CloseAllId, tr( "TOT_CLOSE_ALL" ), QIcon(), tr( "MEN_DESK_CLOSE_ALL" ), tr( "PRP_CLOSE_ALL" ),
798                 0, desk, false, this, SLOT( onCloseAllWindow() ) );
799   createAction( GroupAllId, tr( "TOT_GROUP_ALL" ), QIcon(), tr( "MEN_DESK_GROUP_ALL" ), tr( "PRP_GROUP_ALL" ),
800                 0, desk, false, this, SLOT( onGroupAllWindow() ) );
801
802   createMenu( CloseId,     windowMenu, 0, -1 );
803   createMenu( CloseAllId,  windowMenu, 0, -1 );
804   createMenu( GroupAllId,  windowMenu, 0, -1 );
805   createMenu( separator(), windowMenu, -1, 0 );
806
807 #ifndef DISABLE_GLVIEWER
808   createActionForViewer( NewGLViewId, newWinMenu, QString::number( 0 ), Qt::ALT+Qt::Key_G );
809 #endif
810 #ifndef DISABLE_PLOT2DVIEWER
811   createActionForViewer( NewPlot2dId, newWinMenu, QString::number( 1 ), Qt::ALT+Qt::Key_P );
812 #endif
813 #ifndef DISABLE_OCCVIEWER
814   createActionForViewer( NewOCCViewId, newWinMenu, QString::number( 2 ), Qt::ALT+Qt::Key_O );
815 #endif
816 #ifndef DISABLE_VTKVIEWER
817   createActionForViewer( NewVTKViewId, newWinMenu, QString::number( 3 ), Qt::ALT+Qt::Key_K );
818 #endif
819 #ifndef DISABLE_QXGRAPHVIEWER
820   createActionForViewer( NewQxSceneViewId, newWinMenu, QString::number( 4 ), Qt::ALT+Qt::Key_S );
821 #endif
822 #ifndef DISABLE_GRAPHICSVIEW
823   createActionForViewer( NewGraphicsViewId, newWinMenu, QString::number( 5 ), Qt::ALT+Qt::Key_C );
824 #endif
825 #ifndef DISABLE_PVVIEWER
826   createActionForViewer( NewPVViewId, newWinMenu, QString::number( 6 ), Qt::ALT+Qt::Key_A );
827 #endif
828 #ifndef DISABLE_PYVIEWER
829   createActionForViewer( NewPyViewerId, newWinMenu, QString::number( 7 ), Qt::ALT+Qt::Key_Y );
830 #endif
831 #ifndef DISABLE_PV3DVIEWER
832   createActionForViewer( NewPV3DViewId, newWinMenu, QString::number( 8 ), Qt::ALT+Qt::Key_3 );
833 #endif
834
835   createAction( RenameId, tr( "TOT_RENAME" ), QIcon(), tr( "MEN_DESK_RENAME" ), tr( "PRP_RENAME" ),
836                 Qt::ALT+Qt::SHIFT+Qt::Key_R, desk, false, this, SLOT( onRenameWindow() ) );
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                 Qt::Key_F11, desk, false, this, SLOT( onFullScreen() ) );
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
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()->updateShortcuts();
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   // .... -> clipping color
3068   pref->addPreference( tr( "PREF_CLIPPING_COLOR" ), occClippingGroup,
3069                        LightApp_Preferences::Color, "OCCViewer", "clipping_color" );
3070   int texturePref = pref->addPreference( "", occClippingGroup, LightApp_Preferences::Frame );
3071   pref->setItemProperty( "columns", 2, texturePref );
3072   // .... -> use default texture
3073   pref->addPreference( tr( "PREF_CLIPPING_DEFAULT_TEXTURE" ), texturePref,
3074                LightApp_Preferences::Bool, "OCCViewer", "clipping_use_default_texture" );
3075   // .... -> clipping texture
3076   int filePref = pref->addPreference( tr( "PREF_CLIPPING_TEXTURE" ), texturePref,
3077                LightApp_Preferences::File, "OCCViewer", "clipping_texture" );
3078   pref->setItemProperty( "path_filter", tr( "OCC_TEXTURE_FILES" ), filePref );
3079   // .... -> modulate
3080   pref->addPreference( tr( "PREF_CLIPPING_MODULATE" ), texturePref,
3081                LightApp_Preferences::Bool, "OCCViewer", "clipping_modulate" );
3082   // .... -> scale factor
3083   int scaleFactor = pref->addPreference( tr( "PREF_CLIPPING_SCALE" ), texturePref,
3084                LightApp_Preferences::DblSpin, "OCCViewer", "clipping_scale" );
3085   pref->setItemProperty( "precision", 3, scaleFactor );
3086   pref->setItemProperty( "min", 1.0E-03, scaleFactor );
3087   pref->setItemProperty( "max", 1.0E03, scaleFactor );
3088   pref->setItemProperty( "step", 0.1, scaleFactor );
3089   // ... "Clipping" group <<end>>
3090
3091   // ... "Ray tracing" group <<start>>
3092   int occRayTracingGroup = pref->addPreference( tr( "PREF_GROUP_RAY_TRACING" ), occGroup );
3093   int rtPref = pref->addPreference( "", occRayTracingGroup, LightApp_Preferences::Frame );
3094   pref->setItemProperty( "columns", 2, rtPref );
3095   // .... -> depth
3096   int rt_depth = pref->addPreference( tr( "PREF_RAY_TRACING_DEPTH" ), rtPref,
3097                LightApp_Preferences::IntSpin, "OCCViewer", "rt_depth" );
3098   pref->setItemProperty( "min", 1, rt_depth );
3099   pref->setItemProperty( "max", 10, rt_depth );
3100   pref->setItemProperty( "step", 1, rt_depth );
3101   pref->addPreference( "", rtPref, LightApp_Preferences::Frame );
3102   // .... -> specular reflections
3103   pref->addPreference( tr( "PREF_RAY_TRACING_REFLECTION" ), rtPref,
3104                LightApp_Preferences::Bool, "OCCViewer", "rt_reflection" );
3105   // .... -> adaptive anti-aliasing
3106   pref->addPreference( tr( "PREF_RAY_TRACING_ANTIALIASING" ), rtPref,
3107                LightApp_Preferences::Bool, "OCCViewer", "rt_antialiasing" );
3108   // .... -> shadows rendering
3109   pref->addPreference( tr( "PREF_RAY_TRACING_SHADOW" ), rtPref,
3110                LightApp_Preferences::Bool, "OCCViewer", "rt_shadow" );
3111   // .... -> transparent shadow
3112   pref->addPreference( tr( "PREF_RAY_TRACING_TRANS_SHADOW" ), rtPref,
3113                LightApp_Preferences::Bool, "OCCViewer", "rt_trans_shadow" );
3114   // ... "Ray tracing" group <<end>>
3115
3116   // ... "Light source" group <<start>>
3117   int occLightGroup = pref->addPreference( tr( "PREF_GROUP_LIGHT" ), occGroup );
3118   // .... -> light color
3119   pref->addPreference( tr( "PREF_LIGHT_COLOR" ), occLightGroup,
3120                LightApp_Preferences::Color, "OCCViewer", "light_color" );
3121   int directionPref = pref->addPreference( "", occLightGroup, LightApp_Preferences::Frame );
3122   pref->setItemProperty( "columns", 3, directionPref );
3123   // .... -> light direction (dx component)
3124   int light_dx = pref->addPreference( tr( "Dx" ), directionPref,
3125                LightApp_Preferences::DblSpin, "OCCViewer", "light_dx" );
3126   pref->setItemProperty( "precision", 2, light_dx );
3127   pref->setItemProperty( "min", -1.0E03, light_dx );
3128   pref->setItemProperty( "max", 1.0E03, light_dx );
3129   pref->setItemProperty( "step", 0.1, light_dx );
3130   // .... -> light direction (dy component)
3131   int light_dy = pref->addPreference( tr( "Dy" ), directionPref,
3132                LightApp_Preferences::DblSpin, "OCCViewer", "light_dy" );
3133   pref->setItemProperty( "precision", 2, light_dy );
3134   pref->setItemProperty( "min", -1.0E03, light_dy );
3135   pref->setItemProperty( "max", 1.0E03, light_dy );
3136   pref->setItemProperty( "step", 0.1, light_dy );
3137   // .... -> light direction (dz component)
3138   int light_dz = pref->addPreference( tr( "Dz" ), directionPref,
3139                LightApp_Preferences::DblSpin, "OCCViewer", "light_dz" );
3140   pref->setItemProperty( "precision", 2, light_dz );
3141   pref->setItemProperty( "min", -1.0E03, light_dz );
3142   pref->setItemProperty( "max", 1.0E03, light_dz );
3143   pref->setItemProperty( "step", 0.1, light_dz );
3144   // ... "Light source" group <<end>>
3145
3146   // ... "View cube" group <<start>>
3147   int occViewCubeGroup = pref->addPreference( tr( "PREF_GROUP_VIEWCUBE" ), occGroup );
3148   pref->setItemProperty( "columns", 2, occViewCubeGroup );
3149   // .... -> show view cube on viewer start
3150   pref->addPreference( tr( "PREF_VIEWCUBE_SHOW" ), occViewCubeGroup,
3151                LightApp_Preferences::Bool, "OCCViewer", "viewcube_show" );
3152   // .... -> view cube duration of animation (sec)
3153   int viewcube_dur = pref->addPreference( tr( "PREF_VIEWCUBE_DURATION" ), occViewCubeGroup,
3154                LightApp_Preferences::DblSpin, "OCCViewer", "viewcube_duration" );
3155   pref->setItemProperty( "min", 0.1, viewcube_dur );
3156   pref->setItemProperty( "max", 10.0, viewcube_dur );
3157   pref->setItemProperty( "step", 0.1, viewcube_dur );
3158   // .... -> show view cube axes
3159   pref->addPreference( tr( "PREF_VIEWCUBE_AXES" ), occViewCubeGroup,
3160                LightApp_Preferences::Bool, "OCCViewer", "viewcube_axes" );
3161   // ... "View cube" group <<end>>
3162
3163   // ... "View cube default (OCCT) attributes" group <<start>>
3164   int occViewCubeAttrsGroup = pref->addPreference( tr( "PREF_VIEWCUBE_CUSTOM" ), occGroup,
3165                LightApp_Preferences::Auto, "OCCViewer", "viewcube_custom" );
3166   pref->setItemProperty( "columns", 2, occViewCubeAttrsGroup );
3167   // .... -> box color
3168   pref->addPreference( tr( "PREF_VIEWCUBE_COLOR" ), occViewCubeAttrsGroup,
3169                LightApp_Preferences::Color, "OCCViewer", "viewcube_color" );
3170   // .... -> view cube size
3171   int viewcube_size = pref->addPreference( tr( "PREF_VIEWCUBE_SIZE" ), occViewCubeAttrsGroup,
3172                LightApp_Preferences::DblSpin, "OCCViewer", "viewcube_size" );
3173   pref->setItemProperty( "min",  30.0, viewcube_size );
3174   pref->setItemProperty( "max", 100.0, viewcube_size );
3175   pref->setItemProperty( "step", 10.0, viewcube_size );
3176   // .... -> text color
3177   pref->addPreference( tr( "PREF_VIEWCUBE_TEXTCOLOR" ), occViewCubeAttrsGroup,
3178                LightApp_Preferences::Color, "OCCViewer", "viewcube_text_color" );
3179   // ... "View cube" group <<end>>
3180
3181   // ... -> empty frame (for layout) <<start>>
3182   int occGen = pref->addPreference( "", occGroup, LightApp_Preferences::Frame );
3183   pref->setItemProperty( "margin",  0, occGen );
3184   pref->setItemProperty( "columns", 2, occGen );
3185   // ... -> empty frame (for layout) <<end>>
3186
3187   // .. "OCC viewer" group <<end>>
3188 #endif
3189
3190 #ifndef DISABLE_VTKVIEWER
3191   // .. "VTK viewer" group <<start>>
3192   int vtkGroup = pref->addPreference( tr( "PREF_GROUP_VTKVIEWER" ), salomeCat ); //viewTab
3193
3194   // ... -> empty frame (for layout) <<start>>
3195   int vtkGen = pref->addPreference( "", vtkGroup, LightApp_Preferences::Frame );
3196   //pref->setItemProperty( "columns", 2, vtkGen );
3197   // .... -> projection mode
3198   int vtkProjMode = pref->addPreference( tr( "PREF_PROJECTION_MODE" ), vtkGen,
3199                                          LightApp_Preferences::Selector, "VTKViewer", "projection_mode" );
3200   aValuesList.clear();
3201   anIndicesList.clear();
3202   aValuesList   << tr("PREF_ORTHOGRAPHIC") << tr("PREF_PERSPECTIVE");
3203   anIndicesList << 0                       << 1;
3204   pref->setItemProperty( "strings", aValuesList,   vtkProjMode );
3205   pref->setItemProperty( "indexes", anIndicesList, vtkProjMode );
3206
3207   // .... -> Stereo group
3208   int vtkStereoGroup = pref->addPreference( tr( "PREF_GROUP_STEREO" ), vtkGroup);
3209   pref->setItemProperty( "columns", 2, vtkStereoGroup );
3210   // .... -> Stereo type
3211   int vtkStereoType = pref->addPreference( tr( "PREF_STEREO_TYPE" ), vtkStereoGroup,
3212                                            LightApp_Preferences::Selector, "VTKViewer", "stereo_type" );
3213   aValuesList.clear();
3214   anIndicesList.clear();
3215   idList.clear();
3216   SVTK_Viewer::stereoData( aValuesList, idList);
3217   foreach( int gid, idList ) anIndicesList << gid;
3218   pref->setItemProperty( "strings", aValuesList,   vtkStereoType );
3219   pref->setItemProperty( "indexes", anIndicesList, vtkStereoType );
3220   // .... -> Anaglyph filter
3221   int vtkAnaglyphFilter = pref->addPreference( tr( "PREF_ANAGLYPH_FILTER" ), vtkStereoGroup,
3222                                                LightApp_Preferences::Selector, "VTKViewer", "anaglyph_filter" );
3223   aValuesList.clear();
3224   anIndicesList.clear();
3225   aValuesList   << tr("PREF_ANAGLYPH_RED_CYAN") << tr("PREF_ANAGLYPH_YELLOW_BLUE") << tr("PREF_ANAGLYPH_GREEN_MAGENTA");
3226   anIndicesList << 0                            << 1                               << 2;
3227
3228   pref->setItemProperty( "strings", aValuesList,   vtkAnaglyphFilter );
3229   pref->setItemProperty( "indexes", anIndicesList, vtkAnaglyphFilter );
3230
3231   // .... -> Enable quad-buffer support
3232   pref->addPreference( tr( "PREF_ENABLE_QUAD_BUFFER_SUPPORT" ), vtkStereoGroup,
3233                        LightApp_Preferences::Bool, "VTKViewer", "enable_quad_buffer_support" );
3234
3235   // .... -> background
3236   aValuesList.clear();
3237   anIndicesList.clear();
3238   txtList.clear();
3239   idList.clear();
3240 #ifndef DISABLE_SALOMEOBJECT
3241   formats = SVTK_Viewer::backgroundData( aValuesList, idList, txtList );
3242 #endif
3243   foreach( int gid, idList ) anIndicesList << gid;
3244   bgId = pref->addPreference( tr( "PREF_VIEWER_BACKGROUND" ), vtkGen,
3245                               LightApp_Preferences::Background, "VTKViewer", "background" );
3246   pref->setItemProperty( "gradient_names", aValuesList, bgId );
3247   pref->setItemProperty( "gradient_ids", anIndicesList, bgId );
3248   pref->setItemProperty( "texture_enabled", !txtList.isEmpty(), bgId );
3249   pref->setItemProperty( "texture_center_enabled", (bool)txtList.contains( Qtx::CenterTexture ), bgId );
3250   pref->setItemProperty( "texture_tile_enabled", (bool)txtList.contains( Qtx::TileTexture ), bgId );
3251   pref->setItemProperty( "texture_stretch_enabled", (bool)txtList.contains( Qtx::StretchTexture ), bgId );
3252   pref->setItemProperty( "custom_enabled", false, bgId );
3253 #ifndef DISABLE_SALOMEOBJECT
3254   pref->setItemProperty( "image_formats", formats, bgId );
3255 #endif
3256   // .... -> speed increment
3257   int vtkSpeed = pref->addPreference( tr( "PREF_INCREMENTAL_SPEED" ), vtkGen,
3258                                       LightApp_Preferences::IntSpin, "VTKViewer", "speed_value" );
3259   pref->setItemProperty( "min", 1, vtkSpeed );
3260   pref->setItemProperty( "max", 1000, vtkSpeed );
3261   // .... -> speed mode
3262   int vtkSpeedMode = pref->addPreference( tr( "PREF_INCREMENTAL_SPEED_MODE" ), vtkGen,
3263                                           LightApp_Preferences::Selector, "VTKViewer", "speed_mode" );
3264   aValuesList.clear();
3265   anIndicesList.clear();
3266   aValuesList   << tr("PREF_ARITHMETIC") << tr("PREF_GEOMETRICAL");
3267   anIndicesList << 0                     << 1;
3268   pref->setItemProperty( "strings", aValuesList,   vtkSpeedMode );
3269   pref->setItemProperty( "indexes", anIndicesList, vtkSpeedMode );
3270
3271   // ... "Selection" group <<start>>
3272   int vtkSelectionGroup = pref->addPreference( tr( "PREF_GROUP_SELECTION" ), vtkGroup );
3273   pref->setItemProperty( "columns", 2, vtkSelectionGroup );
3274   // .... -> preselection
3275   int vtkPreselection = pref->addPreference( tr( "PREF_PRESELECTION" ),  vtkSelectionGroup,
3276                                              LightApp_Preferences::Selector, "VTKViewer", "preselection" );
3277   aValuesList.clear();
3278   anIndicesList.clear();
3279   aValuesList   << tr("PREF_PRESELECTION_STANDARD") << tr("PREF_PRESELECTION_DYNAMIC") << tr("PREF_PRESELECTION_DISABLED");
3280   anIndicesList << 0 << 1 << 2;
3281   pref->setItemProperty( "strings", aValuesList,   vtkPreselection );
3282   pref->setItemProperty( "indexes", anIndicesList, vtkPreselection );
3283   // .... -> enable selection
3284   pref->addPreference( tr( "PREF_ENABLE_SELECTION" ), vtkSelectionGroup, LightApp_Preferences::Bool, "VTKViewer", "enable_selection" );
3285   // ... "Selection" group <<end>>
3286
3287   // ... -> empty frame (for layout) <<end>>
3288
3289   // ... space mouse sub-group <<start>>
3290   int vtkSM = pref->addPreference( tr( "PREF_FRAME_SPACEMOUSE" ), vtkGroup, LightApp_Preferences::GroupBox );
3291   //pref->setItemProperty( "columns", 2, vtkSM );
3292   // .... -> decrease speed increment
3293   int spacemousePref1 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_1" ), vtkSM,
3294                                              LightApp_Preferences::Selector, "VTKViewer",
3295                                              "spacemouse_func1_btn" );
3296   // .... -> increase speed increment
3297   int spacemousePref2 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_2" ), vtkSM,
3298                                              LightApp_Preferences::Selector, "VTKViewer",
3299                                              "spacemouse_func2_btn" );
3300   // .... -> dominant / combined switch
3301   int spacemousePref3 = pref->addPreference( tr( "PREF_SPACEMOUSE_FUNC_3" ), vtkSM,
3302                                              LightApp_Preferences::Selector, "VTKViewer",
3303                                              "spacemouse_func5_btn" ); //
3304   aValuesList.clear();
3305   anIndicesList.clear();
3306   aValuesList << tr( "PREF_SPACEMOUSE_BTN_1" )  << tr( "PREF_SPACEMOUSE_BTN_2" ) << tr( "PREF_SPACEMOUSE_BTN_3" );
3307   aValuesList << tr( "PREF_SPACEMOUSE_BTN_4" )  << tr( "PREF_SPACEMOUSE_BTN_5" ) << tr( "PREF_SPACEMOUSE_BTN_6" );
3308   aValuesList << tr( "PREF_SPACEMOUSE_BTN_7" )  << tr( "PREF_SPACEMOUSE_BTN_8" ) << tr( "PREF_SPACEMOUSE_BTN_*" );
3309   aValuesList << tr( "PREF_SPACEMOUSE_BTN_10" ) << tr( "PREF_SPACEMOUSE_BTN_11" );
3310   anIndicesList << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11;
3311   pref->setItemProperty( "strings", aValuesList,   spacemousePref1 );
3312   pref->setItemProperty( "indexes", anIndicesList, spacemousePref1 );
3313   pref->setItemProperty( "strings", aValuesList,   spacemousePref2 );
3314   pref->setItemProperty( "indexes", anIndicesList, spacemousePref2 );
3315   pref->setItemProperty( "strings", aValuesList,   spacemousePref3 );
3316   pref->setItemProperty( "indexes", anIndicesList, spacemousePref3 );
3317   // ... space mouse sub-group <<end>>
3318
3319   // ... avi recording sub-group <<start>>
3320   int vtkRec = pref->addPreference( tr( "PREF_FRAME_RECORDING" ), vtkGroup, LightApp_Preferences::GroupBox );
3321   pref->setItemProperty( "columns", 2, vtkRec );
3322   // .... -> recording mode
3323   int modePref = pref->addPreference( tr( "PREF_RECORDING_MODE" ), vtkRec,
3324                                       LightApp_Preferences::Selector, "VTKViewer", "recorder_mode" );
3325   aValuesList.clear();
3326   anIndicesList.clear();
3327   aValuesList   << tr( "PREF_SKIPPED_FRAMES" ) << tr( "PREF_ALL_DISLPAYED_FRAMES" );
3328   anIndicesList << 0                           << 1;
3329   pref->setItemProperty( "strings", aValuesList,   modePref );
3330   pref->setItemProperty( "indexes", anIndicesList, modePref );
3331   // .... -> fps
3332   int fpsPref = pref->addPreference( tr( "PREF_FPS" ), vtkRec,
3333                                      LightApp_Preferences::DblSpin, "VTKViewer", "recorder_fps" );
3334   pref->setItemProperty( "min", 0.1, fpsPref );
3335   pref->setItemProperty( "max", 100, fpsPref );
3336   // .... -> quality
3337   int qualityPref = pref->addPreference( tr( "PREF_QUALITY" ), vtkRec,
3338                                          LightApp_Preferences::IntSpin, "VTKViewer", "recorder_quality" );
3339   pref->setItemProperty( "min", 1, qualityPref );
3340   pref->setItemProperty( "max", 100, qualityPref );
3341   // .... -> progressive mode
3342   pref->addPreference( tr( "PREF_PROGRESSIVE" ), vtkRec,
3343                        LightApp_Preferences::Bool, "VTKViewer", "recorder_progressive" );
3344   // ... avi recording sub-group <<end>>
3345
3346   // ... group names sub-group <<start>>
3347   int vtkGN = pref->addPreference( tr( "PREF_FRAME_GROUP_NAMES" ), vtkGroup,
3348                                    LightApp_Preferences::GroupBox, "VTKViewer", "show_group_names" );
3349   pref->setItemProperty( "columns", 2, vtkGN );
3350   // .... -> text color
3351   pref->addPreference( tr(  "PREF_GROUP_NAMES_TEXT_COLOR" ), vtkGN,
3352                        LightApp_Preferences::Color, "VTKViewer", "group_names_text_color" );
3353   // .... -> transparency
3354   int transPref = pref->addPreference( tr( "PREF_GROUP_NAMES_TRANSPARENCY" ), vtkGN,
3355                                        LightApp_Preferences::DblSpin, "VTKViewer", "group_names_transparency" );
3356   pref->setItemProperty( "min", 0.0, transPref );
3357   pref->setItemProperty( "max", 1.0, transPref );
3358   pref->setItemProperty( "step", 0.1, transPref );
3359   // ... -> group names sub-group <<end>>
3360   // .. "VTK viewer" group <<end>>
3361 #endif
3362
3363   // .. "Plot2d viewer" group <<start>>
3364   int plot2dGroup = pref->addPreference( tr( "PREF_GROUP_PLOT2DVIEWER" ), salomeCat ); //viewTab
3365   //pref->setItemProperty( "columns", 2, plot2dGroup );
3366
3367   // ... -> background
3368   pref->addPreference( tr( "PREF_VIEWER_BACKGROUND_COLOR" ), plot2dGroup,
3369                        LightApp_Preferences::Color, "Plot2d", "Background" );
3370   // ... -> selection color
3371   pref->addPreference( tr( "PREF_VIEWER_SELECTION" ), plot2dGroup,
3372                        LightApp_Preferences::Color, "Plot2d", "SelectionColor" );
3373
3374   // ... "Viewer" group <<start>>
3375   int plot2dViewerGroup = pref->addPreference( tr( "PREF_GROUP_VIEWER" ), plot2dGroup );
3376
3377   // .... -> curve type
3378   int curveType = pref->addPreference( tr( "PREF_CURVE_TYPE" ), plot2dViewerGroup,
3379                                        LightApp_Preferences::Selector, "Plot2d", "CurveType" );
3380   aValuesList.clear();
3381   anIndicesList.clear();
3382   aValuesList   << tr("PREF_POINTS") << tr("PREF_LINES") << tr("PREF_SPLINE");
3383   anIndicesList << 0                 << 1                << 2                ;
3384   pref->setItemProperty( "strings", aValuesList,   curveType );
3385   pref->setItemProperty( "indexes", anIndicesList, curveType );
3386   // .... -> marker size
3387   int markerSize = pref->addPreference( tr( "PREF_MARKER_SIZE" ), plot2dViewerGroup,
3388                                         LightApp_Preferences::IntSpin, "Plot2d", "MarkerSize" );
3389   pref->setItemProperty( "min", 0, markerSize );
3390   pref->setItemProperty( "max", 100, markerSize );
3391   // .... -> horizontal scaling mode
3392   int horScale = pref->addPreference( tr( "PREF_HOR_AXIS_SCALE" ), plot2dViewerGroup,
3393                                       LightApp_Preferences::Selector, "Plot2d", "HorScaleMode" );
3394   aValuesList.clear();
3395   anIndicesList.clear();
3396   aValuesList   << tr("PREF_LINEAR") << tr("PREF_LOGARITHMIC");
3397   anIndicesList << 0                 << 1                     ;
3398   pref->setItemProperty( "strings", aValuesList,   horScale );
3399   pref->setItemProperty( "indexes", anIndicesList, horScale );
3400   // .... -> vertical scaling mode
3401   int verScale = pref->addPreference( tr( "PREF_VERT_AXIS_SCALE" ), plot2dViewerGroup,
3402                                       LightApp_Preferences::Selector, "Plot2d", "VerScaleMode" );
3403   pref->setItemProperty( "strings", aValuesList,   verScale );
3404   pref->setItemProperty( "indexes", anIndicesList, verScale );
3405
3406   // .... -> errors/deviation colot
3407   pref->addPreference( tr( "PREF_DEVIATION_COLOR" ), plot2dViewerGroup,
3408                        LightApp_Preferences::Color, "Plot2d", "DeviationMarkerColor" );
3409   // .... -> deviation markers line size
3410   int deviationMarkerLw = pref->addPreference( tr( "PREF_DEVIATION_MARKER_LW" ), plot2dViewerGroup,
3411                                         LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerLineWidth" );
3412   pref->setItemProperty( "min", 1, deviationMarkerLw );
3413   pref->setItemProperty( "max", 5, deviationMarkerLw );
3414   // .... -> deviation markers tick mark size
3415   int deviationMarkerTs = pref->addPreference( tr( "PREF_DEVIATION_MARKER_TS" ), plot2dViewerGroup,
3416                                         LightApp_Preferences::IntSpin, "Plot2d", "DeviationMarkerTickSize" );
3417   pref->setItemProperty( "min", 1, deviationMarkerTs );
3418   pref->setItemProperty( "max", 5, deviationMarkerTs );
3419   // .... "Viewer" group <<end>>
3420
3421   // ... "Legend" group <<start>>
3422   int plot2dLegendGroup = pref->addPreference( tr( "PREF_GROUP_LEGEND" ), plot2dGroup );
3423
3424   // .... -> show legend
3425   pref->addPreference( tr( "PREF_SHOW_LEGEND" ), plot2dLegendGroup,
3426                        LightApp_Preferences::Bool, "Plot2d", "ShowLegend" );
3427   // .... -> legend position
3428   int legendPosition = pref->addPreference( tr( "PREF_LEGEND_POSITION" ), plot2dLegendGroup,
3429                                             LightApp_Preferences::Selector, "Plot2d", "LegendPos" );
3430   aValuesList.clear();
3431   anIndicesList.clear();
3432   aValuesList   << tr("PREF_LEFT") << tr("PREF_RIGHT") << tr("PREF_TOP") << tr("PREF_BOTTOM");
3433   anIndicesList << 0               << 1                << 2              << 3                ;
3434   pref->setItemProperty( "strings", aValuesList,   legendPosition );
3435   pref->setItemProperty( "indexes", anIndicesList, legendPosition );
3436   // .... -> Symbol type
3437   int legendSymbolType = pref->addPreference( tr( "PREF_LEGEND_SYMBOL_TYPE" ), plot2dLegendGroup,
3438                                             LightApp_Preferences::Selector, "Plot2d", "LegendSymbolType" );
3439   aValuesList.clear();
3440   anIndicesList.clear();
3441   aValuesList   << tr("PREF_MARKER_ON_LINE") << tr("PREF_MARKER_ABOVE_LINE");
3442   anIndicesList << 0                            << 1                        ;
3443   pref->setItemProperty( "strings", aValuesList,   legendSymbolType );
3444   pref->setItemProperty( "indexes", anIndicesList, legendSymbolType );
3445   // .... -> legend font
3446   pref->addPreference( tr( "PREF_LEGEND_FONT" ), plot2dLegendGroup, LightApp_Preferences::Font, "Plot2d", "LegendFont" );
3447   // ... -> font color
3448   pref->addPreference( tr( "PREF_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "LegendFontColor" );
3449   // ... -> selection font color
3450   pref->addPreference( tr( "PREF_SELECTED_FONT_COLOR" ), plot2dLegendGroup, LightApp_Preferences::Color, "Plot2d", "SelectedLegendFontColor" );
3451   // ... "Legend" group <<end>>
3452
3453   // .. "Plot2d viewer" group <<end>>
3454
3455   // .. "PyViewer" preferences tab <<start>>
3456   int pyeditTab = pref->addPreference( tr( "PREF_TAB_PYEDITOR" ), salomeCat );
3457   // ... "Font settings" group <<start>>
3458   int pyFontGroup = pref->addPreference( tr( "PREF_GROUP_PY_FONT" ), pyeditTab );
3459   int pyFont = pref->addPreference( tr( "PREF_PY_FONT" ), pyFontGroup,
3460                                     LightApp_Preferences::Font, "PyEditor", "Font" );
3461   pref->setItemProperty( "features", QtxFontEdit::Family | QtxFontEdit::Size | QtxFontEdit::UserSize, pyFont );
3462   // ... "Font settings" group <<end>>
3463   // ... "Display settings" group <<start>>
3464   int pyDispGroup = pref->addPreference( tr( "PREF_GROUP_PY_DISPLAY" ), pyeditTab );
3465   pref->setItemProperty( "columns", 2, pyDispGroup );
3466   // ... -> current line highlight
3467   pref->addPreference( tr( "PREF_PY_CURRLINE_HIGHLIGHT" ), pyDispGroup,
3468     LightApp_Preferences::Bool, "PyEditor", "HighlightCurrentLine" );
3469   // ... -> text wrapping
3470   pref->addPreference( tr( "PREF_PY_TEXT_WRAP" ), pyDispGroup,
3471     LightApp_Preferences::Bool, "PyEditor", "TextWrapping" );
3472   // ... -> center cursor on scroll
3473   pref->addPreference( tr( "PREF_PY_CURSON_ON_SCROLL" ), pyDispGroup,
3474     LightApp_Preferences::Bool, "PyEditor", "CenterCursorOnScroll" );
3475   // ... -> line numbers area
3476   pref->addPreference( tr( "PREF_PY_LINE_NUMBS_AREA" ), pyDispGroup,
3477     LightApp_Preferences::Bool, "PyEditor", "LineNumberArea" );
3478   // ... "Display settings" group <<end>>
3479
3480   // ... "Editor settings" group <<start>>
3481   int pyEditGroup = pref->addPreference( tr( "PREF_GROUP_PY_EDITOR" ), pyeditTab );
3482   // ... -> navigation mode
3483   int pyCompletion = pref->addPreference( tr( "PREF_PY_COMPLETION_MODE" ), pyEditGroup,
3484                                           LightApp_Preferences::Selector, "PyEditor", "CompletionPolicy" );
3485   aValuesList.clear();
3486   anIndicesList.clear();
3487   aValuesList   << tr("PREF_PY_NONE") << tr("PREF_PY_AUTO") << tr("PREF_PY_MANUAL") << tr("PREF_PY_ALWAYS");
3488   anIndicesList << 0                  << 1                  << 2                    << 3                   ;
3489   pref->setItemProperty( "strings", aValuesList, pyCompletion );
3490   pref->setItemProperty( "indexes", anIndicesList, pyCompletion );
3491   // ... "Editor settings" group <<end>>
3492
3493   // ... "Tab settings" group <<start>>
3494   int pyTabGroup = pref->addPreference( tr( "PREF_GROUP_PY_TAB" ), pyeditTab );
3495   pref->setItemProperty( "columns", 2, pyTabGroup );
3496   // ... -> tab whitespaces
3497   pref->addPreference( tr( "PREF_PY_TAB_WHITESPACES" ), pyTabGroup,
3498     LightApp_Preferences::Bool, "PyEditor", "TabSpaceVisible" );
3499   // ... -> tab size
3500   pref->addPreference( tr( "PREF_PY_TAB_SIZE" ), pyTabGroup,
3501     LightApp_Preferences::IntSpin, "PyEditor", "TabSize" );
3502   // ... "Tab settings" group <<end>>
3503   // ... "Vertical edge settings" group <<start>>
3504   int pyVertEdgeGroup = pref->addPreference( tr( "PREF_GROUP_VERT_EDGE" ), pyeditTab );
3505   pref->setItemProperty( "columns", 2, pyVertEdgeGroup );
3506   // ... -> vertical edge
3507   pref->addPreference( tr( "PREF_PY_VERT_EDGE" ), pyVertEdgeGroup,
3508     LightApp_Preferences::Bool, "PyEditor", "VerticalEdge" );
3509   // ... -> number of columns
3510   pref->addPreference( tr( "PREF_PY_NUM_COLUMNS" ), pyVertEdgeGroup,
3511     LightApp_Preferences::IntSpin, "PyEditor", "NumberColumns" );
3512   // ... "Vertical edge settings" group <<end>>
3513   // .. "PyEditor" preferences tab <<end>>
3514
3515   // .. "Directories" preferences tab <<start>>
3516   int dirTab = pref->addPreference( tr( "PREF_TAB_DIRECTORIES" ), salomeCat );
3517   // ... --> quick directories list
3518   int dirGroup = pref->addPreference( tr( "PREF_GROUP_DIRECTORIES" ), dirTab );
3519   pref->addPreference( tr( "" ), dirGroup,
3520                        LightApp_Preferences::DirList, "FileDlg", "QuickDirList" );
3521   // .. "Directories" preferences tab <<end>>
3522
3523   // .. "Object browser" preferences tab <<start>>
3524   int obTab = pref->addPreference( tr( "PREF_TAB_OBJBROWSER" ), salomeCat );
3525
3526   // ... "Search tool" group <<start>>
3527   int stGroup = pref->addPreference( tr( "PREF_OBJ_BROWSER_SEARCH_TOOL" ), obTab );
3528   // .... --> auto-hide
3529   pref->addPreference( tr( "PREF_AUTO_HIDE_SEARCH_TOOL" ), stGroup, LightApp_Preferences::Bool,
3530                        "ObjectBrowser", "auto_hide_search_tool" );
3531   // ... "Search tool" group <<end>>
3532
3533   // ... "Object browser settings" group <<start>>
3534   int objSetGroup = pref->addPreference( tr( "PREF_GROUP_LOOK_AND_FEEL" ), obTab );
3535   pref->setItemProperty( "columns", 2, objSetGroup );
3536   // .... -> auto size first column
3537   pref->addPreference( tr( "PREF_AUTO_SIZE_FIRST" ), objSetGroup, LightApp_Preferences::Bool,
3538                        "ObjectBrowser", "auto_size_first" );
3539   // .... -> auto size other columns
3540   pref->addPreference( tr( "PREF_AUTO_SIZE" ), objSetGroup, LightApp_Preferences::Bool,
3541                        "ObjectBrowser", "auto_size" );
3542   // .... -> resize columns on expand item
3543   pref->addPreference( tr( "PREF_RESIZE_ON_EXPAND_ITEM" ), objSetGroup, LightApp_Preferences::Bool,
3544                        "ObjectBrowser", "resize_on_expand_item" );
3545   // .... -> browse to published object
3546   int browsePublished = pref->addPreference( tr( "PREF_BROWSE_TO_THE_PUBLISHED_OBJECT" ), objSetGroup, LightApp_Preferences::Selector,
3547                                              "ObjectBrowser", "browse_published_object" );
3548   aValuesList.clear();
3549   anIndicesList.clear();
3550   aValuesList << tr( "PREF_BROWSE_NEVER" ) << tr( "PREF_BROWSE_AFTER_APPLY_AND_CLOSE_ONLY" ) << tr( "PREF_BROWSE_ALWAYS" );
3551   anIndicesList << BP_Never << BP_ApplyAndClose << BP_Always;
3552   pref->setItemProperty( "strings", aValuesList,   browsePublished );
3553   pref->setItemProperty( "indexes", anIndicesList, browsePublished );
3554   // ... "Object browser settings" group <<end>>
3555   // .. "Object browser" preferences tab <<end>>
3556
3557   // .. "Shortcuts" preferences tab <<start>>
3558   int shortcutTab = pref->addPreference( tr( "PREF_TAB_SHORTCUTS" ), salomeCat );
3559   // ... "Shortcuts settings" group <<start>>
3560   int shortcutGroup = pref->addPreference( tr( "PREF_GROUP_SHORTCUTS" ), shortcutTab );
3561   pref->addPreference( tr( "" ), shortcutGroup,
3562                        LightApp_Preferences::ShortcutTree, "shortcuts" );
3563   // ... "Shortcuts settings" group <<end>>
3564   // .. "Shortcuts" preferences tab <<end>>
3565   // . Top-level "SALOME" preferences group <<end>>
3566
3567   pref->retrieve();
3568 }
3569
3570 /*!
3571   Changes appearance of application according to changed preferences
3572   \param sec - section
3573   \param param - name of changed parameter
3574 */
3575 void LightApp_Application::preferencesChanged( const QString& sec, const QString& param )
3576 {
3577   SUIT_ResourceMgr* resMgr = resourceMgr();
3578   if ( !resMgr )
3579     return;
3580
3581   if ( sec == "viewers" && param == "drop_down_buttons" )
3582   {
3583     ViewManagerList vmlist = viewManagers();
3584     foreach( SUIT_ViewManager* vm, vmlist )
3585     {
3586       QVector<SUIT_ViewWindow*> vwlist = vm->getViews();
3587       foreach( SUIT_ViewWindow* vw, vwlist )
3588         if ( vw ) vw->setDropDownButtons( resMgr->booleanValue( "viewers", "drop_down_buttons", true ) );
3589     }
3590   }
3591
3592   if ( sec == QString( "3DViewer" ) && (param == QString( "trihedron_size" ) || param == QString( "relative_size" )))
3593   {
3594     double sz = resMgr->doubleValue( sec, "trihedron_size", -1 );
3595     bool relative = resMgr->booleanValue( sec, "relative_size", true );
3596     QList<SUIT_ViewManager*> lst;
3597 #ifndef DISABLE_OCCVIEWER
3598     viewManagers( OCCViewer_Viewer::Type(), lst );
3599     QListIterator<SUIT_ViewManager*> itOCC( lst );
3600     while ( itOCC.hasNext() && sz >= 0 )
3601     {
3602       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3603       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3604         continue;
3605
3606       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3607       occVM->setTrihedronSize( sz, relative );
3608       occVM->getAISContext()->UpdateCurrentViewer();
3609     }
3610 #endif
3611 #ifndef DISABLE_VTKVIEWER
3612 #ifndef DISABLE_SALOMEOBJECT
3613     viewManagers( SVTK_Viewer::Type(), lst );
3614     QListIterator<SUIT_ViewManager*> itVTK( lst );
3615     while ( itVTK.hasNext() && sz >= 0 )
3616     {
3617       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3618       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3619         continue;
3620
3621       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3622       if( vtkVM )
3623       {
3624         vtkVM->setTrihedronSize( sz, relative );
3625         vtkVM->Repaint();
3626       }
3627     }
3628 #endif
3629 #endif
3630   }
3631
3632   if ( sec == QString( "3DViewer" ) && param == QString( "show_static_trihedron" ) )
3633   {
3634     bool isVisible = resMgr->booleanValue( "3DViewer", "show_static_trihedron", true );
3635     QList<SUIT_ViewManager*> lst;
3636 #ifndef DISABLE_OCCVIEWER
3637     viewManagers( OCCViewer_Viewer::Type(), lst );
3638     QListIterator<SUIT_ViewManager*> itOCC( lst );
3639     while ( itOCC.hasNext() )
3640     {
3641       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3642       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3643         continue;
3644
3645       OCCViewer_Viewer* occVM = dynamic_cast<OCCViewer_Viewer*>( vm );
3646       if( occVM )
3647       {
3648         occVM->setStaticTrihedronDisplayed( isVisible );
3649       }
3650     }
3651 #endif
3652 #ifndef DISABLE_VTKVIEWER
3653 #ifndef DISABLE_SALOMEOBJECT
3654     viewManagers( SVTK_Viewer::Type(), lst );
3655     QListIterator<SUIT_ViewManager*> itVTK( lst );
3656     while ( itVTK.hasNext() )
3657     {
3658       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3659       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3660         continue;
3661
3662       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3663       if( vtkVM )
3664       {
3665         vtkVM->setStaticTrihedronVisible( isVisible );
3666         vtkVM->Repaint();
3667       }
3668     }
3669 #endif
3670 #endif
3671   }
3672
3673   if ( sec == QString( "3DViewer" ) && param == QString( "navigation_mode" ) )
3674   {
3675     int mode = resMgr->integerValue( "3DViewer", "navigation_mode", 0 );
3676     QList<SUIT_ViewManager*> lst;
3677 #ifndef DISABLE_OCCVIEWER
3678     viewManagers( OCCViewer_Viewer::Type(), lst );
3679     QListIterator<SUIT_ViewManager*> itOCC( lst );
3680     while ( itOCC.hasNext() )
3681     {
3682       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3683       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3684         continue;
3685
3686       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3687       occVM->setInteractionStyle( mode );
3688     }
3689 #endif
3690 #ifndef DISABLE_VTKVIEWER
3691 #ifndef DISABLE_SALOMEOBJECT
3692     viewManagers( SVTK_Viewer::Type(), lst );
3693     QListIterator<SUIT_ViewManager*> itVTK( lst );
3694     while ( itVTK.hasNext() )
3695     {
3696       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
3697       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
3698         continue;
3699
3700       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
3701       if( vtkVM ) vtkVM->setInteractionStyle( mode );
3702     }
3703 #endif
3704 #endif
3705   }
3706
3707 #ifndef DISABLE_OCCVIEWER
3708   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_preselection" ) )
3709   {
3710     bool isToEnablePreselection = resMgr->booleanValue( "OCCViewer", "enable_preselection", true );
3711     QList<SUIT_ViewManager*> lst;
3712     viewManagers( OCCViewer_Viewer::Type(), lst );
3713     QListIterator<SUIT_ViewManager*> it( lst );
3714     while ( it.hasNext() )
3715     {
3716       SUIT_ViewModel* vm = it.next()->getViewModel();
3717       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3718         continue;
3719
3720       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3721       occVM->enablePreselection( isToEnablePreselection );
3722     }
3723   }
3724 #endif
3725
3726 #ifndef DISABLE_OCCVIEWER
3727   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_selection" ) )
3728   {
3729     bool isToEnableSelection = resMgr->booleanValue( "OCCViewer", "enable_selection", true );
3730     QList<SUIT_ViewManager*> lst;
3731     viewManagers( OCCViewer_Viewer::Type(), lst );
3732     QListIterator<SUIT_ViewManager*> it( lst );
3733     while ( it.hasNext() )
3734     {
3735       SUIT_ViewModel* vm = it.next()->getViewModel();
3736       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3737         continue;
3738
3739       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3740       occVM->enableSelection( isToEnableSelection );
3741     }
3742   }
3743 #endif
3744
3745 #ifndef DISABLE_OCCVIEWER
3746   if ( sec == QString( "OCCViewer" ) && param == QString( "clipping_color" ) )
3747   {
3748     QColor aColor = resMgr->colorValue( "OCCViewer", "clipping_color", QColor( 50, 50, 50 ) );
3749     QList<SUIT_ViewManager*> lst;
3750     viewManagers( OCCViewer_Viewer::Type(), lst );
3751     QListIterator<SUIT_ViewManager*> it( lst );
3752     while ( it.hasNext() )
3753     {
3754       SUIT_ViewModel* vm = it.next()->getViewModel();
3755       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3756         continue;
3757
3758       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3759       occVM->setClippingColor( aColor );
3760     }
3761   }
3762 #endif
3763
3764 #ifndef DISABLE_OCCVIEWER
3765   if ( sec == QString( "OCCViewer" ) && ( param == QString( "clipping_use_default_texture" ) ||
3766                                           param == QString( "clipping_texture" ) ||
3767                                           param == QString( "clipping_modulate" ) ||
3768                                           param == QString( "clipping_scale" ) ) )
3769   {
3770     bool isDefaultTextureUsed = resMgr->booleanValue( "OCCViewer", "clipping_use_default_texture" );
3771     QString aTexture = resMgr->stringValue( "OCCViewer", "clipping_texture" );
3772     bool isModulated = resMgr->booleanValue( "OCCViewer", "clipping_modulate" );
3773     double aScale = resMgr->doubleValue( "OCCViewer", "clipping_scale" );
3774     QList<SUIT_ViewManager*> lst;
3775     viewManagers( OCCViewer_Viewer::Type(), lst );
3776     QListIterator<SUIT_ViewManager*> it( lst );
3777     while ( it.hasNext() )
3778     {
3779       SUIT_ViewModel* vm = it.next()->getViewModel();
3780       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3781         continue;
3782
3783       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3784       occVM->setClippingTextureParams( isDefaultTextureUsed, aTexture, isModulated, aScale );
3785     }
3786   }
3787 #endif
3788
3789 #ifndef DISABLE_OCCVIEWER
3790   if ( sec == QString( "OCCViewer" ) && param == QString( "projection_mode" ) )
3791   {
3792     int mode = resMgr->integerValue( "OCCViewer", "projection_mode", 0 );
3793     QList<SUIT_ViewManager*> lst;
3794     viewManagers( OCCViewer_Viewer::Type(), lst );
3795     QListIterator<SUIT_ViewManager*> it( lst );
3796     while ( it.hasNext() )
3797     {
3798       SUIT_ViewModel* vm = it.next()->getViewModel();
3799       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3800         continue;
3801
3802       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3803       occVM->setProjectionType( mode );
3804     }
3805   }
3806 #endif
3807
3808
3809 #ifndef DISABLE_OCCVIEWER
3810   if (sec == QString("OCCViewer") && param == QString("adv_selection_mode"))
3811   {
3812     int mode = resMgr->integerValue("OCCViewer", "adv_selection_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->setSelectionStyle((OCCViewer_ViewWindow::SelectionStyle)mode);
3824     }
3825   }
3826 #endif
3827
3828
3829 #ifndef DISABLE_OCCVIEWER
3830   if ( sec == QString( "OCCViewer" ) && param == QString( "stereo_type" ) )
3831   {
3832     int mode = resMgr->integerValue( "OCCViewer", "stereo_type", 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->setStereoType( mode );
3844     }
3845   }
3846 #endif
3847
3848 #ifndef DISABLE_OCCVIEWER
3849   if ( sec == QString( "OCCViewer" ) && param == QString( "anaglyph_filter" ) )
3850   {
3851     int mode = resMgr->integerValue( "OCCViewer", "anaglyph_filter", 0 );
3852     QList<SUIT_ViewManager*> lst;
3853     viewManagers( OCCViewer_Viewer::Type(), lst );
3854     QListIterator<SUIT_ViewManager*> it( lst );
3855     while ( it.hasNext() )
3856     {
3857       SUIT_ViewModel* vm = it.next()->getViewModel();
3858       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3859         continue;
3860
3861       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3862       occVM->setAnaglyphFilter( mode );
3863     }
3864   }
3865 #endif
3866
3867 #ifndef DISABLE_OCCVIEWER
3868   if ( sec == QString( "OCCViewer" ) && ( param == QString( "focus_type" ) ||
3869                                           param == QString( "focus_value" ) ) )
3870   {
3871     int aType = resMgr->integerValue( "OCCViewer", "focus_type" );
3872     double aValue = resMgr->doubleValue( "OCCViewer", "focus_value" );
3873     QList<SUIT_ViewManager*> lst;
3874     viewManagers( OCCViewer_Viewer::Type(), lst );
3875     QListIterator<SUIT_ViewManager*> it( lst );
3876     while ( it.hasNext() )
3877     {
3878       SUIT_ViewModel* vm = it.next()->getViewModel();
3879       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3880         continue;
3881
3882       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3883       occVM->setStereographicFocus( aType, aValue );
3884     }
3885   }
3886 #endif
3887
3888 #ifndef DISABLE_OCCVIEWER
3889   if ( sec == QString( "OCCViewer" ) && ( param == QString( "iod_type" ) ||
3890                                           param == QString( "iod_value" ) ) )
3891   {
3892     int aType = resMgr->integerValue( "OCCViewer", "iod_type" );
3893     double aValue = resMgr->doubleValue( "OCCViewer", "iod_value" );
3894     QList<SUIT_ViewManager*> lst;
3895     viewManagers( OCCViewer_Viewer::Type(), lst );
3896     QListIterator<SUIT_ViewManager*> it( lst );
3897     while ( it.hasNext() )
3898     {
3899       SUIT_ViewModel* vm = it.next()->getViewModel();
3900       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3901         continue;
3902
3903       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3904       occVM->setInterocularDistance( aType, aValue );
3905     }
3906   }
3907 #endif
3908
3909 #ifndef DISABLE_OCCVIEWER
3910   if ( sec == QString( "OCCViewer" ) && param == QString( "reverse_stereo" ) )
3911   {
3912     bool reverse = resMgr->booleanValue( "OCCViewer", "reverse_stereo", false );
3913     QList<SUIT_ViewManager*> lst;
3914     viewManagers( OCCViewer_Viewer::Type(), lst );
3915     QListIterator<SUIT_ViewManager*> it( lst );
3916     while ( it.hasNext() )
3917     {
3918       SUIT_ViewModel* vm = it.next()->getViewModel();
3919       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3920         continue;
3921
3922       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3923       occVM->setReverseStereo( reverse );
3924     }
3925   }
3926 #endif
3927
3928 #ifndef DISABLE_OCCVIEWER
3929   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_vsync" ) )
3930   {
3931     bool enable = resMgr->booleanValue( "OCCViewer", "enable_vsync", true );
3932     QList<SUIT_ViewManager*> lst;
3933     viewManagers( OCCViewer_Viewer::Type(), lst );
3934     QListIterator<SUIT_ViewManager*> it( lst );
3935     while ( it.hasNext() )
3936     {
3937       SUIT_ViewModel* vm = it.next()->getViewModel();
3938       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3939         continue;
3940
3941       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3942       occVM->setVSync( enable );
3943     }
3944   }
3945 #endif
3946
3947 #ifndef DISABLE_OCCVIEWER
3948   if ( sec == QString( "OCCViewer" ) && param == QString( "enable_quad_buffer_support" ) )
3949   {
3950     bool enable = resMgr->booleanValue( "OCCViewer", "enable_quad_buffer_support", false );
3951     QList<SUIT_ViewManager*> lst;
3952     viewManagers( OCCViewer_Viewer::Type(), lst );
3953     QListIterator<SUIT_ViewManager*> it( lst );
3954     while ( it.hasNext() )
3955     {
3956       SUIT_ViewModel* vm = it.next()->getViewModel();
3957       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3958         continue;
3959
3960       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3961       occVM->setQuadBufferSupport( enable );
3962     }
3963   }
3964 #endif
3965
3966 #ifndef DISABLE_OCCVIEWER
3967   if ( sec == QString( "OCCViewer" ) && param.contains( "viewcube" ) )
3968   {
3969     QList<SUIT_ViewManager*> lst;
3970     viewManagers( OCCViewer_Viewer::Type(), lst );
3971     QListIterator<SUIT_ViewManager*> it( lst );
3972     while ( it.hasNext() )
3973     {
3974       SUIT_ViewModel* vm = it.next()->getViewModel();
3975       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3976         continue;
3977
3978       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3979       occVM->setViewCubeParamsFromPreferences();
3980     }
3981   }
3982 #endif
3983
3984   if ( sec == QString( "3DViewer" ) && param == QString( "zooming_mode" ) )
3985   {
3986     int mode = resMgr->integerValue( "3DViewer", "zooming_mode", 0 );
3987     QList<SUIT_ViewManager*> lst;
3988 #ifndef DISABLE_OCCVIEWER
3989     viewManagers( OCCViewer_Viewer::Type(), lst );
3990     QListIterator<SUIT_ViewManager*> itOCC( lst );
3991     while ( itOCC.hasNext() )
3992     {
3993       SUIT_ViewModel* vm = itOCC.next()->getViewModel();
3994       if ( !vm || !vm->inherits( "OCCViewer_Viewer" ) )
3995         continue;
3996
3997       OCCViewer_Viewer* occVM = (OCCViewer_Viewer*)vm;
3998       occVM->setZoomingStyle( mode );
3999     }
4000 #endif
4001 #ifndef DISABLE_VTKVIEWER
4002 #ifndef DISABLE_SALOMEOBJECT
4003     viewManagers( SVTK_Viewer::Type(), lst );
4004     QListIterator<SUIT_ViewManager*> itVTK( lst );
4005     while ( itVTK.hasNext() )
4006     {
4007       SUIT_ViewModel* vm = itVTK.next()->getViewModel();
4008       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4009         continue;
4010
4011       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4012       if( vtkVM ) vtkVM->setZoomingStyle( mode );
4013     }
4014 #endif
4015 #endif
4016   }
4017
4018 #ifndef DISABLE_VTKVIEWER
4019   if ( sec == QString( "VTKViewer" ) && (param == QString( "speed_value" ) || param == QString( "speed_mode" )) )
4020   {
4021     int speed = resMgr->integerValue( "VTKViewer", "speed_value", 10 );
4022     int mode = resMgr->integerValue( "VTKViewer", "speed_mode", 0 );
4023     QList<SUIT_ViewManager*> lst;
4024 #ifndef DISABLE_SALOMEOBJECT
4025     viewManagers( SVTK_Viewer::Type(), lst );
4026     QListIterator<SUIT_ViewManager*> it( lst );
4027     while ( it.hasNext() )
4028     {
4029       SUIT_ViewModel* vm = it.next()->getViewModel();
4030       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4031         continue;
4032
4033       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4034       if( vtkVM ) vtkVM->setIncrementalSpeed( speed, mode );
4035     }
4036 #endif
4037   }
4038 #endif
4039
4040 #ifndef DISABLE_VTKVIEWER
4041   if ( sec == QString( "VTKViewer" ) && param == QString( "projection_mode" ) )
4042   {
4043     int mode = resMgr->integerValue( "VTKViewer", "projection_mode", 0 );
4044     QList<SUIT_ViewManager*> lst;
4045 #ifndef DISABLE_SALOMEOBJECT
4046     viewManagers( SVTK_Viewer::Type(), lst );
4047     QListIterator<SUIT_ViewManager*> it( lst );
4048     while ( it.hasNext() )
4049     {
4050       SUIT_ViewModel* vm = it.next()->getViewModel();
4051       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4052         continue;
4053
4054       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4055       if( vtkVM ) vtkVM->setProjectionMode( mode );
4056     }
4057 #endif
4058   }
4059 #endif
4060
4061 #ifndef DISABLE_VTKVIEWER
4062   if ( sec == QString( "VTKViewer" ) && param == QString( "stereo_type" ) )
4063   {
4064     int mode = resMgr->integerValue( "VTKViewer", "stereo_type", 0 );
4065     QList<SUIT_ViewManager*> lst;
4066 #ifndef DISABLE_SALOMEOBJECT
4067     viewManagers( SVTK_Viewer::Type(), lst );
4068     QListIterator<SUIT_ViewManager*> it( lst );
4069     while ( it.hasNext() )
4070     {
4071       SUIT_ViewModel* vm = it.next()->getViewModel();
4072       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4073         continue;
4074
4075       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4076       if( vtkVM ) vtkVM->setStereoType( mode );
4077     }
4078 #endif
4079   }
4080 #endif
4081
4082 #ifndef DISABLE_VTKVIEWER
4083   if ( sec == QString( "VTKViewer" ) && param == QString( "anaglyph_filter" ) )
4084   {
4085     int mode = resMgr->integerValue( "VTKViewer", "anaglyph_filter", 0 );
4086     QList<SUIT_ViewManager*> lst;
4087 #ifndef DISABLE_SALOMEOBJECT
4088     viewManagers( SVTK_Viewer::Type(), lst );
4089     QListIterator<SUIT_ViewManager*> it( lst );
4090     while ( it.hasNext() )
4091     {
4092       SUIT_ViewModel* vm = it.next()->getViewModel();
4093       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4094         continue;
4095
4096       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4097       if( vtkVM ) vtkVM->setAnaglyphFilter( mode );
4098     }
4099 #endif
4100   }
4101 #endif
4102
4103 #ifndef DISABLE_VTKVIEWER
4104   if ( sec == QString( "VTKViewer" ) && param == QString( "enable_quad_buffer_support" ) )
4105   {
4106     int enable = resMgr->booleanValue( "VTKViewer", "enable_quad_buffer_support", false );
4107     QList<SUIT_ViewManager*> lst;
4108 #ifndef DISABLE_SALOMEOBJECT
4109     viewManagers( SVTK_Viewer::Type(), lst );
4110     QListIterator<SUIT_ViewManager*> it( lst );
4111     while ( it.hasNext() )
4112     {
4113       SUIT_ViewModel* vm = it.next()->getViewModel();
4114       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4115         continue;
4116
4117       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4118       if( vtkVM ) vtkVM->setQuadBufferSupport( enable );
4119     }
4120 #endif
4121   }
4122 #endif
4123
4124 #ifndef DISABLE_VTKVIEWER
4125   if ( sec == QString( "VTKViewer" ) && param == QString( "preselection" ) )
4126   {
4127     int mode = resMgr->integerValue( "VTKViewer", "preselection", 0 );
4128     QList<SUIT_ViewManager*> lst;
4129 #ifndef DISABLE_SALOMEOBJECT
4130     viewManagers( SVTK_Viewer::Type(), lst );
4131     QListIterator<SUIT_ViewManager*> it( lst );
4132     while ( it.hasNext() )
4133     {
4134       SUIT_ViewModel* vm = it.next()->getViewModel();
4135       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4136         continue;
4137
4138       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4139       if( vtkVM ) vtkVM->setPreSelectionMode( mode );
4140     }
4141 #endif
4142   }
4143 #endif
4144
4145 #ifndef DISABLE_VTKVIEWER
4146   if ( sec == QString( "VTKViewer" ) && param == QString( "enable_selection" ) )
4147   {
4148     bool isToEnableSelection = resMgr->booleanValue( "VTKViewer", "enable_selection", true );
4149     QList<SUIT_ViewManager*> lst;
4150 #ifndef DISABLE_SALOMEOBJECT
4151     viewManagers( SVTK_Viewer::Type(), lst );
4152     QListIterator<SUIT_ViewManager*> it( lst );
4153     while ( it.hasNext() )
4154     {
4155       SUIT_ViewModel* vm = it.next()->getViewModel();
4156       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4157         continue;
4158
4159       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4160       if( vtkVM ) vtkVM->enableSelection( isToEnableSelection );
4161     }
4162 #endif
4163   }
4164 #endif
4165
4166 #ifndef DISABLE_VTKVIEWER
4167   if ( sec == QString( "VTKViewer" ) && (param == QString( "spacemouse_func1_btn" ) ||
4168                                          param == QString( "spacemouse_func2_btn" ) ||
4169                                          param == QString( "spacemouse_func5_btn" ) ) )
4170   {
4171     int btn1 = resMgr->integerValue( "VTKViewer", "spacemouse_func1_btn", 1 );
4172     int btn2 = resMgr->integerValue( "VTKViewer", "spacemouse_func2_btn", 2 );
4173     int btn3 = resMgr->integerValue( "VTKViewer", "spacemouse_func5_btn", 9 );
4174     QList<SUIT_ViewManager*> lst;
4175 #ifndef DISABLE_SALOMEOBJECT
4176     viewManagers( SVTK_Viewer::Type(), lst );
4177     QListIterator<SUIT_ViewManager*> it( lst );
4178     while ( it.hasNext() )
4179     {
4180       SUIT_ViewModel* vm = it.next()->getViewModel();
4181       if ( !vm || !vm->inherits( "SVTK_Viewer" ) )
4182         continue;
4183
4184       SVTK_Viewer* vtkVM = dynamic_cast<SVTK_Viewer*>( vm );
4185       if( vtkVM ) vtkVM->setSpacemouseButtons( btn1, btn2, btn3 );
4186     }
4187 #endif
4188   }
4189 #endif
4190   if( sec=="ObjectBrowser" )
4191   {
4192     SUIT_DataBrowser* ob = objectBrowser();
4193     if ( !ob )
4194       return;
4195
4196     if ( param=="auto_size_first" )
4197     {
4198       bool autoSizeFirst = resMgr->booleanValue( "ObjectBrowser", "auto_size_first", true );
4199       ob->setAutoSizeFirstColumn( autoSizeFirst );
4200       if ( autoSizeFirst )
4201         ob->adjustFirstColumnWidth();
4202     }
4203     else if ( param=="auto_size" ) {
4204       bool autoSize = resMgr->booleanValue( "ObjectBrowser", "auto_size", false );
4205       ob->setAutoSizeColumns(autoSize);
4206       if ( autoSize )
4207         ob->adjustColumnsWidth();
4208     }
4209     else if ( param=="resize_on_expand_item" ) {
4210       bool resizeOnExpandItem = resMgr->booleanValue( "ObjectBrowser", "resize_on_expand_item", false );
4211       ob->setResizeOnExpandItem(resizeOnExpandItem);
4212     }
4213     else if ( param == "auto_hide_search_tool" ) {
4214       ob->searchTool()->enableAutoHide( resMgr->booleanValue( "ObjectBrowser", "auto_hide_search_tool" ) );
4215     }
4216   }
4217
4218   if( sec=="Study" )
4219   {
4220     if( param=="auto_save_interval" ) {
4221       myAutoSaveTimer->stop();
4222       int autoSaveInterval = resMgr->integerValue( "Study", "auto_save_interval", 0 );
4223       if ( activeStudy() && autoSaveInterval > 0 ) myAutoSaveTimer->start( autoSaveInterval*60000 );
4224     }
4225   }
4226
4227 #ifndef DISABLE_PYCONSOLE
4228   if( sec=="PyConsole" && pythonConsole() )
4229   {
4230     if ( param=="font" ) {
4231       pythonConsole()->setFont( resMgr->fontValue( "PyConsole", "font" ) );
4232     }
4233     else if ( param=="show_banner" ) {
4234       pythonConsole()->setIsShowBanner( resMgr->booleanValue( "PyConsole", "show_banner", true ) );
4235     }
4236     else if ( param=="auto_completion" ) {
4237       pythonConsole()->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) );
4238     }
4239   }
4240 #endif
4241
4242   if( sec=="MRU" )
4243   {
4244     QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4245     if ( mru ) {
4246       if ( param == "visible_count" )
4247         mru->setVisibleCount( resMgr->integerValue( "MRU", "visible_count", 5 ) );    // 5 MRU items by default
4248       else if ( param == "max_count" )
4249         mru->setHistoryCount( resMgr->integerValue( "MRU", "max_count", -1 ) );       // unlimited history by default
4250       else if ( param == "insert_mode" )
4251         mru->setInsertMode( resMgr->integerValue( "MRU", "insert_mode", 0 ) );        // QtxMRUAction::MoveFirst by default
4252       else if ( param == "link_type" )
4253         mru->setLinkType( resMgr->integerValue( "MRU", "link_type", 0 ) );            // QtxMRUAction::LinkAuto by default
4254       else if ( param == "show_clear" )
4255         mru->setClearPossible( resMgr->booleanValue( "MRU", "show_clear", false ) );  // do not show "Clear" item by default
4256       else if ( param == "show_mru" )
4257         mru->setVisible( resMgr->booleanValue( "MRU", "show_mru", false ) );          // do not show MRU menu item by default
4258     }
4259   }
4260   if ( sec == "language" && param == "language" )
4261   {
4262     // VSR 18.06.2015 : commented out : single warning dialog box is now shown by the LightApp_PreferencesDlg
4263     //SUIT_MessageBox::information( desktop(), tr( "WRN_WARNING" ), tr( "LANG_CHANGED" ) );
4264   }
4265   if ( sec == "language" && param == "locale")
4266   {
4267     // VSR 18.06.2015: commented out : single warning dialog box is now shown by the LightApp_PreferencesDlg
4268     //SUIT_MessageBox::information( desktop(), tr( "WRN_WARNING" ), tr( "LOCALE_CHANGED" ) );
4269   }
4270   if ( sec == "desktop" && param == "opaque_resize" ) {
4271     bool opaqueResize = resMgr->booleanValue( "desktop", "opaque_resize", false );
4272     // RNV: This code has been commented, because clearing of the QMainWindow::AnimatedDocks option
4273     //      leads to strange behaviour of the dockable windows (at least at qt-5.6.1):
4274     //      any dockable window can't be docked to the another area, except initial area.
4275     //      It is possible to move window to another area, but it always returns to the initial area.
4276     //
4277     //    QMainWindow::DockOptions dopts = desktop()->dockOptions();
4278     //    if ( opaqueResize ) dopts |= QMainWindow::AnimatedDocks;
4279     //     else                dopts &= ~QMainWindow::AnimatedDocks;
4280     //    desktop()->setDockOptions( dopts );
4281     desktop()->setOpaqueResize( opaqueResize );
4282     if ( dynamic_cast<STD_TabDesktop*>( desktop() ) )
4283       dynamic_cast<STD_TabDesktop*>( desktop() )->workstack()->setOpaqueResize( opaqueResize );
4284   }
4285
4286 #ifndef DISABLE_PLOT2DVIEWER
4287   QList<SUIT_ViewManager*> lst;
4288   viewManagers( Plot2d_Viewer::Type(), lst );
4289   QListIterator<SUIT_ViewManager*> itPlot2d( lst );
4290   while ( itPlot2d.hasNext() ) {
4291     SUIT_ViewManager* viewMgr = itPlot2d.next();
4292     SUIT_ViewModel* vm = viewMgr->getViewModel();
4293     if ( !vm || !vm->inherits( "Plot2d_Viewer" ) )
4294       continue;
4295
4296     //Plot2d_Viewer* Plot2dVM = dynamic_cast<Plot2d_Viewer*>( vm );
4297
4298     viewMgr->setViewModel( vm  );
4299     Plot2d_ViewWindow* wnd = dynamic_cast<Plot2d_ViewWindow*>( viewMgr->getActiveView() );
4300     if( wnd ) {
4301       Plot2d_ViewFrame* frame = wnd->getViewFrame();
4302       frame->SetPreference();
4303     }
4304   }
4305 #endif
4306 }
4307
4308 /*!
4309   Loads preferences
4310 */
4311 void LightApp_Application::loadPreferences()
4312 {
4313   CAM_Application::loadPreferences();
4314
4315   SUIT_ResourceMgr* aResMgr = resourceMgr();
4316
4317   if ( !aResMgr )
4318     return;
4319
4320   static bool mru_load = true;
4321   if ( mru_load )
4322   {
4323     QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4324     if ( mru ) {
4325       mru->setVisible( aResMgr->booleanValue( "MRU", "show_mru", false ) );         // do not show MRU menu item by default
4326       mru->setVisibleCount( aResMgr->integerValue( "MRU", "visible_count", 5 ) );   // 5 MRU items by default
4327       mru->setHistoryCount( aResMgr->integerValue( "MRU", "max_count", -1 ) );      // unlimited history by default
4328       mru->setInsertMode( aResMgr->integerValue( "MRU", "insert_mode", 0 ) );       // QtxMRUAction::MoveFirst by default
4329       mru->setLinkType( aResMgr->integerValue( "MRU", "link_type", 0 ) );           // QtxMRUAction::LinkAuto by default
4330       mru->setClearPossible( aResMgr->booleanValue( "MRU", "show_clear", false ) ); // do not show "Clear" item by default
4331       mru->loadLinks( aResMgr, "MRU" );
4332     }
4333     mru_load = false;
4334   }
4335
4336   myWinVis.clear();
4337   QStringList mods = aResMgr->parameters( "windows_visibility" );
4338   for ( QStringList::const_iterator itr = mods.begin(); itr != mods.end(); ++itr )
4339   {
4340     QByteArray arr;
4341     if ( aResMgr->value( "windows_visibility", *itr, arr ) )
4342       myWinVis.insert( *itr, arr );
4343   }
4344
4345   if ( desktop() ) {
4346     desktop()->retrieveGeometry( aResMgr->stringValue( "desktop", "geometry" ) );
4347     bool opaqueResize = aResMgr->booleanValue( "desktop", "opaque_resize", false );
4348     //    QMainWindow::DockOptions dopts = desktop()->dockOptions();
4349     //    if ( opaqueResize ) dopts |= QMainWindow::AnimatedDocks;
4350     //    else                dopts &= ~QMainWindow::AnimatedDocks;
4351     //    desktop()->setDockOptions( dopts );
4352     desktop()->setOpaqueResize( opaqueResize );
4353     if ( dynamic_cast<STD_TabDesktop*>( desktop() ) )
4354       dynamic_cast<STD_TabDesktop*>( desktop() )->workstack()->setOpaqueResize( opaqueResize );
4355   }
4356 }
4357
4358 /*!
4359   Saves preferences
4360 */
4361 void LightApp_Application::savePreferences()
4362 {
4363   CAM_Application::savePreferences();
4364
4365   saveDockWindowsState();
4366
4367   SUIT_ResourceMgr* aResMgr = resourceMgr();
4368
4369   if ( !aResMgr )
4370     return;
4371
4372   QtxMRUAction* mru = ::qobject_cast<QtxMRUAction*>( action( MRUId ) );
4373   if ( mru )
4374     mru->saveLinks( aResMgr, "MRU" );
4375
4376   for ( WinVis::const_iterator itr = myWinVis.begin(); itr != myWinVis.end(); ++itr )
4377     aResMgr->setValue( "windows_visibility", itr.key(), itr.value() );
4378
4379   if ( desktop() )
4380     aResMgr->setValue( "desktop", "geometry", desktop()->storeGeometry() );
4381
4382 #if GUI_DEVELOPMENT > 0
4383   aResMgr->setValue( "salome", "version", QString(GUI_VERSION_STR)+"dev" );
4384 #else
4385   aResMgr->setValue( "salome", "version", QString(GUI_VERSION_STR) );
4386 #endif
4387
4388   aResMgr->save();
4389 }
4390
4391 /*!
4392   Updates desktop title
4393 */
4394 void LightApp_Application::updateDesktopTitle()
4395 {
4396   QString aTitle = applicationName();
4397   QString aVer = applicationVersion();
4398   if ( !aVer.isEmpty() )
4399     aTitle += QString( " " ) + aVer;
4400
4401   if ( activeStudy() ) {
4402     QString sName = SUIT_Tools::file( activeStudy()->studyName().trimmed(), false );
4403     aTitle += QString( " - [%1]" ).arg( sName );
4404   }
4405
4406   desktop()->setWindowTitle( aTitle );
4407 }
4408
4409 /*!
4410   \brief Get map of the operations which can be performed
4411   on the module activation.
4412
4413   The method should return the map of the kind \c {<id>:<name>}
4414   where \c <id> is an integer identifier of the operation and
4415   \c <name> is a title for the button to be added to the
4416   dialog box. After user selects the required operation by the
4417   clicking the corresponding button in the dialog box, its identifier
4418   is passed to the moduleActionSelected() method to process
4419   the made choice.
4420
4421   \return map of the operations
4422   \sa moduleActionSelected()
4423 */
4424 QMap<int, QString> LightApp_Application::activateModuleActions() const
4425 {
4426   QMap<int, QString> opmap;
4427   opmap.insert( NewStudyId,  tr( "ACTIVATE_MODULE_OP_NEW" ) );
4428   opmap.insert( OpenStudyId, tr( "ACTIVATE_MODULE_OP_OPEN" ) );
4429   return opmap;
4430 }
4431
4432 /*!
4433   \brief Called when the used selectes required operation chosen
4434   from "Activate module" dialog box.
4435
4436   Performs the required operation according to the user choice.
4437
4438   \param id operation identifier
4439   \sa activateModuleActions()
4440 */
4441 void LightApp_Application::moduleActionSelected( const int id )
4442 {
4443   switch ( id ) {
4444   case NewStudyId:
4445     onNewDoc();
4446     break;
4447   case OpenStudyId:
4448     onOpenDoc();
4449     break;
4450   default:
4451     break;
4452   }
4453 }
4454
4455 /*!
4456   Updates windows after close document
4457 */
4458 void LightApp_Application::afterCloseDoc()
4459 {
4460   updateWindows();
4461
4462   CAM_Application::afterCloseDoc();
4463 }
4464
4465 /*!
4466   Updates actions of active module
4467 */
4468 void LightApp_Application::updateModuleActions()
4469 {
4470   emit moduleActivated( activeModule() ? activeModule()->moduleName() : QString() );
4471 }
4472
4473 bool LightApp_Application::checkModule( const QString& title )
4474 {
4475   if ( title.isEmpty() )
4476     return false;
4477
4478   QString library = moduleLibrary( title, true );
4479   if ( library.isEmpty() )
4480     return false;
4481
4482   QString name = moduleName( title );
4483
4484   bool isPyModule = library.contains( "SalomePyQtGUI" ) || library.contains( "SalomePyQtGUILight" );
4485
4486   QStringList paths;
4487 #if defined(WIN32)
4488   paths = QString( Qtx::getenv( "PATH" ) ).split( ";", QString::SkipEmptyParts );
4489 #elif defined(__APPLE__)
4490   paths = QString( Qtx::getenv( "DYLD_LIBRARY_PATH" ) ).split( ":", QString::SkipEmptyParts );
4491 #else
4492   paths = QString( Qtx::getenv( "LD_LIBRARY_PATH" ) ).split( ":", QString::SkipEmptyParts );
4493 #endif
4494
4495   bool isFound = false;
4496   QStringList::const_iterator it;
4497   for ( it = paths.begin(); it != paths.end() && !isFound; ++it )
4498   {
4499     isFound = QFileInfo( Qtx::addSlash( *it ) + library ).exists();
4500   }
4501
4502   if ( !isFound )
4503   {
4504     INFOS( std::endl <<
4505            "****************************************************************" << std::endl <<
4506            "     Warning: library " << qPrintable( library ) << " is not found!" << std::endl <<
4507            "     Module " << qPrintable( title ) << " will not be available in GUI mode!" << std::endl <<
4508            "****************************************************************" << std::endl);
4509     return false;
4510   }
4511
4512   if ( isPyModule )
4513   {
4514     QString pyModule = QString( "%1GUI.py" ).arg( name );
4515 #if defined(WIN32)
4516     paths = QString( Qtx::getenv( "PYTHONPATH" ) ).split( ";", QString::SkipEmptyParts );
4517 #else
4518     paths = QString( Qtx::getenv( "PYTHONPATH" ) ).split( ":", QString::SkipEmptyParts );
4519 #endif
4520     isFound = false;
4521     for ( it = paths.begin(); it != paths.end() && !isFound; ++it )
4522     {
4523       isFound = QFileInfo( Qtx::addSlash( *it ) + pyModule ).exists();
4524     }
4525
4526     if ( !isFound )
4527     {
4528       INFOS( std::endl <<
4529              "****************************************************************" << std::endl <<
4530              "     Warning: Python module " << qPrintable( pyModule ) << " is not found!" << std::endl <<
4531              "     Module " << qPrintable( title ) << " will not be available in GUI mode!" << std::endl <<
4532              "****************************************************************" << std::endl);
4533       return false;
4534     }
4535   }
4536
4537   return true;
4538 }
4539
4540 /*!
4541   Gets current windows.
4542   \param winMap - output current windows map.
4543 */
4544 void LightApp_Application::currentWindows( QMap<int, int>& winMap ) const
4545 {
4546   winMap.clear();
4547   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
4548     ((LightApp_Module*)activeModule())->windows( winMap );
4549   else
4550     defaultWindows( winMap );
4551 }
4552
4553 /*!
4554   Gets current view managers.
4555   \param lst - output current view managers list.
4556 */
4557 void LightApp_Application::currentViewManagers( QStringList& lst ) const
4558 {
4559   lst.clear();
4560   if ( !activeStudy() )
4561     return;
4562
4563   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
4564     ((LightApp_Module*)activeModule())->viewManagers( lst );
4565   else
4566     defaultViewManagers( lst );
4567 }
4568
4569 /*!
4570   Updates windows
4571 */
4572 void LightApp_Application::updateWindows()
4573 {
4574   QMap<int, int> winMap;
4575   currentWindows( winMap );
4576
4577   for ( QMap<int, int>::ConstIterator it = winMap.begin(); it != winMap.end(); ++it )
4578   {
4579     if ( !dockWindow( it.key() ) )
4580       getWindow( it.key() );
4581   }
4582
4583   for ( WinMap::ConstIterator it = myWin.begin(); it != myWin.end(); ++it )
4584   {
4585     QWidget* wid = it.value();
4586     if ( !wid )
4587       continue;
4588     if ( winMap.contains( it.key() ) )
4589       wid->setVisible( true );
4590     else if ( !activeStudy() )
4591       delete wid;
4592     else
4593       wid->setVisible( false );
4594   }
4595
4596   loadDockWindowsState();
4597
4598   if ( !activeModule() && infoPanel() )
4599   {
4600     infoPanel()->clear();
4601     infoPanel()->setTitle( tr( "INFO_WELCOME_TO_SALOME" ) );
4602
4603     int grp = infoPanel()->addGroup( tr( "INFO_GETTING_STARTED" ) );
4604     infoPanel()->addAction( action( FileNewId ), grp );
4605     infoPanel()->addLabel( action( FileNewId )->statusTip(), grp );
4606     infoPanel()->addAction( action( FileOpenId ), grp );
4607     infoPanel()->addLabel( action( FileOpenId )->statusTip(), grp );
4608     if ( HAS_TUTORIAL_URL ) {
4609       infoPanel()->addAction( action( TutorialsId ), grp );
4610       infoPanel()->addLabel( action( TutorialsId )->statusTip(), grp );
4611     }
4612     infoPanel()->addAction( action( VideosId ), grp );
4613     infoPanel()->addLabel( action( VideosId )->statusTip(), grp );
4614
4615     LightApp_ModuleAction* ma = qobject_cast<LightApp_ModuleAction*>(action(ModulesListId));
4616     if ( ma && ma->count() > 0 )
4617     {
4618       grp = infoPanel()->addGroup( tr( "INFO_AVAILABLE_MODULES" ) );
4619       foreach ( QString mname, ma->modules() )
4620       {
4621         infoPanel()->addAction( ma->moduleAction( mname ), grp );
4622         if ( !moduleDescription( mname ).isEmpty() )
4623           infoPanel()->addLabel( moduleDescription( mname ), grp );
4624       }
4625     }
4626   }
4627 }
4628
4629 /*!
4630   Updates view managers
4631 */
4632 void LightApp_Application::updateViewManagers()
4633 {
4634   QStringList lst;
4635   currentViewManagers( lst );
4636
4637   for ( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it )
4638     getViewManager( *it, true );
4639 }
4640
4641 /*!
4642   Loads windows geometry
4643 */
4644 void LightApp_Application::loadDockWindowsState()
4645 {
4646   if ( !desktop() )
4647     return;
4648   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
4649   bool storeWin = aResMgr->booleanValue( "Study", "store_positions", true );
4650   bool storeTb = aResMgr->booleanValue( "Study", "store_tool_positions", true );
4651
4652   QString modName;
4653   if ( activeModule() )
4654     modName = activeModule()->name();
4655   else if ( activeStudy() )
4656     modName = "nomodule";
4657
4658   QtxResourceMgr::WorkingMode prevMode = aResMgr->setWorkingMode( QtxResourceMgr::IgnoreUserValues );
4659   QByteArray aDefaultState;
4660   aResMgr->value( "windows_geometry", modName, aDefaultState );
4661   QByteArray aDefaultVisibility;
4662   aResMgr->value( "windows_visibility", modName, aDefaultVisibility );
4663   bool hasDefaultVisibility = !aDefaultVisibility.isEmpty();
4664   aResMgr->setWorkingMode( prevMode );
4665
4666   if( !storeWin && !storeTb && aDefaultState.isEmpty() && !hasDefaultVisibility)
4667     return;
4668
4669   if ( aResMgr->hasValue("windows_geometry" ,modName ) ) {
4670     long version = Qtx::versionToId( aResMgr->stringValue( "windows_geometry_version", modName, "" ) );
4671     QByteArray arr;
4672     if ( version > Qtx::versionToId( "7.4.1" ) )
4673       aResMgr->value( "windows_geometry", modName , arr );
4674     else
4675       arr = aDefaultState;
4676     QByteArray aTargetArray = processState(arr, storeWin, storeTb, true, aDefaultState);
4677     desktop()->restoreState( aTargetArray );
4678   }
4679
4680   QStringList mainToolbarsNames;
4681   mainToolbarsNames << "SalomeStandard" << "SalomeModules";
4682   QList<QToolBar*> mainToolbars = findToolBars( mainToolbarsNames );
4683   foreach( QToolBar* tb, mainToolbars ) tb->setVisible( true );
4684   /*
4685   if ( !myWinVis.contains( modName ) && aDefaultVisibility.isEmpty())
4686     return;
4687
4688   QMap<QString, bool> *tbMap = 0;
4689   QMap<QString, bool> *dwMap = 0;
4690
4691   QMap<QString, bool> userTbMap, userDwMap;
4692   dockWindowsState( myWinVis[modName], userTbMap, userDwMap );
4693
4694   QMap<QString, bool> defaultTbMap, defaultDwMap;
4695   if(hasDefaultVisibility) {
4696     dockWindowsState( aDefaultVisibility, defaultTbMap, defaultDwMap);
4697   }
4698
4699   if(storeTb) {
4700     tbMap =  &userTbMap;
4701   } else {
4702     if(hasDefaultVisibility){
4703       tbMap =  &defaultTbMap;
4704     }
4705   }
4706
4707   if(storeWin) {
4708     dwMap =  &userDwMap;
4709   } else {
4710     if(hasDefaultVisibility){
4711       dwMap =  &defaultDwMap;
4712     }
4713   }
4714
4715   if(tbMap) {
4716     QList<QToolBar*> tbList = findToolBars();
4717     for ( QList<QToolBar*>::iterator tit = tbList.begin(); tit != tbList.end(); ++tit )
4718       {
4719         QToolBar* tb = *tit;
4720         if ( tbMap->contains( tb->objectName() ) ) {
4721           tb->setVisible( (*tbMap)[tb->objectName()] );
4722         }
4723       }
4724   }
4725
4726   if(dwMap) {
4727     QList<QDockWidget*> dwList = desktop()->findChildren<QDockWidget*>();
4728     for ( QList<QDockWidget*>::iterator dit = dwList.begin(); dit != dwList.end(); ++dit )
4729       {
4730         QDockWidget* dw = *dit;
4731
4732         QObject* po = Qtx::findParent( dw, "QMainWindow" );
4733         if ( po != desktop() )
4734           continue;
4735
4736         if ( dwMap->contains( dw->objectName() ) )
4737           dw->setVisible( (*dwMap)[dw->objectName()] );
4738       }
4739   }
4740   */
4741 }
4742
4743
4744 /*!
4745   Saves windows geometry
4746 */
4747 void LightApp_Application::saveDockWindowsState()
4748 {
4749   if ( !desktop() )
4750     return;
4751
4752   bool storeWin = resourceMgr()->booleanValue( "Study", "store_positions", true );
4753   bool storeTb = resourceMgr()->booleanValue( "Study", "store_tool_positions", true );
4754
4755   if( !storeWin && !storeTb )
4756     return;
4757
4758   QString modName;
4759   if ( activeModule() )
4760     modName = activeModule()->name();
4761   else if ( activeStudy() )
4762     modName = "nomodule";
4763
4764   QString versionId = GUI_VERSION_STR;
4765 #if GUI_DEVELOPMENT > 0
4766   versionId += "dev";
4767 #endif
4768
4769   QByteArray arr = desktop()->saveState();
4770   resourceMgr()->setValue( "windows_geometry", modName, processState(arr, storeWin, storeTb, false) );
4771   resourceMgr()->setValue( "windows_geometry_version", modName, versionId );
4772
4773   QByteArray visArr;
4774   if ( myWinVis.contains( modName ) )
4775     visArr = myWinVis[modName];
4776
4777   QMap<QString, bool> tbMap, dwMap;
4778   dockWindowsState( visArr, tbMap, dwMap );
4779
4780   QList<QToolBar*> tbList = desktop()->findChildren<QToolBar*>();
4781   for ( QList<QToolBar*>::iterator it = tbList.begin(); it != tbList.end(); ++it )
4782   {
4783     QToolBar* tb = *it;
4784     tbMap.insert( tb->objectName(), tb->toggleViewAction()->isChecked() );
4785   }
4786
4787   QList<QDockWidget*> dwList = desktop()->findChildren<QDockWidget*>();
4788   for ( QList<QDockWidget*>::iterator it = dwList.begin(); it != dwList.end(); ++it )
4789   {
4790     QDockWidget* wid = *it;
4791     dwMap.insert( wid->objectName(), wid->toggleViewAction()->isChecked() );
4792   }
4793
4794   visArr = dockWindowsState( tbMap, dwMap );
4795
4796   myWinVis.insert( modName, visArr );
4797 }
4798
4799 QByteArray LightApp_Application::dockWindowsState( const QMap<QString, bool>& tb, const QMap<QString, bool>& dw ) const
4800 {
4801   QByteArray visArr;
4802   QDataStream stream( &visArr, QIODevice::WriteOnly );
4803
4804   stream << (uchar)ToolBarMarker;
4805   stream << tb.size();
4806   for ( QMap<QString, bool>::const_iterator tit = tb.begin(); tit != tb.end(); ++tit )
4807   {
4808     stream << tit.key();
4809     stream << (uchar)( tit.value() ? 1 : 0 );
4810   }
4811
4812   stream << (uchar)DockWidgetMarker;
4813   stream << dw.size();
4814   for ( QMap<QString, bool>::const_iterator wit = dw.begin(); wit != dw.end(); ++wit )
4815   {
4816     stream << wit.key();
4817     stream << (uchar)( wit.value() ? 1 : 0 );
4818   }
4819
4820   return visArr;
4821 }
4822
4823 void LightApp_Application::dockWindowsState( const QByteArray& arr, QMap<QString, bool>& tb, QMap<QString, bool>& dw ) const
4824 {
4825   tb.clear();
4826   dw.clear();
4827
4828   QByteArray visArr = arr;
4829   QDataStream stream( &visArr, QIODevice::ReadOnly );
4830
4831   uchar marker;
4832   stream >> marker;
4833   if ( marker != ToolBarMarker )
4834     return;
4835
4836   int lines;
4837   stream >> lines;
4838   for ( int i = 0; i < lines; ++i )
4839   {
4840     QString objectName;
4841     stream >> objectName;
4842     uchar shown;
4843     stream >> shown;
4844     tb.insert( objectName, shown );
4845   }
4846
4847   stream >> marker;
4848   if ( marker != DockWidgetMarker )
4849     return;
4850
4851   stream >> lines;
4852   for ( int j = 0; j < lines; ++j )
4853   {
4854     QString objectName;
4855     stream >> objectName;
4856     uchar shown;
4857     stream >> shown;
4858     dw.insert( objectName, shown );
4859   }
4860 }
4861
4862 QPixmap LightApp_Application::moduleIcon( const QString& moduleTitle, const int size ) const
4863 {
4864   QPixmap icon;
4865   if ( resourceMgr() )
4866   {
4867     QPixmap defaultIcon = resourceMgr()->loadPixmap( "LightApp", tr( "APP_MODULE_ICO" ), QPixmap( imageEmptyIcon ) );
4868     QString iconName = resourceMgr()->stringValue( moduleName( moduleTitle ), "icon", QString() );
4869     icon = resourceMgr()->loadPixmap( moduleName( moduleTitle ), iconName, defaultIcon );
4870     if ( size > 0 )
4871       icon = Qtx::scaleIcon( icon, size );
4872   }
4873   return icon;
4874 }
4875
4876 /*!
4877   Inserts items in popup, which necessary for current application
4878 */
4879 void LightApp_Application::contextMenuPopup( const QString& type, QMenu* thePopup, QString& title )
4880 {
4881   //Add "Rename" item
4882   LightApp_SelectionMgr* selMgr = LightApp_Application::selectionMgr();
4883   bool cacheIsOn = selMgr->isSelectionCacheEnabled();
4884   selMgr->setSelectionCacheEnabled( true );
4885
4886   SUIT_DataBrowser* ob = objectBrowser();
4887
4888   CAM_Application::contextMenuPopup( type, thePopup, title );
4889
4890   if ( ob && type == ob->popupClientType() ) {
4891     thePopup->addSeparator();
4892     QAction* a = thePopup->addAction( tr( "MEN_REFRESH" ), this, SLOT( onRefresh() ) );
4893     if ( ob->shortcutKey(SUIT_DataBrowser::UpdateShortcut) )
4894       a->setShortcut( ob->shortcutKey(SUIT_DataBrowser::UpdateShortcut) );
4895   }
4896
4897 #ifndef DISABLE_SALOMEOBJECT
4898   if ( selMgr && ob ) {
4899     SALOME_ListIO selected;
4900     selMgr->selectedObjects( selected );
4901     if(selected.Extent() == 1){
4902       Handle(SALOME_InteractiveObject) anIObject = selected.First();
4903       SUIT_DataObject* obj = findObject(anIObject->getEntry());
4904       if(obj && obj->renameAllowed()) {
4905         QAction* a = new QAction(tr("MEN_RENAME_OBJ"), thePopup);
4906         connect( a, SIGNAL( triggered(bool) ), ob, SLOT( onStartEditing() ) );
4907         if ( ob->shortcutKey(SUIT_DataBrowser::RenameShortcut) )
4908           a->setShortcut( ob->shortcutKey(SUIT_DataBrowser::RenameShortcut) );
4909
4910         QList<QAction*> acts = thePopup->actions();
4911         QAction* firstAction = acts.count() > 0 ? acts.first() : 0;
4912         thePopup->insertAction(firstAction,a);
4913       }
4914     }
4915   }
4916 #endif
4917
4918   selMgr->setSelectionCacheEnabled( cacheIsOn );
4919 }
4920
4921 /*!
4922   Create empty study
4923 */
4924 void LightApp_Application::createEmptyStudy()
4925 {
4926   CAM_Application::createEmptyStudy();
4927
4928   if ( objectBrowser() )
4929     objectBrowser()->updateTree();
4930
4931   SUIT_ResourceMgr* aResMgr = SUIT_Session::session()->resourceMgr();
4932   if ( aResMgr && activeStudy() ) {
4933     int autoSaveInterval = aResMgr->integerValue( "Study", "auto_save_interval", 0 );
4934     if ( autoSaveInterval > 0 ) myAutoSaveTimer->start( autoSaveInterval*60000 );
4935   }
4936 }
4937
4938 /*!Set desktop:*/
4939 void LightApp_Application::setDesktop( SUIT_Desktop* desk )
4940 {
4941   CAM_Application::setDesktop( desk );
4942
4943   if ( desk ) {
4944     connect( desk, SIGNAL( message( const QString& ) ),
4945              this, SLOT( onDesktopMessage( const QString& ) ), Qt::UniqueConnection );
4946     connect( desk, SIGNAL( windowActivated( SUIT_ViewWindow* ) ),
4947              this, SLOT( onWindowActivated( SUIT_ViewWindow* ) ), Qt::UniqueConnection );
4948     /* connect( desk, SIGNAL( windowMoved( SUIT_ViewWindow* ) ),
4949              this, SLOT( onWindowMoved( SUIT_ViewWindow* ) ), Qt::UniqueConnection ); */
4950   }
4951 }
4952
4953 /*!
4954   Activates module
4955   \param mod - module to be activated
4956 */
4957 bool LightApp_Application::activateModule( CAM_Module* mod )
4958 {
4959   bool res = CAM_Application::activateModule( mod );
4960
4961   if ( objectBrowser() )
4962     objectBrowser()->updateTree();
4963
4964   return res;
4965 }
4966
4967 /*!
4968   \return keyborad accelerators manager object
4969 */
4970 SUIT_Accel* LightApp_Application::accel() const
4971 {
4972   return myAccel;
4973 }
4974
4975 /*!
4976   Removes dead widget container from map
4977 */
4978 void LightApp_Application::onWCDestroyed( QObject* ob )
4979 {
4980   // remove destroyed widget container from windows map
4981   for ( WinMap::ConstIterator itr = myWin.begin(); itr != myWin.end(); ++itr )
4982   {
4983     if ( itr.value() != ob )
4984       continue;
4985
4986     int key = itr.key();
4987     myWin.remove( key );
4988     break;
4989   }
4990 }
4991
4992 void LightApp_Application::onMRUActivated( const QString& name )
4993 {
4994   SUIT_Session* s = SUIT_Session::session();
4995   if ( s && s->activeApplication() == this )
4996     onOpenDoc( name );
4997 }
4998
4999 void LightApp_Application::onStylePreferences()
5000 {
5001 #ifdef USE_SALOME_STYLE
5002   Style_PrefDlg dlg( desktop() );
5003   dlg.exec();
5004
5005   resourceMgr()->setValue( "Style", "use_salome_style", Style_Salome::isActive() );
5006 #endif // USE_SALOME_STYLE
5007 }
5008
5009 void LightApp_Application::onFullScreen(){
5010   if(myScreenHelper) {
5011     if(desktop()->isFullScreen())
5012       myScreenHelper->switchToNormalScreen();
5013     else
5014       myScreenHelper->switchToFullScreen();
5015   }
5016 }
5017
5018 /*!
5019   Connects just added view manager
5020 */
5021 void LightApp_Application::addViewManager( SUIT_ViewManager* vm )
5022 {
5023   connect( vm, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
5024            this, SLOT( onCloseView( SUIT_ViewManager* ) ) );
5025   CAM_Application::addViewManager( vm );
5026 }
5027
5028 /*!
5029   Remove view manager from memory
5030 */
5031 void LightApp_Application::removeViewManager( SUIT_ViewManager* vm )
5032 {
5033   disconnect( vm, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
5034            this, SLOT( onCloseView( SUIT_ViewManager* ) ) );
5035   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5036   if (aStudy )
5037     aStudy->removeObjectProperties( vm->getGlobalId() );
5038
5039   CAM_Application::removeViewManager( vm );
5040
5041   LightApp_SelectionMgr* selMgr = selectionMgr();
5042   QList<SUIT_Selector*> selectors;
5043   selMgr->selectors( selectors );
5044   foreach( SUIT_Selector* selector, selectors ) {
5045     if ( selector->owner() == vm->getViewModel() ) {
5046       delete selector;
5047     }
5048   }
5049
5050   // IPAL22894: Crash on closing OCC view
5051   //delete vm;
5052   vm->deleteLater();
5053 }
5054
5055 /*!
5056   Renames active window of desktop
5057 */
5058 void LightApp_Application::onRenameWindow()
5059 {
5060   if( !desktop() )
5061     return;
5062
5063   QWidget* w = desktop()->activeWindow();
5064   if( !w )
5065     return;
5066
5067   bool ok;
5068   QString name = QInputDialog::getText( w, tr( "TOT_RENAME" ), tr( "PRP_RENAME" ), QLineEdit::Normal, w->windowTitle(), &ok );
5069   if( ok && !name.isEmpty() )
5070     w->setWindowTitle( name );
5071 }
5072
5073 /*!
5074   Closes active window of desktop
5075 */
5076 void LightApp_Application::onCloseWindow()
5077 {
5078   if( !desktop() )
5079     return;
5080
5081   QWidget* w = desktop()->activeWindow();
5082   if( !w )
5083     return;
5084
5085   w->close();
5086 }
5087
5088 /*!
5089   Closes all windows of desktop
5090 */
5091 void LightApp_Application::onCloseAllWindow()
5092 {
5093   STD_TabDesktop* desk = dynamic_cast<STD_TabDesktop*>( desktop() );
5094   if( !desk )
5095     return;
5096
5097   QList<SUIT_ViewWindow*> wndList = desk->windows();
5098   SUIT_ViewWindow* wnd;
5099   foreach( wnd, wndList )
5100   {
5101     if ( wnd )
5102       wnd->close();
5103   }
5104 }
5105
5106 /*!
5107   Groups all windows of desktop
5108 */
5109 void LightApp_Application::onGroupAllWindow()
5110 {
5111   STD_TabDesktop* desk = dynamic_cast<STD_TabDesktop*>( desktop() );
5112   if( !desk )
5113     return;
5114
5115   QtxWorkstack* wgStack = desk->workstack();
5116   if ( wgStack )
5117     wgStack->stack();
5118 }
5119
5120 /*!
5121   \return default name for an active study
5122 */
5123 void LightApp_Application::setDefaultStudyName( const QString& theName )
5124 {
5125   QStringList anInfoList;
5126   modules( anInfoList, false );
5127
5128   LightApp_Study* aStudy = (LightApp_Study*)activeStudy();
5129   if( anInfoList.count() == 1 && // to avoid a conflict between different modules
5130       !aStudy->isSaved() )
5131   {
5132     aStudy->setStudyName( theName );
5133     updateDesktopTitle();
5134   }
5135 }
5136
5137 /*!
5138   Custom event handler
5139 */
5140 bool LightApp_Application::event( QEvent* e )
5141 {
5142   if( e && e->type()==2000 )
5143   {
5144     SALOME_CustomEvent* ce = ( SALOME_CustomEvent* )e;
5145     QString* d = ( QString* )ce->data();
5146     if( SUIT_MessageBox::question(0, tr("WRN_WARNING"),
5147                                   d ? *d : "",
5148                                   SUIT_MessageBox::Yes | SUIT_MessageBox::No,
5149                                   SUIT_MessageBox::Yes ) == SUIT_MessageBox::Yes )
5150     {
5151       QStringList path;
5152       path << tr( "PREF_CATEGORY_SALOME" ) << tr( "PREF_TAB_GENERAL" )
5153            << tr( "PREF_GROUP_EXT_BROWSER" ) << tr( "PREF_APP" );
5154       showPreferences( path );
5155     }
5156     if( d )
5157       delete d;
5158     return true;
5159   }
5160   return CAM_Application::event( e );
5161 }
5162
5163 /*! Check data object */
5164 bool LightApp_Application::checkDataObject(LightApp_DataObject* theObj)
5165 {
5166   if (theObj)
5167     {
5168       bool isSuitable = !theObj->entry().isEmpty() &&
5169                         !theObj->componentDataType().isEmpty() &&
5170                         !theObj->name().isEmpty();
5171       return isSuitable;
5172     }
5173
5174   return false;
5175 }
5176
5177 int LightApp_Application::openChoice( const QString& aName )
5178 {
5179   int choice = CAM_Application::openChoice( aName );
5180
5181   if ( choice == OpenExist ) // The document is already open.
5182   {
5183     // Do you want to reload it?
5184     if ( SUIT_MessageBox::question( desktop(), tr( "WRN_WARNING" ), tr( "QUE_DOC_ALREADYOPEN" ).arg( aName ),
5185                                     SUIT_MessageBox::Yes | SUIT_MessageBox::No, SUIT_MessageBox::No ) == SUIT_MessageBox::Yes )
5186       choice = OpenReload;
5187   }
5188
5189   return choice;
5190 }
5191
5192 bool LightApp_Application::openAction( const int choice, const QString& aName )
5193 {
5194   bool res = false;
5195   switch ( choice )
5196   {
5197   case OpenReload:
5198     {
5199       STD_Application* app = 0;
5200       SUIT_Session* session = SUIT_Session::session();
5201       QList<SUIT_Application*> appList = session->applications();
5202       for ( QList<SUIT_Application*>::iterator it = appList.begin(); it != appList.end() && !app; ++it )
5203       {
5204         if ( (*it)->activeStudy() && (*it)->activeStudy()->studyName() == aName )
5205           app = ::qobject_cast<STD_Application*>( *it );
5206       }
5207
5208       if ( app )
5209       {
5210         app->onCloseDoc( false );
5211         appList = session->applications();
5212         STD_Application* other = 0;
5213         for ( QList<SUIT_Application*>::iterator it = appList.begin(); it != appList.end() && !other; ++it )
5214           other = ::qobject_cast<STD_Application*>( *it );
5215
5216         if ( other )
5217           res = other->onOpenDoc( aName );
5218       }
5219     }
5220     break;
5221   default:
5222     res = CAM_Application::openAction( choice, aName );
5223     break;
5224   }
5225
5226   return res;
5227 }
5228
5229 QStringList LightApp_Application::viewManagersTypes() const
5230 {
5231   QStringList aTypesList;
5232   aTypesList += myUserWmTypes;
5233 #ifndef DISABLE_GLVIEWER
5234   aTypesList<<GLViewer_Viewer::Type();
5235 #endif
5236 #ifndef DISABLE_PLOT2DVIEWER
5237   aTypesList<<Plot2d_Viewer::Type();
5238 #endif
5239 #ifndef DISABLE_QXGRAPHVIEWER
5240   aTypesList<<QxScene_Viewer::Type();
5241 #endif
5242 #ifndef DISABLE_PVVIEWER
5243   aTypesList<<PVViewer_Viewer::Type();
5244 #endif
5245 #ifndef DISABLE_PYVIEWER
5246   aTypesList<<PyViewer_Viewer::Type();
5247 #endif
5248 #ifndef DISABLE_OCCVIEWER
5249   aTypesList<<OCCViewer_Viewer::Type();
5250 #endif
5251 #ifndef DISABLE_VTKVIEWER
5252  #ifndef DISABLE_SALOMEOBJECT
5253   aTypesList<<SVTK_Viewer::Type();
5254  #else
5255   aTypesList<<VTKViewer_Viewer::Type();
5256  #endif
5257 #endif
5258 #ifndef DISABLE_PV3DVIEWER
5259   aTypesList<<PV3DViewer_ViewModel::Type();
5260 #endif
5261   return aTypesList;
5262 }
5263 /*!
5264  * Removes all view managers of known types
5265  * Other view managers are ignored
5266  */
5267 void LightApp_Application::clearKnownViewManagers()
5268 {
5269   QStringList aTypesList = viewManagersTypes();
5270   QList<SUIT_ViewManager*> aMgrList;
5271   viewManagers( aMgrList );
5272   foreach (SUIT_ViewManager* aMgr, aMgrList) {
5273     if (aTypesList.contains(aMgr->getType()))
5274       removeViewManager(aMgr);
5275   }
5276 }
5277
5278 /*!
5279   Copy of current selection
5280  */
5281 void LightApp_Application::onCopy()
5282 {
5283   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
5284   if( m )
5285     m->copy();
5286 }
5287
5288 /*!
5289   Paste of current data in clipboard
5290  */
5291 void LightApp_Application::onPaste()
5292 {
5293   LightApp_Module* m = dynamic_cast<LightApp_Module*>( activeModule() );
5294   if( m )
5295     m->paste();
5296 }
5297
5298 /*!
5299   Browse (i.e. set focus on) the published objects
5300   \param theIsApplyAndClose - flag indicating that the dialog for creating objects
5301                               has been accepted by Ok (or Apply & Close) button
5302   \param theIsOptimizedBrowsing - flag switching to optimized browsing mode
5303                                   (to select the first published object only)
5304   \return entry of the selected object
5305  */
5306 QString LightApp_Application::browseObjects( const QStringList& theEntryList,
5307                                              const bool theIsApplyAndClose,
5308                                              const bool theIsOptimizedBrowsing )
5309 {
5310   QString aResult;
5311   if( SUIT_ResourceMgr* aResourceMgr = resourceMgr() )
5312   {
5313     int aBrowsePolicy = aResourceMgr->integerValue( "ObjectBrowser", "browse_published_object", (int)BP_Never );
5314     switch( aBrowsePolicy )
5315     {
5316       case BP_Never:
5317         return aResult;
5318       case BP_ApplyAndClose:
5319         if( !theIsApplyAndClose )
5320           return aResult;
5321       case BP_Always:
5322       default:
5323         break;
5324     }
5325   }
5326
5327   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( activeStudy() );
5328   if( !aStudy )
5329     return aResult;
5330
5331   SUIT_DataBrowser* anOB = objectBrowser();
5332   if( !anOB )
5333     return aResult;
5334
5335   SUIT_AbstractModel* aModel = dynamic_cast<SUIT_AbstractModel*>( anOB->model() );
5336   if( !aModel )
5337     return aResult;
5338
5339   QStringListIterator anIter( theEntryList );
5340   if( theIsOptimizedBrowsing )
5341   {
5342     // go to the last entry
5343     anIter.toBack();
5344     if( anIter.hasPrevious() )
5345       anIter.previous();
5346   }
5347
5348   // scroll to each entry in the list
5349   // (in optimized mode - to the last entry only)
5350   QString anEntry;
5351   LightApp_DataObject* anObject = 0;
5352   while( anIter.hasNext() )
5353   {
5354     anEntry = anIter.next();
5355     if( !anEntry.isEmpty() )
5356     {
5357       anObject = aStudy->findObjectByEntry( anEntry );
5358       if( anObject )
5359       {
5360         QModelIndex anIndex = aModel->index( anObject );
5361         anOB->treeView()->scrollTo( anIndex );
5362       }
5363     }
5364   }
5365
5366   // always select the last object
5367   if( anObject && !anEntry.isEmpty() )
5368   {
5369     QList<SUIT_Selector*> aSelectorList;
5370     selectionMgr()->selectors( "ObjectBrowser", aSelectorList );
5371     if( !aSelectorList.isEmpty() )
5372     {
5373       if( LightApp_OBSelector* aSelector = dynamic_cast<LightApp_OBSelector*>( aSelectorList.first() ) )
5374       {
5375         bool anIsAutoBlock = aSelector->autoBlock();
5376
5377         // temporarily disable auto block, to emit LightApp_SelectionMgr::currentSelectionChanged() signal
5378         aSelector->setAutoBlock( false );
5379
5380         SUIT_DataOwnerPtrList aList;
5381 #ifndef DISABLE_SALOMEOBJECT
5382         Handle(SALOME_InteractiveObject) aSObj = new SALOME_InteractiveObject
5383           ( anObject->entry().toUtf8().constData(),
5384             anObject->componentDataType().toLatin1().constData(),
5385             anObject->name().toUtf8().constData() );
5386         LightApp_DataOwner* owner = new LightApp_DataOwner( aSObj  );
5387 #else
5388         LightApp_DataOwner* owner = new LightApp_DataOwner( anEntry );
5389 #endif
5390
5391         aList.append( owner );
5392         selectionMgr()->setSelected( aList );
5393         aResult = anEntry;
5394
5395         // restore auto block flag
5396         aSelector->setAutoBlock( anIsAutoBlock );
5397       }
5398     }
5399   }
5400
5401   return aResult;
5402 }
5403
5404 SUIT_DataObject* LightApp_Application::findObject( const QString& id ) const
5405 {
5406   LightApp_Study* study = dynamic_cast<LightApp_Study*>( activeStudy() );
5407   return study ? study->findObjectByEntry( id ) : 0;
5408 }
5409
5410 /*!
5411   Checks that an object can be renamed.
5412   \param entry entry of the object
5413   \brief Return \c true if object can be renamed
5414 */
5415 bool LightApp_Application::renameAllowed( const QString& /*entry*/) const {
5416   return false;
5417 }
5418
5419 /*!
5420   Rename object by entry.
5421   \param entry entry of the object
5422   \param name new name of the object
5423   \brief Return \c true if rename operation finished successfully, \c false otherwise.
5424 */
5425 bool LightApp_Application::renameObject( const QString& /*entry*/, const QString& /*name*/ ) {
5426   return false;
5427 }
5428
5429 /*! Process standard messages from desktop */
5430 void LightApp_Application::onDesktopMessage( const QString& message )
5431 {
5432   const QString sectionSeparator = "/";
5433
5434   if ( message.toLower() == "updateobjectbrowser" ||
5435        message.toLower() == "updateobjbrowser" ) {
5436     // update object browser
5437     updateObjectBrowser();
5438   }
5439   else if ( message.toLower().startsWith( "activate_viewer" ) ) {
5440     QString vtype = message.split( sectionSeparator ).last();
5441     if ( !vtype.isEmpty() )
5442       getViewManager( vtype, true );
5443   }
5444   else if ( message.toLower().startsWith("register_module_in_study" ) ) {
5445     QString moduleName = message.split( sectionSeparator ).last();
5446     // Check name of current activating module name in order to avoid ciclik
5447     // call because of messages
5448     if (!property("activateModule").toBool()) {
5449       CAM_Module* mod = module(moduleName);
5450       if (!mod)
5451         mod = module(moduleTitle(moduleName));
5452       if (!mod) {
5453         mod = loadModule(moduleName);
5454         if (!mod)
5455           mod = loadModule(moduleTitle(moduleName));
5456         if (mod) {
5457           addModule(mod);
5458         }
5459       }
5460       if (mod) {
5461         CAM_Study* anActiveStudy = dynamic_cast<CAM_Study*>(activeStudy());
5462         if (anActiveStudy) {
5463           mod->connectToStudy(anActiveStudy);
5464           LightApp_DataModel* aDM = dynamic_cast<LightApp_DataModel*>(mod->dataModel());
5465           if(aDM) {
5466             aDM->initRootObject();
5467           }
5468         }
5469       }
5470     }
5471   }
5472   else {
5473     QStringList data = message.split( sectionSeparator );
5474     if ( data.count() > 1 ) {
5475       QString msgType = data[0].trimmed();
5476       LightApp_Module* sMod = 0;
5477       CAM_Module* mod = module( msgType );
5478       if ( !mod )
5479         mod = module( moduleTitle( msgType ) );
5480       if ( mod && mod->inherits( "LightApp_Module" ) )
5481         sMod = (LightApp_Module*)mod;
5482
5483       if ( msgType.toLower() == "preferences" ) {
5484         // requested preferences change: should be given as "preferences/<section>/<name>/<value>"
5485         // for example "preferences/Study/multi_file_dump/true"
5486         if ( data.count() > 3 ) {
5487           QString section = data[1].trimmed();
5488           QString param   = data[2].trimmed();
5489           QString value   = QStringList( data.mid(3) ).join( sectionSeparator );
5490           resourceMgr()->setValue( section, param, value );
5491         }
5492       }
5493       else if ( sMod ) {
5494         // received message for the module
5495         QString msg = QStringList( data.mid(1) ).join( sectionSeparator );
5496         sMod->message( msg );
5497       }
5498     }
5499   }
5500 }
5501
5502 void LightApp_Application::onInfoPanelShown()
5503 {
5504   if ( activeModule() && activeModule()->inherits( "LightApp_Module" ) )
5505     ((LightApp_Module*)activeModule())->updateInfoPanel();
5506 }
5507
5508 /*!
5509   Internal method.
5510   Returns all top level toolbars.
5511   Note : Result list contains only main window toolbars, not including toolbars from viewers.
5512 */
5513 QList<QToolBar*> LightApp_Application::findToolBars( const QStringList& names )
5514 {
5515   QList<QToolBar*> aResult;
5516   QList<QToolBar*> tbList = desktop()->findChildren<QToolBar*>();
5517   for ( QList<QToolBar*>::iterator tit = tbList.begin(); tit != tbList.end(); ++tit ) {
5518     QToolBar* tb = *tit;
5519     QObject* po = Qtx::findParent( tb, "QMainWindow" );
5520     if ( po != desktop() )
5521       continue;
5522     if ( names.isEmpty() || names.contains( tb->objectName() ) )
5523       aResult.append(tb);
5524   }
5525   return aResult;
5526 }
5527
5528 /*!
5529   Internal method to parse toolbars and dockable windows state.
5530 */
5531 QByteArray LightApp_Application::processState(QByteArray& input,
5532                                               const bool processWin,
5533                                               const bool processTb,
5534                                               const bool isRestoring,
5535                                               QByteArray defaultState) {
5536
5537   QByteArray aRes;
5538   bool hasDefaultState  = !defaultState.isEmpty();
5539   bool isDockWinWriten = false;
5540   int nbDocWin = -1;
5541   //Write date from users settings
5542   if(isRestoring){
5543     QDataStream tmpInputData(&input, QIODevice::ReadOnly);
5544     int marker, version;
5545     uchar dockmarker;
5546     tmpInputData >> marker;
5547     tmpInputData >> version;
5548     tmpInputData >> dockmarker;
5549     tmpInputData >> nbDocWin;
5550   }
5551   if(processWin && processTb && !isRestoring) {
5552     aRes = input;
5553   } else if(!processWin && !processTb ) {
5554     if(hasDefaultState)
5555       aRes = defaultState;
5556   } else {
5557     QDataStream aData(&aRes, QIODevice::WriteOnly);
5558     QList<QToolBar*> aToolBars = findToolBars();
5559
5560     QStringList aNames;
5561     for ( QList<QToolBar*>::iterator tit = aToolBars.begin(); tit != aToolBars.end(); ++tit ) {
5562       QToolBar* tb = *tit;
5563       aNames.append(tb->objectName());
5564     }
5565
5566     int toolBarMarkerIndex = getToolbarMarkerIndex(input,aNames);
5567     if(toolBarMarkerIndex < 0)
5568       return aRes;
5569     QDataStream anInputData(&input, QIODevice::ReadOnly);
5570
5571     int toolBarMarkerIndexDef = 0;
5572     if(hasDefaultState) {
5573       toolBarMarkerIndexDef = getToolbarMarkerIndex(defaultState, aNames);
5574       if(toolBarMarkerIndexDef < 0)
5575         return aRes;
5576     }
5577     QDataStream anInputDataDef(&defaultState, QIODevice::ReadOnly);
5578
5579     QDataStream* aTargetData = 0;
5580     int          aTargetIndex = -1;
5581
5582     QByteArray currentArr = desktop()->saveState();
5583     QDataStream anInputDataCur(&currentArr, QIODevice::ReadOnly);
5584     bool useInputData = !isRestoring || (isRestoring && nbDocWin > 0);
5585     if(processWin && useInputData) {
5586       aTargetData = &anInputData;
5587       aTargetIndex = toolBarMarkerIndex;
5588     } else {
5589       //Write date from default settings
5590       if(hasDefaultState) {
5591         aTargetData = &anInputDataDef;
5592         aTargetIndex = toolBarMarkerIndexDef;
5593       } else {
5594         //If no default state, write current snapshot of the dockable windows
5595         if(isRestoring) {
5596           aTargetData = &anInputDataCur;
5597           int toolBarMarkerIndexCur = getToolbarMarkerIndex(currentArr, aNames);
5598           aTargetIndex = toolBarMarkerIndexCur;
5599         }
5600       }
5601     }
5602
5603     if(aTargetData && aTargetIndex >= 0 ) {
5604       aTargetData->device()->seek(0);
5605       while( aTargetData->device()->pos() < aTargetIndex ) {
5606         uchar ch;
5607         *aTargetData >> ch;
5608         aData<<ch;
5609       }
5610       isDockWinWriten = true;
5611     }
5612
5613     aTargetData = 0;
5614     aTargetIndex = -1;
5615
5616     if(processTb) {
5617       aTargetData = &anInputData;
5618       aTargetIndex = toolBarMarkerIndex;
5619     } else {
5620       if(hasDefaultState) {
5621         aTargetData = &anInputDataDef;
5622         aTargetIndex = toolBarMarkerIndexDef;
5623       }
5624     }
5625
5626     if(aTargetData && aTargetIndex >= 0) {
5627       int index;
5628       if(!isDockWinWriten ) {
5629         //Write version marker
5630         int marker, version;
5631         aTargetData->device()->seek(0);
5632         *aTargetData >> marker;
5633         *aTargetData >> version;
5634         aData << marker;
5635         aData << version;
5636         aData << (uchar) QDockWidgetMarker;
5637         aData << (int) 0;
5638         int shift = 4*sizeof(int) + sizeof(QSize);
5639         index = aTargetIndex - shift;
5640       } else {
5641         index = aTargetIndex;
5642       }
5643
5644       aTargetData->device()->seek(index);
5645       while(!aTargetData->atEnd()) {
5646         uchar ch;
5647         *aTargetData >> ch;
5648         aData << ch;
5649       }
5650     } else { // Not treat toolbars
5651       aData << (uchar) QToolBarMarker;
5652       aData << (int) 0; //Nb toolbars = 0
5653     }
5654   }
5655   return aRes;
5656 }
5657
5658 /*!
5659   \brief Emits operationFinished signal.
5660   \param theModuleName the name of the module which perfomed the operation
5661   \param theOperationName the operation name
5662   \param theEntryList the list of the created objects entries
5663 */
5664 void LightApp_Application::emitOperationFinished( const QString& theModuleName,
5665                                                   const QString& theOperationName,
5666                                                   const QStringList& theEntryList )
5667 {
5668   emit operationFinished( theModuleName, theOperationName, theEntryList );
5669 }
5670
5671 /*!
5672   Update visibility state of given objects
5673 */
5674 void LightApp_Application::updateVisibilityState( DataObjectList& theList,
5675                                                   SUIT_ViewModel* theViewModel )
5676 {
5677   if ( !theViewModel || theList.isEmpty() ) return;
5678
5679   LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5680   if ( !aStudy ) return;
5681
5682   SALOME_View* aView = dynamic_cast<SALOME_View*>( theViewModel );
5683
5684   for ( DataObjectList::iterator itr = theList.begin(); itr != theList.end(); ++itr ) {
5685     LightApp_DataObject* obj = dynamic_cast<LightApp_DataObject*>(*itr);
5686
5687     if ( !obj || aStudy->isComponent( obj->entry() ) )
5688       continue;
5689
5690     QString mname = aStudy->componentDataType(obj->entry());
5691     LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(mname, false);
5692     if ( aDisplayer ) {
5693       Qtx::VisibilityState anObjState = Qtx::UnpresentableState;
5694       if ( aDisplayer->canBeDisplayed( obj->entry(), theViewModel->getType() ) ) {
5695         if ( aDisplayer->IsDisplayed( obj->entry(), aView ) )
5696           anObjState = Qtx::ShownState;
5697         else
5698           anObjState = Qtx::HiddenState;
5699       }
5700       aStudy->setVisibilityState( obj->entry(), anObjState );
5701     }
5702   }
5703 }
5704
5705 /*!
5706   Update presentations of all displayed objects of theComponent in specified viewers
5707 */
5708 void LightApp_Application::updatePresentations( const QString& theComponent,
5709                                                 const QStringList& theViewManagerTypes )
5710 {
5711   LightApp_Displayer* aDisplayer = LightApp_Displayer::FindDisplayer(theComponent, false);
5712   if ( aDisplayer ) {
5713     LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>(activeStudy());
5714     DataObjectList aComps;
5715     bool isFound = false;
5716     aStudy->root()->children( aComps );
5717     DataObjectList::const_iterator aCompsIt = aComps.begin();
5718     for ( ; aCompsIt != aComps.end() && !isFound; aCompsIt++ ) {
5719       LightApp_DataObject* aComp = dynamic_cast<LightApp_DataObject*>( *aCompsIt );
5720       if ( aComp && aComp->componentDataType() ==  theComponent) {
5721         isFound = true;
5722         DataObjectList anObjs;
5723         aComp->children(anObjs, true);
5724
5725         QList<SUIT_ViewManager*> aViewMgrs;
5726         QStringList::const_iterator itVMTypes = theViewManagerTypes.begin();
5727         for ( ; itVMTypes != theViewManagerTypes.end(); ++itVMTypes )
5728           viewManagers( *itVMTypes, aViewMgrs );
5729
5730         DataObjectList::const_iterator itObjs = anObjs.begin();
5731         for ( ; itObjs != anObjs.end(); itObjs++ ) {
5732           LightApp_DataObject* anObj = dynamic_cast<LightApp_DataObject*>( *itObjs );
5733           QString anEntry = anObj->entry();
5734
5735           QListIterator<SUIT_ViewManager*> itViewMgrs( aViewMgrs );
5736           while ( itViewMgrs.hasNext()) {
5737             SUIT_ViewModel* aVM = itViewMgrs.next()->getViewModel();
5738             if ( aVM ) {
5739               SALOME_View* aView = dynamic_cast<SALOME_View*>(aVM);
5740               if ( aView ) {
5741                 bool isDisp = aDisplayer->IsDisplayed( anEntry, aView );
5742                 aDisplayer->Erase( anEntry, true, false, aView );
5743                 if ( isDisp ) {
5744                   aDisplayer->Display( anEntry, false, aView );
5745                 }
5746               }
5747             }
5748           }
5749         }
5750       }
5751     }
5752   }
5753 }
5754
5755 /*!
5756  * Called when window activated
5757  */
5758 void LightApp_Application::onWindowActivated( SUIT_ViewWindow* theViewWindow )
5759 {
5760   SUIT_DataBrowser* anOB = objectBrowser();
5761   if ( !anOB )
5762     return;
5763   SUIT_DataObject* rootObj = anOB->root();
5764   if ( !rootObj )
5765     return;
5766
5767   DataObjectList listObj = rootObj->children( true );
5768
5769   SUIT_ViewModel* vmod = 0;
5770   if ( SUIT_ViewManager* vman = theViewWindow->getViewManager() )
5771     vmod = vman->getViewModel();
5772   updateVisibilityState( listObj, vmod );
5773 }
5774
5775 /*!
5776   Called then view manager removed
5777 */
5778 void LightApp_Application::onViewManagerRemoved( SUIT_ViewManager* )
5779 {
5780   ViewManagerList lst;
5781   viewManagers( lst );
5782   if ( lst.count() == 1) { // in case if closed last view window
5783     LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( activeStudy() );
5784     if ( aStudy )
5785       aStudy->setVisibilityStateForAll( Qtx::UnpresentableState );
5786   }
5787 }
5788
5789 /*!
5790   Check existing document.
5791 */
5792 bool LightApp_Application::checkExistingDoc( bool closeExistingDoc )
5793 {
5794   bool result = true;
5795   if( activeStudy() ) {
5796     int answer = !activeStudy()->isModified() ? 1 :
5797                  SUIT_MessageBox::question( desktop(),
5798                                             tr( "APPCLOSE_CAPTION" ),
5799                                             tr( "STUDYCLOSE_DESCRIPTION" ),
5800                                             tr( "APPCLOSE_SAVE" ),
5801                                             tr( "APPCLOSE_CLOSE" ),
5802                                             tr( "APPCLOSE_CANCEL" ), 0 );
5803     if(answer == 0) {
5804       if ( activeStudy()->isSaved() ) {
5805         onSaveDoc();
5806                 if (closeExistingDoc) {
5807                         closeDoc(false);
5808                 }
5809       } else if ( onSaveAsDoc() ) {
5810          if (closeExistingDoc) {
5811            if( !closeDoc( false ) ) {
5812              result = false;
5813            }
5814         }
5815       } else {
5816         result = false;
5817       }
5818     }
5819     else if( answer == 1 ) {
5820       if (closeExistingDoc) {
5821         closeDoc( false );
5822       }
5823     } else if( answer == 2 ) {
5824       result = false;
5825     }
5826   }
5827   return result;
5828 }
5829
5830 #ifndef DISABLE_PYCONSOLE
5831
5832 PyConsole_Interp* LightApp_Application::getPyInterp()
5833 {
5834   static PyConsole_Interp* myInterp = 0;
5835   if ( !myInterp ) {
5836     myInterp = createPyInterp();
5837     myInterp->initialize();
5838   }
5839   return myInterp;
5840 }
5841
5842 PyConsole_Interp* LightApp_Application::createPyInterp()
5843 {
5844   return new PyConsole_Interp();
5845 }
5846
5847 #endif // DISABLE_PYCONSOLE
5848
5849 void LightApp_Application::createHelpItems( const QString& modTitle )
5850 {
5851   if ( modTitle.isEmpty() )
5852     return;
5853
5854   QString userGuide = "User's Guide";
5855   QString devGuide = "Developer's Guide";
5856
5857   int helpMenu = createMenu( tr( "MEN_DESK_HELP" ), -1, -1, 1000 );
5858
5859   createMenu( userGuide, helpMenu, -1, 5 );
5860   createMenu( devGuide, helpMenu, -1, 5 );
5861
5862   IMap <QString, QString> helpData;                                 // list of help files for the module
5863   QString helpSubMenu;                                              // help submenu name (empty if not needed)
5864   QString modName = moduleName( modTitle );                         // module name
5865   if ( modName.isEmpty() ) modName = modTitle;                      // for KERNEL and GUI
5866   QString rootDir = QString( "%1_ROOT_DIR" ).arg( modName );        // module root dir env variable
5867   QString modDir = Qtx::getenv( rootDir.toUtf8().constData() );     // module root dir path
5868   QString docSection;
5869   if ( resourceMgr()->hasValue( modName, "documentation" ) )
5870     docSection = resourceMgr()->stringValue( modName, "documentation" );
5871   else if ( resourceMgr()->hasSection( modName + "_documentation" ) )
5872     docSection = modName + "_documentation";
5873   if ( !docSection.isEmpty() )
5874   {
5875     helpSubMenu = resourceMgr()->stringValue( docSection, "sub_menu", "" );
5876     if ( helpSubMenu.contains( "%1" ) )
5877       helpSubMenu = helpSubMenu.arg( modTitle );
5878     foreach( QString paramName, resourceMgr()->parameters( docSection ) )
5879     {
5880       QString key = paramName.contains( "%1" ) ? paramName.arg( modTitle ) : paramName;
5881       QString helpItem = getHelpItem( docSection, paramName );
5882       if ( !helpItem.isEmpty() )
5883         helpData.insert( key, helpItem );
5884     }
5885   }
5886
5887   if ( helpData.isEmpty() && !modDir.isEmpty() )
5888   {
5889     QStringList idxLst = QStringList() << modDir << "share" << "doc" << "salome" << "gui" << modName << "index.html";
5890     QString indexFile = idxLst.join( QDir::separator() );          // index file
5891     if ( QFile::exists( indexFile ) )
5892       helpData.insert( tr( "%1 module Users's Guide" ).arg( modTitle ), indexFile );
5893   }
5894
5895   IMapConstIterator<QString, QString > fileIt;
5896   for ( fileIt = helpData.begin(); fileIt != helpData.end(); fileIt++ )
5897   {
5898     QString helpItemPath = fileIt.key();
5899     // remove all '//' occurances
5900     while ( helpItemPath.contains( "//" ) )
5901       helpItemPath.replace( "//", "" );
5902     // obtain submenus hierarchy if given
5903     QStringList smenus = helpItemPath.split( "/" );
5904     helpItemPath = smenus.takeLast();
5905     // workaround for User's Guide and Developer's Guide to avoid having single item in module's submenu.
5906     if ( helpItemPath == userGuide || helpItemPath == devGuide )
5907     {
5908       QString menuPath = smenus.join( "/" );
5909       QStringList allKeys = helpData.keys();
5910       QStringList total = allKeys.filter( QRegExp( QString( "^%1" ).arg( menuPath ) ) );
5911       if ( total.count() == 1 && smenus.count() > 0 )
5912         helpItemPath = smenus.takeLast();
5913     }
5914     QPixmap helpIcon = fileIt.value().startsWith( "http", Qt::CaseInsensitive ) ?
5915       resourceMgr()->loadPixmap( "STD", tr( "ICON_WWW" ), false ) :
5916       resourceMgr()->loadPixmap( "STD", tr( "ICON_HELP" ), false );
5917     QAction* a = createAction( -1, helpItemPath, helpIcon, helpItemPath, helpItemPath,
5918                                0, desktop(), false, this, SLOT( onHelpContentsModule() ) );
5919     a->setData( fileIt.value() );
5920     if ( !helpSubMenu.isEmpty() )
5921       smenus.prepend( helpSubMenu );
5922     // create sub-menus hierarchy
5923     int menuId = helpMenu;
5924     foreach ( QString subMenu, smenus )
5925       menuId = createMenu( subMenu, menuId, -1, 5 );
5926     createMenu( a, menuId, -1, ( menuId != helpMenu && ( helpItemPath == userGuide || helpItemPath == devGuide ) ) ? 0 : 5 );
5927     if ( !myHelpItems.contains( modName ) )
5928       myHelpItems[modName] = IdList();
5929     myHelpItems[modName].append( actionId( a ) );
5930   }
5931 }
5932
5933 void LightApp_Application::removeHelpItems( const QString& modTitle )
5934 {
5935   QString modName = moduleName( modTitle );
5936   if ( myHelpItems.contains( modName ) )
5937   {
5938     foreach( int id, myHelpItems[modName] )
5939       setMenuShown( id, false );
5940     myHelpItems.remove( modName );
5941   }
5942 }