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