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