0029195: OCAF - ensure thread safety for different documents.
[occt.git] / tools / DFBrowser / DFBrowser_Window.cxx
1 // Created on: 2017-06-16
2 // Created by: Natalia ERMOLAEVA
3 // Copyright (c) 2017 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement. 
15
16 #include <inspector/DFBrowser_Window.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <AIS_InteractiveObject.hxx>
20 #include <AIS_ListOfInteractive.hxx>
21
22 #include <CDF_Session.hxx>
23
24 #include <inspector/DFBrowserPane_AttributePaneAPI.hxx>
25
26 #include <inspector/DFBrowser_AttributePaneStack.hxx>
27 #include <inspector/DFBrowser_AttributePaneType.hxx>
28 #include <inspector/DFBrowser_DumpView.hxx>
29 #include <inspector/DFBrowser_Item.hxx>
30 #include <inspector/DFBrowser_ItemApplication.hxx>
31 #include <inspector/DFBrowser_Module.hxx>
32 #include <inspector/DFBrowser_OpenApplication.hxx>
33 #include <inspector/DFBrowser_PropertyPanel.hxx>
34 #include <inspector/DFBrowser_SearchLine.hxx>
35 #include <inspector/DFBrowser_SearchView.hxx>
36 #include <inspector/DFBrowser_Thread.hxx>
37 #include <inspector/DFBrowser_ThreadItemSearch.hxx>
38 #include <inspector/DFBrowser_Tools.hxx>
39 #include <inspector/DFBrowser_TreeLevelLine.hxx>
40 #include <inspector/DFBrowser_TreeLevelView.hxx>
41 #include <inspector/DFBrowser_TreeModel.hxx>
42
43 #include <inspector/DFBrowserPane_AttributePaneSelector.hxx>
44 #include <inspector/DFBrowserPane_SelectionKind.hxx>
45 #include <inspector/DFBrowserPane_Tools.hxx>
46
47 #include <inspector/TreeModel_ContextMenu.hxx>
48 #include <inspector/TreeModel_Tools.hxx>
49
50 #include <inspector/ViewControl_PropertyView.hxx>
51 #include <inspector/ViewControl_TreeView.hxx>
52
53 #include <OSD_Directory.hxx>
54 #include <OSD_Environment.hxx>
55 #include <OSD_Protection.hxx>
56 #include <OSD_Thread.hxx>
57 #include <inspector/View_Displayer.hxx>
58 #include <inspector/View_ToolBar.hxx>
59 #include <inspector/View_Viewer.hxx>
60 #include <inspector/View_Window.hxx>
61
62 #include <TDF_Tool.hxx>
63 #include <inspector/ViewControl_MessageDialog.hxx>
64 #include <inspector/ViewControl_Tools.hxx>
65
66 #include <Standard_WarningsDisable.hxx>
67 #include <Standard_ThreadId.hxx>
68 #include <QAction>
69 #include <QApplication>
70 #include <QComboBox>
71 #include <QDir>
72 #include <QDockWidget>
73 #include <QGridLayout>
74 #include <QList>
75 #include <QMainWindow>
76 #include <QItemSelectionModel>
77 #include <QTabWidget>
78 #include <QToolBar>
79 #include <QTreeView>
80 #include <QMenu>
81 #include <QMessageBox>
82 #include <QStatusBar>
83 #include <QWidget>
84 #if QT_VERSION < 0x050000
85 #include <QWindowsStyle>
86 #else
87 #include <QStyleFactory>
88 #endif
89 #include <Standard_WarningsRestore.hxx>
90
91 const int DFBROWSER_DEFAULT_WIDTH = 650;
92 const int DFBROWSER_DEFAULT_HEIGHT = 350;
93 const int DFBROWSER_DEFAULT_TREE_VIEW_WIDTH = 325;
94 const int DFBROWSER_DEFAULT_TREE_VIEW_HEIGHT = 500;
95 const int DFBROWSER_DEFAULT_VIEW_WIDTH = 400;
96 const int DFBROWSER_DEFAULT_VIEW_HEIGHT = 300;
97
98 const int DFBROWSER_DEFAULT_POSITION_X = 200;
99 const int DFBROWSER_DEFAULT_POSITION_Y = 60;
100
101 const int DEFAULT_PROPERTY_PANEL_HEIGHT = 200;
102 const int DEFAULT_BROWSER_HEIGHT = 800;
103
104 //#define USE_DUMPJSON
105
106 // =======================================================================
107 // function : Constructor
108 // purpose :
109 // =======================================================================
110 DFBrowser_Window::DFBrowser_Window()
111 : myModule (0), myParent (0), myPropertyPanel (0), myExportToShapeViewDialog (0)
112 {
113   myMainWindow = new QMainWindow (0);
114
115   // tree view
116   myTreeView = new ViewControl_TreeView (myMainWindow);
117   myTreeView->setContextMenuPolicy (Qt::CustomContextMenu);
118   connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)),
119            this, SLOT (onTreeViewContextMenuRequested (const QPoint&)));
120   new TreeModel_ContextMenu (myTreeView);
121   ((ViewControl_TreeView*)myTreeView)->SetPredefinedSize (QSize (DFBROWSER_DEFAULT_TREE_VIEW_WIDTH,
122                                                                  DFBROWSER_DEFAULT_TREE_VIEW_HEIGHT));
123   myTreeView->setHeaderHidden (true);
124   myTreeView->setSortingEnabled (Standard_False);
125   myMainWindow->setCentralWidget (myTreeView);
126
127 #if QT_VERSION < 0x050000
128   myTreeView->setStyle (new QWindowsStyle);
129 #else
130   myTreeView->setStyle (QStyleFactory::create("Windows"));
131 #endif
132
133   myTreeLevelLine = new DFBrowser_TreeLevelLine (myMainWindow);
134   connect (myTreeLevelLine->GetSearchLine(), SIGNAL (searchActivated()), this, SLOT (onSearchActivated()));
135   connect (myTreeLevelLine, SIGNAL (indexSelected (const QModelIndex&)),
136           this, SLOT (onTreeLevelLineSelected (const QModelIndex&)));
137   connect (myTreeLevelLine, SIGNAL (updateClicked()), this, SLOT (onUpdateClicked()));
138
139   QDockWidget* aTreeLineDockWidget = new QDockWidget (tr ("Tree Level Line"), myMainWindow);
140   aTreeLineDockWidget->setObjectName (aTreeLineDockWidget->windowTitle());
141   aTreeLineDockWidget->setTitleBarWidget (new QWidget(myMainWindow));
142   aTreeLineDockWidget->setWidget (myTreeLevelLine->GetControl());
143   myMainWindow->addDockWidget (Qt::TopDockWidgetArea, aTreeLineDockWidget);
144
145   // property panel
146   myPropertyPanel = new DFBrowser_PropertyPanel (myMainWindow);
147   DFBrowser_AttributePaneStack* anAttributePaneStack = myPropertyPanel->GetAttributesStack();
148   anAttributePaneStack->GetSearchView()->SetSearchLine (myTreeLevelLine->GetSearchLine());
149
150   connect (anAttributePaneStack->GetPaneSelector(),
151            SIGNAL (tableSelectionChanged (const QItemSelection&, const QItemSelection&, QItemSelectionModel*)),
152            this, SLOT (onPaneSelectionChanged (const QItemSelection&, const QItemSelection&, QItemSelectionModel*)));
153
154   DFBrowser_SearchView* aSearchView = anAttributePaneStack->GetSearchView();
155   connect (aSearchView, SIGNAL (pathSelected (const QStringList&, const QString&)),
156            this, SLOT (onSearchPathSelected (const QStringList&, const QString&)));
157   connect (aSearchView, SIGNAL (pathDoubleClicked (const QStringList&, const QString&)),
158            this, SLOT (onSearchPathDoubleClicked (const QStringList&, const QString&)));
159
160   DFBrowser_TreeLevelView* aLevelView = anAttributePaneStack->GetTreeLevelView();
161   connect (aLevelView, SIGNAL (indexSelected (const QModelIndex&)), this, SLOT (onLevelSelected (const QModelIndex&)));
162   connect (aLevelView, SIGNAL (indexDoubleClicked (const QModelIndex&)),
163            this, SLOT (onLevelDoubleClicked (const QModelIndex&)));
164
165   // property widget
166   QDockWidget* aPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow);
167   aPropertyPanelWidget->setObjectName (aPropertyPanelWidget->windowTitle());
168   aPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
169   aPropertyPanelWidget->setWidget (myPropertyPanel->GetControl());
170   myMainWindow->addDockWidget (Qt::RightDockWidgetArea, aPropertyPanelWidget);
171
172   // property view
173 #ifdef USE_DUMPJSON
174   myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel (DumpJson)"), myMainWindow);
175   myPropertyView = new ViewControl_PropertyView (myMainWindow,
176     QSize(DFBROWSER_DEFAULT_VIEW_WIDTH, DFBROWSER_DEFAULT_VIEW_HEIGHT));
177   myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle());
178   myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
179   myPropertyPanelWidget->setWidget (myPropertyView->GetControl());
180   myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget);
181 #endif
182
183   // dump view window
184   QWidget* aDumpWidget = new QWidget(myMainWindow);
185   QVBoxLayout* aDumpLay = new QVBoxLayout(aDumpWidget);
186   aDumpLay->setMargin(0);
187   myDumpView = new DFBrowser_DumpView(aDumpWidget);
188   aDumpLay->addWidget(myDumpView->GetControl());
189   QDockWidget* aDumpDockWidget = new QDockWidget(tr("Dump"), myMainWindow);
190   aDumpDockWidget->setObjectName(aDumpDockWidget->windowTitle());
191
192   aDumpDockWidget->setWidget(aDumpWidget);
193   myMainWindow->addDockWidget(Qt::RightDockWidgetArea, aDumpDockWidget);
194
195   // view
196   myViewWindow = new View_Window (myMainWindow);
197   myViewWindow->SetPredefinedSize (DFBROWSER_DEFAULT_VIEW_WIDTH, DFBROWSER_DEFAULT_VIEW_HEIGHT);
198
199   QDockWidget* aViewDockWidget = new QDockWidget (tr ("View"), myMainWindow);
200   aViewDockWidget->setObjectName (aViewDockWidget->windowTitle());
201   aViewDockWidget->setTitleBarWidget (myViewWindow->ViewToolBar()->GetControl());
202   aViewDockWidget->setWidget (myViewWindow);
203   myMainWindow->addDockWidget (Qt::RightDockWidgetArea, aViewDockWidget);
204
205   QColor aHColor (229, 243, 255);
206   myViewWindow->Displayer()->SetAttributeColor (Quantity_Color(aHColor.red() / 255., aHColor.green() / 255.,
207                                                 aHColor.blue() / 255., Quantity_TOC_sRGB), View_PresentationType_Additional);
208
209   myMainWindow->splitDockWidget (aPropertyPanelWidget, aViewDockWidget, Qt::Vertical);
210
211 #ifdef USE_DUMPJSON
212   myMainWindow->tabifyDockWidget (aDumpDockWidget, myPropertyPanelWidget);
213   myMainWindow->tabifyDockWidget (myPropertyPanelWidget, aViewDockWidget);
214 #else
215   myMainWindow->tabifyDockWidget (aDumpDockWidget, aViewDockWidget);
216 #endif
217
218   myTreeView->resize (DFBROWSER_DEFAULT_TREE_VIEW_WIDTH, DFBROWSER_DEFAULT_TREE_VIEW_HEIGHT);
219
220   myThread = new DFBrowser_Thread (this);
221 }
222
223 // =======================================================================
224 // function : Destructor
225 // purpose :
226 // =======================================================================
227 DFBrowser_Window::~DFBrowser_Window()
228 {
229   delete myModule;
230 }
231
232 // =======================================================================
233 // function : SetParent
234 // purpose :
235 // =======================================================================
236 void DFBrowser_Window::SetParent (void* theParent)
237 {
238   myParent = (QWidget*)theParent;
239   if (myParent)
240   {
241     QLayout* aLayout = myParent->layout();
242     if (aLayout)
243       aLayout->addWidget (GetMainWindow());
244
245     if (!myOpenedFileName.isEmpty())
246       myParent->setObjectName(myOpenedFileName);
247   }
248 }
249
250 // =======================================================================
251 // function : FillActionsMenu
252 // purpose :
253 // =======================================================================
254 void DFBrowser_Window::FillActionsMenu (void* theMenu)
255 {
256   QMenu* aMenu = (QMenu*)theMenu;
257   QList<QDockWidget*> aDockwidgets = myMainWindow->findChildren<QDockWidget*>();
258   for (QList<QDockWidget*>::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it)
259   {
260     QDockWidget* aDockWidget = *it;
261     if (aDockWidget->parentWidget() == myMainWindow)
262       aMenu->addAction (aDockWidget->toggleViewAction());
263   }
264 }
265
266 // =======================================================================
267 // function : GetPreferences
268 // purpose :
269 // =======================================================================
270 void DFBrowser_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem)
271 {
272   theItem.Bind ("geometry",  TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str());
273
274   QMap<QString, QString> anItems;
275   TreeModel_Tools::SaveState (myTreeView, anItems);
276   View_Window::SaveState(myViewWindow, anItems);
277
278   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
279     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
280 }
281
282 // =======================================================================
283 // function : SetPreferences
284 // purpose :
285 // =======================================================================
286 void DFBrowser_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem)
287 {
288   if (theItem.IsEmpty())
289   {
290     TreeModel_Tools::SetDefaultHeaderSections (myTreeView);
291     return;
292   }
293
294   for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next())
295   {
296     if (anItemIt.Key().IsEqual ("geometry"))
297       myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemIt.Value().ToCString()));
298     else if (TreeModel_Tools::RestoreState (myTreeView, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
299       continue;
300     else if (View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
301       continue;
302   }
303 }
304
305 // =======================================================================
306 // function : UpdateContent
307 // purpose :
308 // =======================================================================
309 void DFBrowser_Window::UpdateContent()
310 {
311   TCollection_AsciiString aName = "TKDFBrowser";
312
313   if (myParameters->FindParameters (aName))
314     Init(myParameters->Parameters (aName));
315   else
316     Init(NCollection_List<Handle(Standard_Transient)>());
317
318   if (myParameters->FindFileNames(aName))
319   {
320     NCollection_List<TCollection_AsciiString> aFileNames = myParameters->FileNames (aName);
321     if (aFileNames.Extent() > 0) // only one document file might be opened
322       OpenFile (aFileNames.First());
323     myParameters->SetFileNames(aName, NCollection_List<TCollection_AsciiString>());
324   }
325   onUpdateClicked();
326
327   // make parameter items selected if defined
328   if (myParameters->FindSelectedNames(aName))
329   {
330     const NCollection_List<TCollection_AsciiString>& aSelected = myParameters->GetSelectedNames (aName);
331
332     DFBrowser_TreeModel* aTreeModel = dynamic_cast<DFBrowser_TreeModel*> (myTreeView->model());
333     Handle(TDocStd_Application) anApplication = aTreeModel->GetTDocStdApplication();
334
335     QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
336     aSelectionModel->clear();
337
338     NCollection_List<TCollection_AsciiString>::Iterator aSelectedIt (aSelected);
339     if (aSelectedIt.More())
340     {
341       TCollection_AsciiString aLabelEntry = aSelectedIt.Value();
342
343       TDF_Label aLabel;
344       for (Standard_Integer aDocId = 1, aNbDoc = anApplication->NbDocuments(); aDocId <= aNbDoc; aDocId++)
345       {
346         Handle(TDocStd_Document) aDocument;
347         anApplication->GetDocument (aDocId, aDocument);
348
349         TDF_Tool::Label(aDocument->GetData(), aLabelEntry.ToCString(), aLabel, Standard_False);
350         if (!aLabel.IsNull())
351           break;
352       }
353       if (!aLabel.IsNull())
354       {
355         QModelIndex anIndexToBeSelected = aTreeModel->FindIndex (aLabel);
356
357         TCollection_AsciiString anAttributeType;
358         aSelectedIt.Next();
359         // find attribute by attribute type on the given label
360         if  (aSelectedIt.More())
361         {
362           anAttributeType = aSelectedIt.Value();
363
364           TreeModel_ItemBasePtr aLabelItem = TreeModel_ModelBase::GetItemByIndex (anIndexToBeSelected);
365           //DFBrowser_ItemPtr anItem = itemDynamicCast<DFBrowser_Item> (anItemBase);
366           for (int aChildId = 0, aNbChildren = aLabelItem->rowCount(); aChildId < aNbChildren; aChildId++)
367           {
368             QModelIndex anIndex = aTreeModel->index (aChildId, 0, anIndexToBeSelected);
369             TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
370             DFBrowser_ItemPtr anItem = itemDynamicCast<DFBrowser_Item> (anItemBase);
371             if (anItem->HasAttribute())
372             {
373               // processing attribute in theValue
374               DFBrowser_ItemApplicationPtr aRootAppItem = itemDynamicCast<DFBrowser_ItemApplication>(aTreeModel->RootItem (0));
375               QString anAttributeInfo = DFBrowser_Module::GetAttributeInfo (anItem->GetAttribute(), aRootAppItem->GetModule(),
376                                                       Qt::DisplayRole, 0).toString();
377               if (anAttributeInfo == anAttributeType.ToCString())
378               {
379                 anIndexToBeSelected = anIndex;
380                 break;
381               }
382             }
383           }
384         }
385         aSelectionModel->select (anIndexToBeSelected, QItemSelectionModel::Select);
386         myTreeView->scrollTo (anIndexToBeSelected);
387       }
388     }
389
390     myParameters->SetSelectedNames(aName, NCollection_List<TCollection_AsciiString>());
391   }
392 }
393
394 // =======================================================================
395 // function : Init
396 // purpose :
397 // =======================================================================
398 void DFBrowser_Window::Init (const NCollection_List<Handle(Standard_Transient)>& theParameters)
399 {
400   Handle(TDocStd_Application) anApplication;
401   if (myModule)
402   {
403     DFBrowser_TreeModel* anOCAFViewModel = dynamic_cast<DFBrowser_TreeModel*> (myModule->GetOCAFViewModel());
404     if (anOCAFViewModel)
405       anApplication = anOCAFViewModel->GetTDocStdApplication();
406   }
407   Handle(AIS_InteractiveContext) aContext;
408   if (myModule)
409     aContext = myModule->GetExternalContext();
410
411   bool aSameApplication = !anApplication.IsNull(), aSameContext = !aContext.IsNull();
412   for (NCollection_List<Handle(Standard_Transient)>::Iterator aParametersIt (theParameters);
413        aParametersIt.More(); aParametersIt.Next())
414   {
415     Handle(Standard_Transient) anObject = aParametersIt.Value();
416     // check if the object is an application
417     Handle(TDocStd_Application) anIApplication = Handle(TDocStd_Application)::DownCast (anObject);
418     if (!anIApplication.IsNull())
419     {
420       aSameApplication = anApplication == anIApplication;
421       if (!aSameApplication)
422         anApplication = anIApplication;
423     }
424     // check if the object is an interactive context
425     Handle(AIS_InteractiveContext) anIContext = Handle(AIS_InteractiveContext)::DownCast (anObject);
426     if (!anIContext.IsNull())
427     {
428       aSameContext = aContext == anIContext;
429       if (!aSameContext)
430         aContext = anIContext;
431     }
432   }
433   if (aSameApplication)
434   {
435     if (!aSameContext && !aContext.IsNull())
436     {
437       myModule->SetExternalContext (aContext);
438       myViewWindow->SetContext (View_ContextType_External, aContext);
439     }
440     return;
441   }
442   else
443   {
444     if (anApplication.IsNull() && CDF_Session::Exists()) {
445       Standard_ThreadId anID = OSD_Thread::Current();
446       Handle(CDF_Application) anApp;
447       CDF_Session::CurrentSession()->FindApplication(anID, anApp);
448       anApplication = Handle(TDocStd_Application)::DownCast (anApp);
449     }
450   }
451
452   myModule = new DFBrowser_Module();
453   myModule->CreateViewModel (myMainWindow);
454
455   myPropertyPanel->GetAttributesStack()->SetModule (myModule);
456
457   // model should be set after the attribute pane stack is initialized by module
458   QAbstractItemModel* aModel = myModule->GetOCAFViewModel();
459   setOCAFModel (aModel);
460   myModule->SetOCAFViewSelectionModel (myTreeView->selectionModel());
461   myTreeLevelLine->GetSearchLine()->SetModule (myModule);
462   myPropertyPanel->GetAttributesStack()->GetSearchView()->InitModels();
463
464   connect (myModule, SIGNAL (beforeUpdateTreeModel()), this, SLOT (onBeforeUpdateTreeModel()));
465
466   if (!aContext.IsNull())
467   {
468     myModule->SetExternalContext (aContext);
469     myViewWindow->SetContext (View_ContextType_External, aContext);
470   }
471
472   myModule->SetApplication (anApplication);
473   //! expand first three levels: CUSTOM
474   QModelIndex aParentIndex = aModel->index (0, 0);
475   setExpandedLevels (myTreeView, aParentIndex, 3/*levels*/);
476
477   myThread->ProcessApplication();
478   myModule->SetInitialTreeViewSelection();
479 }
480
481 // =======================================================================
482 // function : OpenFile
483 // purpose :
484 // =======================================================================
485 void DFBrowser_Window::OpenFile (const TCollection_AsciiString& theFileName)
486 {
487   QApplication::setOverrideCursor (Qt::WaitCursor);
488   myThread->TerminateThread();
489
490   myTreeLevelLine->ClearHistory();
491   QItemSelectionModel* aSelectionModel = myModule->GetOCAFViewSelectionModel();
492   if (aSelectionModel)
493   {
494     aSelectionModel->clearSelection();
495     QModelIndex anIndex;
496     aSelectionModel->select (anIndex, QItemSelectionModel::ClearAndSelect);
497   }
498   ClearThreadCache();
499
500   myTreeLevelLine->ClearHistory();
501
502   DFBrowser_TreeModel* anOCAFViewModel = dynamic_cast<DFBrowser_TreeModel*> (myModule->GetOCAFViewModel());
503   anOCAFViewModel->Reset();
504
505   //! close previous documents to open new document
506   Handle(TDocStd_Application) anApplication;
507   if (CDF_Session::Exists())
508   {
509     Handle(CDF_Session) aSession = CDF_Session::CurrentSession();
510     if (!aSession.IsNull())
511     {
512       Standard_ThreadId anID = OSD_Thread::Current();
513       Handle(CDF_Application) anApp;
514       CDF_Session::CurrentSession()->FindApplication(anID, anApp);
515       anApplication = Handle(TDocStd_Application)::DownCast (anApp);
516       if (!anApplication.IsNull())
517       {
518         for (int aDocId = 1, aNbDocuments = anApplication->NbDocuments(); aDocId <= aNbDocuments; aDocId++)
519         {
520           Handle(TDocStd_Document) aDocument;
521           anApplication->GetDocument (aDocId, aDocument);
522           if (!aDocument.IsNull())
523             anApplication->Close (aDocument);
524         }
525       }
526     }
527   }
528   //! open new document
529   bool isSTEPFileName = false;
530   anApplication = DFBrowser_OpenApplication::OpenApplication (theFileName, isSTEPFileName);
531   
532   if (myParent)
533     myParent->setObjectName (isSTEPFileName ? QString (TCollection_AsciiString (theFileName).ToCString()) : getWindowTitle());
534   else
535     myOpenedFileName = isSTEPFileName ? QString(TCollection_AsciiString(theFileName).ToCString()) : getWindowTitle();
536
537   if (anApplication.IsNull())
538   {
539     QApplication::restoreOverrideCursor();
540     QMessageBox::information (0, "Error", QString ("File %1 can't be opened by OCAF application")
541                                                    .arg(TCollection_AsciiString (theFileName).ToCString()));
542   }
543   else {
544     myModule->SetApplication (anApplication);
545     //! expand first three levels: CUSTOM
546     QModelIndex aParentIndex = anOCAFViewModel->index (0, 0);
547     setExpandedLevels (myTreeView, aParentIndex, 3/*levels*/);
548
549     myThread->ProcessApplication();
550     myModule->SetInitialTreeViewSelection();
551     QApplication::restoreOverrideCursor();
552   }
553 }
554
555 // =======================================================================
556 // function : getWindowTitle
557 // purpose :
558 // =======================================================================
559 QString DFBrowser_Window::getWindowTitle() const
560 {
561   DFBrowser_TreeModel* anOCAFViewModel = dynamic_cast<DFBrowser_TreeModel*> (myModule->GetOCAFViewModel());
562   if (!anOCAFViewModel)
563     return "";
564
565   Handle(TDocStd_Application) anApplication = anOCAFViewModel->GetTDocStdApplication();
566   if (anApplication.IsNull() || anApplication->NbDocuments() == 0)
567     return "";
568
569   Handle(TDocStd_Document) aDocument;
570   anApplication->GetDocument (1, aDocument);
571   if (aDocument.IsNull() || !aDocument->IsSaved())
572     return "";
573
574   return DFBrowserPane_Tools::ToString (aDocument->GetPath());
575 }
576
577 // =======================================================================
578 // function : setExpandedLevels
579 // purpose :
580 // =======================================================================
581 void DFBrowser_Window::setExpandedLevels (QTreeView* theTreeView, const QModelIndex& theParentIndex, const int theLevels)
582 {
583   if (theLevels <= 0)
584     return;
585
586   QAbstractItemModel* aModel = theTreeView->model();
587   if (!aModel)
588     return;
589
590   theTreeView->setExpanded (theParentIndex, true);
591   for (int aRowId = 0, aRows = aModel->rowCount (theParentIndex); aRowId < aRows; aRowId++)
592     setExpandedLevels (theTreeView, aModel->index (aRowId, 0, theParentIndex), theLevels - 1);
593 }
594
595 // =======================================================================
596 // function : setOCAFModel
597 // purpose :
598 // =======================================================================
599 void DFBrowser_Window::setOCAFModel (QAbstractItemModel* theModel)
600 {
601   myTreeView->setModel (theModel);
602
603   QItemSelectionModel* aSelectionModel = new QItemSelectionModel (theModel);
604   myTreeView->setSelectionModel (aSelectionModel);
605
606   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
607            myTreeLevelLine, SLOT (OnTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
608   connect(aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
609           myDumpView, SLOT (OnTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
610   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
611            this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
612 }
613
614 // =======================================================================
615 // function : onBeforeUpdateTreeModel
616 // purpose :
617 // =======================================================================
618 void DFBrowser_Window::onBeforeUpdateTreeModel()
619 {
620   myTreeLevelLine->ClearHistory();
621   ClearThreadCache();
622   myThread->ProcessApplication();
623 }
624
625 // =======================================================================
626 // function : ClearThreadCache
627 // purpose :
628 // =======================================================================
629 void DFBrowser_Window::ClearThreadCache()
630 {
631   DFBrowser_ThreadItemSearch::ClearValues (GetTreeLevelLine()->GetSearchLine());
632 }
633
634 // =======================================================================
635 // function : TmpDirectory
636 // purpose :
637 // =======================================================================
638 TCollection_AsciiString DFBrowser_Window::TmpDirectory()
639 {
640   TCollection_AsciiString aTmpDir;
641 #ifdef _WIN32
642   OSD_Environment anEnvironment ("TEMP");
643   aTmpDir = anEnvironment.Value();
644   if (aTmpDir.IsEmpty() )
645   {
646     anEnvironment.SetName("TMP");
647     aTmpDir = anEnvironment.Value();
648     if (aTmpDir.IsEmpty())
649       aTmpDir = "C:\\";
650   }
651   OSD_Path aTmpPath (aTmpDir);
652   OSD_Directory aTmpDirectory (aTmpPath);
653   if (!aTmpDirectory.Exists())
654     aTmpDirectory.Build(OSD_Protection());
655 #else
656   OSD_Directory aTmpDirectory = OSD_Directory::BuildTemporary();
657   OSD_Path aTmpPath;
658   aTmpDirectory.Path (aTmpPath);
659   aTmpPath.SystemName(aTmpDir);
660 #endif
661
662   return aTmpDir;
663 }
664
665 // =======================================================================
666 // function : onTreeViewContextMenuRequested
667 // purpose :
668 // =======================================================================
669 void DFBrowser_Window::onTreeViewContextMenuRequested (const QPoint& thePosition)
670 {
671   QMenu* aMenu = new QMenu(GetMainWindow());
672   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand"), SLOT (onExpand()), GetMainWindow(), this));
673   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand All"), SLOT (onExpandAll()), GetMainWindow(), this));
674   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Collapse All"), SLOT (onCollapseAll()), GetMainWindow(), this));
675
676   QPoint aPoint = myTreeView->mapToGlobal (thePosition);
677   aMenu->exec (aPoint);
678 }
679
680 // =======================================================================
681 // function : onExpand
682 // purpose :
683 // =======================================================================
684 void DFBrowser_Window::onExpand()
685 {
686   QApplication::setOverrideCursor (Qt::WaitCursor);
687
688   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
689   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
690   for (int aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++)
691   {
692     int aLevels = 2;
693     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], true, aLevels);
694   }
695   QApplication::restoreOverrideCursor();
696 }
697
698 // =======================================================================
699 // function : onExpandAll
700 // purpose :
701 // =======================================================================
702 void DFBrowser_Window::onExpandAll()
703 {
704   QApplication::setOverrideCursor (Qt::WaitCursor);
705
706   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
707   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
708   for (int  aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++)
709   {
710     int aLevels = -1;
711     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], true, aLevels);
712   }
713   QApplication::restoreOverrideCursor();
714 }
715
716 // =======================================================================
717 // function : onCollapseAll
718 // purpose :
719 // =======================================================================
720 void DFBrowser_Window::onCollapseAll()
721 {
722   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
723   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
724   for (int aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++) {
725     int aLevels = -1;
726     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], false, aLevels);
727   }
728 }
729
730 // =======================================================================
731 // function : onTreeViewSelectionChanged
732 // purpose :
733 // =======================================================================
734 void DFBrowser_Window::onTreeViewSelectionChanged (const QItemSelection& theSelected,
735                                                    const QItemSelection& theDeselected)
736 {
737   if (!myModule)
738     return;
739
740 #ifdef USE_DUMPJSON
741   if (myPropertyPanelWidget->toggleViewAction()->isChecked())
742     myPropertyView->Init (ViewControl_Tools::CreateTableModelValues (myTreeView->selectionModel()));
743 #endif
744
745   // previuos selection should be cleared in the panel selectors
746   DFBrowser_AttributePaneStack* anAttributePaneStack = myPropertyPanel->GetAttributesStack();
747   anAttributePaneStack->GetPaneSelector()->ClearSelected();
748
749   myPropertyPanel->UpdateBySelectionChanged (theSelected, theDeselected);
750   anAttributePaneStack->GetTreeLevelView()->UpdateByTreeSelectionChanged (theSelected, theDeselected);
751
752   QModelIndexList aSelectedIndices = theSelected.indexes();
753   QModelIndex aSelectedIndex = TreeModel_ModelBase::SingleSelected (aSelectedIndices, 0);
754
755   myTreeView->scrollTo (aSelectedIndex);
756   View_Displayer* aDisplayer = myViewWindow->Displayer();
757   
758   aDisplayer->ErasePresentations (View_PresentationType_Additional, false);
759   aDisplayer->DisplayPresentation (findPresentation (aSelectedIndex), View_PresentationType_Main);
760 }
761
762 // =======================================================================
763 // function : onSearchActivated
764 // purpose :
765 // =======================================================================
766 void DFBrowser_Window::onSearchActivated()
767 {
768   myPropertyPanel->GetAttributesStack()->SetPaneMode ((myTreeLevelLine->GetSearchLine()->Text().isEmpty()
769                         ? DFBrowser_AttributePaneType_ItemView : DFBrowser_AttributePaneType_SearchView));
770 }
771
772 // =======================================================================
773 // function : onPaneSelectionChanged
774 // purpose :
775 // =======================================================================
776 void DFBrowser_Window::onPaneSelectionChanged (const QItemSelection&,
777                                                const QItemSelection&,
778                                                QItemSelectionModel* theModel)
779 {
780   DFBrowserPane_AttributePaneAPI* anAttributePane = myPropertyPanel->GetAttributesStack()->GetCurrentPane();
781   switch (anAttributePane->GetSelectionKind (theModel))
782   {
783     case DFBrowserPane_SelectionKind_ExportToShapeViewer:
784     {
785       QItemSelectionModel* aSelectionModel = theModel;
786       QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
787       if (aSelectedIndices.size() != 1)
788         return;
789
790       TCollection_AsciiString aPluginName ("TKShapeView");
791       NCollection_List<Handle(Standard_Transient)> aParameters;
792       if (myParameters->FindParameters (aPluginName))
793         aParameters = myParameters->Parameters (aPluginName);
794
795       NCollection_List<TCollection_AsciiString> anItemNames;
796       if (myParameters->FindSelectedNames (aPluginName))
797         anItemNames = myParameters->GetSelectedNames (aPluginName);
798
799       int aParametersCount = aParameters.Extent();
800       anAttributePane->GetSelectionParameters (aSelectionModel, aParameters, anItemNames);
801       if (aParametersCount != aParameters.Extent()) // some TShapes are added
802       {
803         TCollection_AsciiString aPluginShortName = aPluginName.SubString (3, aPluginName.Length());
804         QString aMessage = QString ("TShape %1 is sent to %2.")
805           .arg (Standard_Dump::GetPointerInfo (aParameters.Last()).ToCString())
806           .arg (aPluginShortName.ToCString());
807         QString aQuestion = QString ("Would you like to activate %1 immediately?\n")
808           .arg (aPluginShortName.ToCString()).toStdString().c_str();
809         if (!myExportToShapeViewDialog)
810           myExportToShapeViewDialog = new ViewControl_MessageDialog (myParent, aMessage, aQuestion);
811         else
812           myExportToShapeViewDialog->SetInformation (aMessage);
813         myExportToShapeViewDialog->Start();
814
815         myParameters->SetSelectedNames (aPluginName, anItemNames);
816         myParameters->SetParameters (aPluginName, aParameters, myExportToShapeViewDialog->IsAccepted());
817       }
818       return;
819     }
820     case DFBrowserPane_SelectionKind_ExportToBREP:
821     case DFBrowserPane_SelectionKind_LabelReferences:
822     case DFBrowserPane_SelectionKind_AttributeReferences:
823     default: break;
824   }
825
826   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
827   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
828   if (aSelectedIndices.size() != 1)
829     return;
830
831   // make the shape visualized
832   QModelIndex aSelectedIndex = aSelectedIndices.first();
833   View_Displayer* aDisplayer = myViewWindow->Displayer();
834   aDisplayer->DisplayPresentation (findPresentation (aSelectedIndex), View_PresentationType_Main);
835
836   // highlight and scroll to the referenced item if it exists
837   Handle(TDF_Attribute) anAttribute = myModule->FindAttribute (aSelectedIndex);
838   NCollection_List<TDF_Label> aReferences;
839   Handle(Standard_Transient) aPresentation;
840   anAttributePane->GetReferences (anAttribute, aReferences, aPresentation);
841   QModelIndexList anIndices;
842   DFBrowser_TreeModel* aTreeModel = dynamic_cast<DFBrowser_TreeModel*> (myTreeView->model());
843   if (!aReferences.IsEmpty())
844     aTreeModel->ConvertToIndices (aReferences, anIndices);
845   else {
846     NCollection_List<Handle(TDF_Attribute)> anAttributeReferences;
847     anAttributePane->GetAttributeReferences (anAttribute, anAttributeReferences, aPresentation);
848     aTreeModel->ConvertToIndices (anAttributeReferences, anIndices);
849   }
850   highlightIndices (anIndices);
851   // display either the reference presentation of the panel or find a presentation if the reference
852   // is an attribute
853   if (!aPresentation.IsNull())
854     aDisplayer->DisplayPresentation (aPresentation, View_PresentationType_Additional);
855   else {
856     aDisplayer->ErasePresentations (View_PresentationType_Additional, false);
857     AIS_ListOfInteractive aDisplayed;
858     findPresentations (anIndices, aDisplayed);
859     for (AIS_ListIteratorOfListOfInteractive aDisplayedIt (aDisplayed); aDisplayedIt.More(); aDisplayedIt.Next())
860       aDisplayer->DisplayPresentation (aDisplayedIt.Value(), View_PresentationType_Additional, false);
861
862     aDisplayer->UpdateViewer();
863   }
864 }
865
866 // =======================================================================
867 // function : onTreeLevelLineSelected
868 // purpose :
869 // =======================================================================
870 void DFBrowser_Window::onTreeLevelLineSelected (const QModelIndex& theIndex)
871 {
872   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
873   if (theIndex.isValid())
874     aSelectionModel->select (theIndex, QItemSelectionModel::ClearAndSelect);
875   else
876     aSelectionModel->clearSelection();
877 }
878
879 // =======================================================================
880 // function : onUpdateClicked
881 // purpose :
882 // =======================================================================
883 void DFBrowser_Window::onUpdateClicked()
884 {
885   if (myModule)
886     myModule->UpdateTreeModel();
887 }
888
889 // =======================================================================
890 // function : onSearchPathSelected
891 // purpose :
892 // =======================================================================
893 void DFBrowser_Window::onSearchPathSelected (const QStringList& thePath, const QString& theValue)
894 {
895   DFBrowser_TreeModel* aDFBrowserModel = dynamic_cast<DFBrowser_TreeModel*> (myTreeView->model());
896   const QModelIndex& anIndex = aDFBrowserModel->FindIndexByPath (thePath, theValue);
897
898   if (anIndex.isValid())
899   {
900     QModelIndexList anIndices;
901     anIndices.append (anIndex);
902     highlightIndices (anIndices);
903   }
904 }
905
906 // =======================================================================
907 // function : onSearchPathDoubleClicked
908 // purpose :
909 // =======================================================================
910 void DFBrowser_Window::onSearchPathDoubleClicked (const QStringList& thePath, const QString& theValue)
911 {
912   DFBrowser_TreeModel* aDFBrowserModel = dynamic_cast<DFBrowser_TreeModel*> (myTreeView->model());
913   const QModelIndex& anIndex = aDFBrowserModel->FindIndexByPath (thePath, theValue);
914
915   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
916   if (anIndex.isValid())
917     aSelectionModel->select (anIndex, QItemSelectionModel::ClearAndSelect);
918   else
919     aSelectionModel->clearSelection();
920 }
921
922 // =======================================================================
923 // function : onLevelSelected
924 // purpose :
925 // =======================================================================
926 void DFBrowser_Window::onLevelSelected (const QModelIndex& theIndex)
927 {
928   if (!theIndex.isValid())
929     return;
930
931   QModelIndexList anIndices;
932   anIndices.append (theIndex);
933   highlightIndices (anIndices);
934   View_Displayer* aDisplayer = myViewWindow->Displayer();
935   aDisplayer->ErasePresentations (View_PresentationType_Additional, false);
936   aDisplayer->DisplayPresentation (findPresentation (theIndex), View_PresentationType_Main);
937 }
938
939 // =======================================================================
940 // function : onLevelDoubleClicked
941 // purpose :
942 // =======================================================================
943 void DFBrowser_Window::onLevelDoubleClicked (const QModelIndex& theIndex)
944 {
945   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
946   if (theIndex.isValid())
947     aSelectionModel->select (theIndex, QItemSelectionModel::ClearAndSelect);
948   else
949     aSelectionModel->clearSelection();
950 }
951
952 // =======================================================================
953 // function : highlightIndices
954 // purpose :
955 // =======================================================================
956 void DFBrowser_Window::highlightIndices (const QModelIndexList& theIndices)
957 {
958   QAbstractItemModel* aModel = myTreeView->model();
959   if (!aModel)
960     return;
961
962   DFBrowser_TreeModel* aTreeModel = dynamic_cast<DFBrowser_TreeModel*> (aModel);
963   if (!aTreeModel)
964     return;
965
966   aTreeModel->SetHighlighted (theIndices);
967
968   QModelIndex anIndexToScroll;
969   if (!theIndices.isEmpty())
970     anIndexToScroll = theIndices.last(); // scroll to last selected index
971   else
972   {
973     // scroll to tree selected item
974     QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
975     QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
976     if (aSelectedIndices.size() == 1)
977       anIndexToScroll = aSelectedIndices.first();
978   }
979   if (anIndexToScroll.isValid())
980     myTreeView->scrollTo (anIndexToScroll);
981
982   if (theIndices.isEmpty())
983     myTreeView->setFocus(); // to see the selected item in active palette color
984
985   aTreeModel->EmitLayoutChanged();
986 }
987
988 // =======================================================================
989 // function : findPresentation
990 // purpose :
991 // =======================================================================
992 Handle(AIS_InteractiveObject) DFBrowser_Window::findPresentation (const QModelIndex& theIndex)
993 {
994   Handle(AIS_InteractiveObject) aPresentation;
995
996   QModelIndexList anIndices;
997   anIndices.append (theIndex);
998   AIS_ListOfInteractive aDisplayed;
999   findPresentations (anIndices, aDisplayed);
1000   if (!aDisplayed.IsEmpty())
1001     aPresentation = aDisplayed.First();
1002
1003   return aPresentation;
1004 }
1005
1006 // =======================================================================
1007 // function : findPresentations
1008 // purpose :
1009 // =======================================================================
1010 void DFBrowser_Window::findPresentations (const QModelIndexList& theIndices, AIS_ListOfInteractive& thePresentations)
1011 {
1012   for (int anIndexId = 0, aCount = theIndices.size(); anIndexId < aCount; anIndexId++)
1013   {
1014     Handle(AIS_InteractiveObject) aPresentation;
1015     Handle(TDF_Attribute) anAttribute = myModule->FindAttribute (theIndices[anIndexId]);
1016     if (anAttribute.IsNull())
1017       continue;
1018     DFBrowserPane_AttributePaneAPI* anAttributePane = myModule->GetAttributePane (anAttribute);
1019     if (!anAttributePane)
1020       continue;
1021     aPresentation = Handle(AIS_InteractiveObject)::DownCast (anAttributePane->GetPresentation (anAttribute));
1022     if (aPresentation.IsNull())
1023       continue;
1024
1025     thePresentations.Append (aPresentation);
1026   }
1027 }