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