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