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