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