0030268: Inspectors - improvements in VInspector plugin
[occt.git] / tools / VInspector / VInspector_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/VInspector_Window.hxx>
17
18 #include <AIS_Shape.hxx>
19 #include <BRepBuilderAPI_MakeVertex.hxx>
20
21 #include <inspector/Convert_Tools.hxx>
22
23 #include <inspector/TreeModel_ColumnType.hxx>
24 #include <inspector/TreeModel_ContextMenu.hxx>
25 #include <inspector/TreeModel_ItemProperties.hxx>
26 #include <inspector/TreeModel_Tools.hxx>
27
28 #include <inspector/ViewControl_MessageDialog.hxx>
29 #include <inspector/ViewControl_TableModel.hxx>
30 #include <inspector/ViewControl_Tools.hxx>
31 #include <inspector/Convert_TransientShape.hxx>
32
33 #include <inspector/VInspector_ToolBar.hxx>
34 #include <inspector/VInspector_Tools.hxx>
35 #include <inspector/VInspector_ViewModel.hxx>
36 #include <inspector/VInspector_CallBack.hxx>
37 #include <inspector/VInspector_Communicator.hxx>
38 #include <inspector/VInspector_ItemContext.hxx>
39 #include <inspector/VInspector_ToolBar.hxx>
40 #include <inspector/VInspector_Tools.hxx>
41 #include <inspector/VInspector_ViewModel.hxx>
42 #include <inspector/VInspector_ViewModelHistory.hxx>
43
44 #include <inspector/ViewControl_PropertyView.hxx>
45 #include <inspector/ViewControl_TreeView.hxx>
46
47 #include <inspector/View_Displayer.hxx>
48 #include <inspector/View_DisplayPreview.hxx>
49 #include <inspector/View_PreviewParameters.hxx>
50 #include <inspector/View_Widget.hxx>
51 #include <inspector/View_Window.hxx>
52
53 #include <Standard_WarningsDisable.hxx>
54 #include <QApplication>
55 #include <QDockWidget>
56 #include <QHeaderView>
57 #include <QGridLayout>
58 #include <QItemSelectionModel>
59 #include <QMainWindow>
60 #include <QMenu>
61 #include <QMessageBox>
62 #include <QToolButton>
63 #include <QTreeView>
64 #include <QWidget>
65 #include <Standard_WarningsRestore.hxx>
66
67 const int VINSPECTOR_DEFAULT_PROPERTY_VIEW_WIDTH = 300;
68 const int VINSPECTOR_DEFAULT_PROPERTY_VIEW_HEIGHT = 1000;
69
70 const int VINSPECTOR_DEFAULT_WIDTH  = 1250;
71 const int VINSPECTOR_DEFAULT_HEIGHT = 800;
72
73 const int VINSPECTOR_DEFAULT_POSITION_X = 200;
74 const int VINSPECTOR_DEFAULT_POSITION_Y = 60;
75
76 const int VINSPECTOR_DEFAULT_VIEW_WIDTH = 400;
77 const int VINSPECTOR_DEFAULT_VIEW_HEIGHT = 1000;
78
79 const int VINSPECTOR_DEFAULT_HISTORY_VIEW_WIDTH = 400;
80 const int VINSPECTOR_DEFAULT_HISTORY_VIEW_HEIGHT = 50;
81
82 const int VINSPECTOR_DEFAULT_VIEW_POSITION_X = 200 + 900 + 100; // TINSPECTOR_DEFAULT_POSITION_X + TINSPECTOR_DEFAULT_WIDTH + 100
83 const int VINSPECTOR_DEFAULT_VIEW_POSITION_Y = 60; // TINSPECTOR_DEFAULT_POSITION_Y + 50
84
85 // =======================================================================
86 // function : Constructor
87 // purpose :
88 // =======================================================================
89 VInspector_Window::VInspector_Window()
90 : myParent (0), myExportToShapeViewDialog (0), myViewWindow (0)
91 {
92   myDisplayer = new View_Displayer();
93
94   myMainWindow = new QMainWindow (0);
95
96   QWidget* aCentralWidget = new QWidget (myMainWindow);
97   QGridLayout* aParentLay = new QGridLayout (aCentralWidget);
98   aParentLay->setContentsMargins (0, 0, 0, 0);
99   aParentLay->setSpacing(0);
100
101   // restore state of tool bar: on the bottom of the window
102   myToolBar = new VInspector_ToolBar(aCentralWidget);
103   connect (myToolBar, SIGNAL (actionClicked (int)), this, SLOT (onToolBarActionClicked (int)));
104   aParentLay->addWidget (myToolBar->GetControl(), 0, 0);
105
106   // tree view
107   myTreeView = new QTreeView (aCentralWidget);
108   myTreeView->setSelectionBehavior (QAbstractItemView::SelectRows);
109   myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection);
110   myTreeView->header()->setStretchLastSection (true);
111   myTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
112   VInspector_ViewModel* aTreeModel = new VInspector_ViewModel (myTreeView);
113   aTreeModel->InitColumns();
114   myTreeView->setModel (aTreeModel);
115   // hide Visibility column
116   TreeModel_HeaderSection anItem = aTreeModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility);
117   anItem.SetIsHidden (true);
118   aTreeModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem);
119
120   connect (myTreeView, SIGNAL(customContextMenuRequested(const QPoint&)),
121            this, SLOT (onTreeViewContextMenuRequested(const QPoint&)));
122   new TreeModel_ContextMenu (myTreeView);
123
124   QItemSelectionModel* aSelModel = new QItemSelectionModel (myTreeView->model(), myTreeView);
125   myTreeView->setSelectionModel (aSelModel);
126   connect (aSelModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
127            this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
128
129   aParentLay->addWidget(myTreeView, 1, 0);
130   aParentLay->setRowStretch (1, 1);
131   myMainWindow->setCentralWidget (aCentralWidget);
132
133   // property view
134   myPropertyView = new ViewControl_PropertyView (myMainWindow,
135     QSize(VINSPECTOR_DEFAULT_PROPERTY_VIEW_WIDTH, VINSPECTOR_DEFAULT_PROPERTY_VIEW_HEIGHT));
136   myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow);
137   myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle());
138   myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
139   myPropertyPanelWidget->setWidget (myPropertyView->GetControl());
140   myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget);
141   connect (myPropertyPanelWidget->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT (onPropertyPanelShown (bool)));
142
143   myHistoryView = new ViewControl_TreeView (myMainWindow);
144   myHistoryView->setSelectionBehavior (QAbstractItemView::SelectRows);
145   ((ViewControl_TreeView*)myHistoryView)->SetPredefinedSize (QSize (VINSPECTOR_DEFAULT_HISTORY_VIEW_WIDTH,
146                                                                     VINSPECTOR_DEFAULT_HISTORY_VIEW_HEIGHT));
147   myHistoryView->setContextMenuPolicy (Qt::CustomContextMenu);
148   myHistoryView->header()->setStretchLastSection (true);
149   new TreeModel_ContextMenu (myHistoryView);
150
151   myHistoryView->setSelectionMode (QAbstractItemView::ExtendedSelection);
152   VInspector_ViewModelHistory* aHistoryModel = new VInspector_ViewModelHistory (myHistoryView);
153   aHistoryModel->InitColumns();
154   myHistoryView->setModel (aHistoryModel);
155
156   QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aHistoryModel);
157   myHistoryView->setSelectionModel (aSelectionModel);
158   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
159     this, SLOT (onHistoryViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
160
161   anItem = aHistoryModel->GetHeaderItem (0);
162   // hide Visibility column
163   TreeModel_Tools::UseVisibilityColumn (myHistoryView, false);
164   anItem = aHistoryModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility);
165   anItem.SetIsHidden (true);
166   aHistoryModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem);
167
168   QModelIndex aParentIndex = myHistoryView->model()->index (0, 0);
169   myHistoryView->setExpanded (aParentIndex, true);
170
171   QDockWidget* aHistoryDockWidget = new QDockWidget (tr ("HistoryView"), myMainWindow);
172   aHistoryDockWidget->setObjectName (aHistoryDockWidget->windowTitle());
173   aHistoryDockWidget->setTitleBarWidget (new QWidget(myMainWindow));
174   aHistoryDockWidget->setWidget (myHistoryView);
175   myMainWindow->addDockWidget (Qt::BottomDockWidgetArea, aHistoryDockWidget);
176
177   myMainWindow->resize (450, 800);
178   myMainWindow->move (60, 20);
179
180   myMainWindow->resize (VINSPECTOR_DEFAULT_WIDTH, VINSPECTOR_DEFAULT_HEIGHT);
181   myMainWindow->move (VINSPECTOR_DEFAULT_POSITION_X, VINSPECTOR_DEFAULT_POSITION_Y);
182 }
183
184 // =======================================================================
185 // function : SetParent
186 // purpose :
187 // =======================================================================
188 void VInspector_Window::SetParent (void* theParent)
189 {
190   myParent = (QWidget*)theParent;
191   if (!myParent)
192     return;
193
194   QLayout* aLayout = myParent->layout();
195   if (aLayout)
196     aLayout->addWidget (GetMainWindow());
197 }
198
199 // =======================================================================
200 // function : FillActionsMenu
201 // purpose :
202 // =======================================================================
203 void VInspector_Window::FillActionsMenu (void* theMenu)
204 {
205   QMenu* aMenu = (QMenu*)theMenu;
206   QList<QDockWidget*> aDockwidgets = myMainWindow->findChildren<QDockWidget*>();
207   for (QList<QDockWidget*>::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it)
208   {
209     QDockWidget* aDockWidget = *it;
210     if (aDockWidget->parentWidget() == myMainWindow)
211       aMenu->addAction (aDockWidget->toggleViewAction());
212   }
213 }
214
215 // =======================================================================
216 // function : GetPreferences
217 // purpose :
218 // =======================================================================
219 void VInspector_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem)
220 {
221   theItem.Bind ("geometry",  TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str());
222
223   QMap<QString, QString> anItems;
224   TreeModel_Tools::SaveState (myTreeView, anItems);
225   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
226   {
227     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
228   }
229
230   anItems.clear();
231   View_PreviewParameters::SaveState (displayer()->DisplayPreview()->GetPreviewParameters(), anItems, "preview_parameters_");
232   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
233     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
234
235   anItems.clear();
236   TreeModel_Tools::SaveState (myTreeView, anItems);
237   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
238   {
239     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
240   }
241
242   anItems.clear();
243   ViewControl_PropertyView::SaveState (myPropertyView, anItems, "property_view_parameters_");
244   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
245     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
246
247   if (myViewWindow)
248   {
249     anItems.clear();
250     View_Window::SaveState(myViewWindow, anItems);
251     for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
252       theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
253   }
254 }
255
256 // =======================================================================
257 // function : SetPreferences
258 // purpose :
259 // =======================================================================
260 void VInspector_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem)
261 {
262   if (theItem.IsEmpty())
263   {
264     TreeModel_Tools::SetDefaultHeaderSections (myTreeView);
265     TreeModel_Tools::SetDefaultHeaderSections (myHistoryView);
266     return;
267   }
268
269   for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next())
270   {
271     TCollection_AsciiString anItemKey = anItemIt.Key();
272     TCollection_AsciiString anItemValue = anItemIt.Value();
273     if (anItemKey.IsEqual ("geometry"))
274       myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemValue.ToCString()));
275     else if (TreeModel_Tools::RestoreState (myTreeView, anItemKey.ToCString(), anItemValue.ToCString()))
276       continue;
277     else if (TreeModel_Tools::RestoreState (myHistoryView, anItemKey.ToCString(), anItemValue.ToCString(),
278                                             "history_view_"))
279       continue;
280     else if (View_PreviewParameters::RestoreState (displayer()->DisplayPreview()->GetPreviewParameters(), anItemKey.ToCString(),
281       anItemValue.ToCString(), "preview_parameters_"))
282       continue;
283     else if (ViewControl_PropertyView::RestoreState (myPropertyView, anItemKey.ToCString(),
284       anItemValue.ToCString(), "property_view_parameters_"))
285       continue;
286     else if (myViewWindow && View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
287       continue;
288   }
289 }
290
291 // =======================================================================
292 // function : UpdateContent
293 // purpose :
294 // =======================================================================
295 void VInspector_Window::UpdateContent()
296 {
297   TCollection_AsciiString aName = "TKVInspector";
298
299   bool isModelUpdated = false;
300   if (myParameters->FindParameters (aName))
301     isModelUpdated = Init (myParameters->Parameters (aName));
302   if (myParameters->FindFileNames (aName))
303   {
304     for (NCollection_List<TCollection_AsciiString>::Iterator aFileNamesIt (myParameters->FileNames (aName));
305          aFileNamesIt.More(); aFileNamesIt.Next())
306          isModelUpdated = OpenFile (aFileNamesIt.Value()) || isModelUpdated;
307
308     NCollection_List<TCollection_AsciiString> aNames;
309     myParameters->SetFileNames (aName, aNames);
310   }
311   if (!isModelUpdated)
312     UpdateTreeModel();
313
314   // make AIS_InteractiveObject selected selected if exist in select parameters
315   NCollection_List<Handle(Standard_Transient)> anObjects;
316   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*>(myTreeView->model());
317   if (aViewModel && myParameters->GetSelectedObjects(aName, anObjects))
318   {
319     QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
320     aSelectionModel->clear();
321     for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (anObjects);
322          aParamsIt.More(); aParamsIt.Next())
323     {
324       Handle(Standard_Transient) anObject = aParamsIt.Value();
325       Handle(AIS_InteractiveObject) aPresentation = Handle(AIS_InteractiveObject)::DownCast (anObject);
326       if (aPresentation.IsNull())
327         continue;
328
329       QModelIndex aPresentationIndex = aViewModel->FindIndex (aPresentation);
330       if (!aPresentationIndex.isValid())
331         continue;
332        aSelectionModel->select (aPresentationIndex, QItemSelectionModel::Select);
333        myTreeView->scrollTo (aPresentationIndex);
334     }
335   }
336
337   if (!myCallBack.IsNull())
338   {
339     VInspector_ViewModelHistory* aHistoryModel = dynamic_cast<VInspector_ViewModelHistory*>
340       (myHistoryView->model());
341     aHistoryModel->Reset();
342     aHistoryModel->EmitLayoutChanged();
343   }
344 }
345
346 // =======================================================================
347 // function : SelectedPresentations
348 // purpose :
349 // =======================================================================
350 NCollection_List<Handle(AIS_InteractiveObject)> VInspector_Window::SelectedPresentations (QItemSelectionModel* theModel)
351 {
352   NCollection_List<Handle(AIS_InteractiveObject)> aSelectedPresentations;
353
354   QList<TreeModel_ItemBasePtr> anItems = TreeModel_ModelBase::SelectedItems (theModel->selectedIndexes());
355
356   QList<size_t> aSelectedIds; // Remember of selected address in order to avoid duplicates
357   NCollection_List<Handle(Standard_Transient)> anItemPresentations;
358   for (QList<TreeModel_ItemBasePtr>::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt)
359   {
360     TreeModel_ItemBasePtr anItem = *anItemIt;
361     VInspector_ItemBasePtr aVItem = itemDynamicCast<VInspector_ItemBase>(anItem);
362     if (!aVItem)
363       continue;
364
365     anItemPresentations.Clear();
366     aVItem->Presentations (anItemPresentations);
367
368     for (NCollection_List<Handle(Standard_Transient)>::Iterator anIt (anItemPresentations); anIt.More(); anIt.Next())
369     {
370       Handle(AIS_InteractiveObject) aPresentation = Handle(AIS_InteractiveObject)::DownCast (anIt.Value());
371       if (aSelectedIds.contains ((size_t)aPresentation.get()))
372         continue;
373       aSelectedIds.append ((size_t)aPresentation.get());
374       if (!aPresentation.IsNull())
375         aSelectedPresentations.Append (aPresentation);
376     }
377   }
378   return aSelectedPresentations;
379 }
380
381 // =======================================================================
382 // function : SelectedShapes
383 // purpose :
384 // =======================================================================
385 void VInspector_Window::SelectedShapes (NCollection_List<Handle(Standard_Transient)>& theSelPresentations)
386 {
387   QModelIndexList theIndices = myTreeView->selectionModel()->selectedIndexes();
388
389   QList<TreeModel_ItemBasePtr> anItems = TreeModel_ModelBase::SelectedItems (theIndices);
390   for (QList<TreeModel_ItemBasePtr>::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt)
391   {                                                                                                                  
392     TreeModel_ItemBasePtr anItem = *anItemIt;
393     VInspector_ItemBasePtr aVItem = itemDynamicCast<VInspector_ItemBase>(anItem);
394     if (!aVItem /*|| aVItem->Row() == 0*/)
395       continue;
396
397     TopoDS_Shape aShape = aVItem->GetPresentationShape();
398     if (aShape.IsNull())
399       continue;
400
401     theSelPresentations.Append (new Convert_TransientShape (aShape));
402   }
403 }
404
405 // =======================================================================
406 // function : Init
407 // purpose :
408 // =======================================================================
409 bool VInspector_Window::Init (const NCollection_List<Handle(Standard_Transient)>& theParameters)
410 {
411   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
412   if (!aViewModel)
413     return Standard_False;
414
415   Handle(AIS_InteractiveContext) aContext;
416   Handle(VInspector_CallBack) aCallBack;
417   Standard_Boolean isModelUpdated = Standard_False;
418
419   for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (theParameters); aParamsIt.More(); aParamsIt.Next())
420   {
421     Handle(Standard_Transient) anObject = aParamsIt.Value();
422     if (aContext.IsNull())
423       aContext = Handle(AIS_InteractiveContext)::DownCast (anObject);
424
425     if (aCallBack.IsNull())
426       aCallBack = Handle(VInspector_CallBack)::DownCast (anObject);
427   }
428   if (aViewModel->GetContext() != aContext)
429     SetContext(aContext);
430   else
431     isModelUpdated = Standard_True;
432
433   if (!aCallBack.IsNull() && aCallBack != myCallBack)
434   {
435     myCallBack = aCallBack;
436     VInspector_ViewModelHistory* aHistoryModel = dynamic_cast<VInspector_ViewModelHistory*>
437       (myHistoryView->model());
438     myCallBack->SetContext(aContext);
439     myCallBack->SetHistoryModel(aHistoryModel);
440   }
441
442   if (isModelUpdated)
443     UpdateTreeModel();
444
445   return true;
446 }
447
448 // =======================================================================
449 // function : SetContext
450 // purpose :
451 // =======================================================================
452 void VInspector_Window::SetContext (const Handle(AIS_InteractiveContext)& theContext)
453 {
454   if (theContext.IsNull())
455     return;
456
457   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
458   aViewModel->SetContext (theContext);
459   myTreeView->setExpanded (aViewModel->index (0, 0), true);
460
461   if (!myCallBack.IsNull())
462     myCallBack->SetContext (theContext);
463
464   if (myDisplayer)
465     myDisplayer->SetContext (theContext);
466 }
467
468 // =======================================================================
469 // function : OpenFile
470 // purpose :
471 // =======================================================================
472 bool VInspector_Window::OpenFile(const TCollection_AsciiString& theFileName)
473 {
474   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
475   if (!aViewModel)
476     return false;
477
478   Handle(AIS_InteractiveContext) aContext = aViewModel->GetContext();
479   bool isModelUpdated = false;
480   if (aContext.IsNull())
481   {
482     aContext = createView();
483     SetContext (aContext);
484     isModelUpdated = true;
485   }
486
487   TopoDS_Shape aShape = Convert_Tools::ReadShape (theFileName);
488   if (aShape.IsNull())
489     return isModelUpdated;
490
491   Handle(AIS_Shape) aPresentation = new AIS_Shape (aShape);
492   View_Displayer* aDisplayer = myViewWindow->Displayer();
493   aDisplayer->DisplayPresentation (aPresentation);
494   aContext->UpdateCurrentViewer();
495
496   UpdateTreeModel();
497   myTreeView->setExpanded (aViewModel->index (0, 0), true);
498   return true;
499 }
500
501 // =======================================================================
502 // function : onTreeViewContextMenuRequested
503 // purpose :
504 // =======================================================================
505 void VInspector_Window::onTreeViewContextMenuRequested(const QPoint& thePosition)
506 {
507   QMenu* aMenu = new QMenu (GetMainWindow());
508   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export to ShapeView"), SLOT (onExportToShapeView()), GetMainWindow(), this));
509   aMenu->addSeparator();
510
511   QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (myTreeView->selectionModel()->selectedIndexes(), 0);
512   TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
513   if (anItemBase)
514   {
515     if (itemDynamicCast<VInspector_ItemContext> (anItemBase))
516     {
517       aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export to MessageView"), SLOT (onExportToMessageView()), GetMainWindow(), this));
518       aMenu->addSeparator();
519     }
520   }
521
522   aMenu->addSeparator();
523   for (int aTypeId = (int)View_DisplayActionType_DisplayId; aTypeId <= (int)View_DisplayActionType_RemoveId; aTypeId++)
524   {
525     aMenu->addAction (ViewControl_Tools::CreateAction (VInspector_Tools::DisplayActionTypeToString ((View_DisplayActionType) aTypeId),
526                       SLOT (onDisplayActionTypeClicked()), GetMainWindow(), this));
527   }
528   aMenu->addSeparator();
529
530   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand"), SLOT (onExpand()), GetMainWindow(), this));
531   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand All"), SLOT (onExpandAll()), GetMainWindow(), this));
532   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Collapse All"), SLOT (onCollapseAll()), GetMainWindow(), this));
533
534   aMenu->addSeparator();
535   aMenu->addAction (ViewControl_Tools::CreateAction ("Test AddChild", SLOT (OnTestAddChild()), GetMainWindow(), this));
536
537   QPoint aPoint = myTreeView->mapToGlobal (thePosition);
538   aMenu->exec(aPoint);
539 }
540
541 // =======================================================================
542 // function : onToolBarActionClicked
543 // purpose :
544 // =======================================================================
545 void VInspector_Window::onToolBarActionClicked (const int theActionId)
546 {
547   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
548   if (!aViewModel)
549     return;
550
551   switch (theActionId)
552   {
553     case VInspector_ToolActionType_UpdateId:
554     {
555       UpdateTreeModel();
556       break;
557     }
558     default:
559       break;
560   }
561 }
562
563 // =======================================================================
564 // function : onPropertyPanelShown
565 // purpose :
566 // =======================================================================
567 void VInspector_Window::onPropertyPanelShown (bool isToggled)
568 {
569   if (!isToggled)
570     return;
571
572   myPropertyView->Init (ViewControl_Tools::CreateTableModelValues (myTreeView->selectionModel()));
573 }
574
575 // =======================================================================
576 // function : onTreeViewSelectionChanged
577 // purpose :
578 // =======================================================================
579 void VInspector_Window::onTreeViewSelectionChanged (const QItemSelection&,
580                                                     const QItemSelection&)
581 {
582   if (myPropertyPanelWidget->toggleViewAction()->isChecked())
583     myPropertyView->Init (ViewControl_Tools::CreateTableModelValues (myTreeView->selectionModel()));
584
585   NCollection_List<Handle(Standard_Transient)> aSelPresentations;
586
587   QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes();
588   for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++)
589   {
590     QModelIndex anIndex = *aSelIt;
591     if (anIndex.column() != 0)
592       continue;
593
594     TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
595     if (!anItemBase)
596       continue;
597
598     const Handle(TreeModel_ItemProperties)& anItemProperties = anItemBase->Properties();
599     if (anItemProperties)
600     {
601       anItemProperties->Presentations (aSelPresentations);
602     }
603   }
604
605   SelectedShapes (aSelPresentations);
606   displayer()->DisplayPreview()->UpdatePreview (View_DisplayActionType_DisplayId, aSelPresentations, myViewWindow->ViewWidget()->DisplayMode());
607 }
608
609 // =======================================================================
610 // function : onHistoryViewSelectionChanged
611 // purpose :
612 // =======================================================================
613 void VInspector_Window::onHistoryViewSelectionChanged (const QItemSelection& theSelected,
614                                                        const QItemSelection&)
615 {
616   VInspector_ViewModelHistory* aHistoryModel = dynamic_cast<VInspector_ViewModelHistory*> (myHistoryView->model());
617   if (!aHistoryModel)
618     return;
619
620   if (theSelected.size() == 0)
621     return;
622
623   QModelIndexList aSelectedIndices = theSelected.indexes();
624   QStringList aPointers = aHistoryModel->GetSelectedPointers(aSelectedIndices.first());
625   selectTreeViewItems (aPointers);
626 }
627
628 // =======================================================================
629 // function : onExportToShapeView
630 // purpose :
631 // =======================================================================
632 void VInspector_Window::onExportToShapeView()
633 {
634   NCollection_List<Handle(Standard_Transient)> aSelectedShapes;
635   SelectedShapes (aSelectedShapes);
636
637   TCollection_AsciiString aPluginName ("TKShapeView");
638   NCollection_List<Handle(Standard_Transient)> aParameters;
639   if (myParameters->FindParameters (aPluginName))
640     aParameters = myParameters->Parameters (aPluginName);
641
642   NCollection_List<TCollection_AsciiString> anItemNames;
643   if (myParameters->FindSelectedNames (aPluginName))
644     anItemNames = myParameters->GetSelectedNames (aPluginName);
645
646   QStringList anExportedPointers;
647   if (aSelectedShapes.Extent() > 0)
648   {
649     for (NCollection_List<Handle(Standard_Transient)>::Iterator aShapeIt (aSelectedShapes); aShapeIt.More(); aShapeIt.Next())
650     {
651       Handle(Convert_TransientShape) aShapePtr = Handle(Convert_TransientShape)::DownCast (aShapeIt.Value());
652       if (aShapePtr.IsNull())
653         continue;
654
655       const TopoDS_Shape& aShape = aShapePtr->Shape();
656       if (aShape.IsNull())
657         continue;
658       aParameters.Append (aShape.TShape());
659       anItemNames.Append (TInspectorAPI_PluginParameters::ParametersToString(aShape));
660       anExportedPointers.append (Standard_Dump::GetPointerInfo (aShape.TShape(), true).ToCString());
661     }
662   }
663
664   // search for objects to be exported
665   QList<TreeModel_ItemBasePtr> anItems = TreeModel_ModelBase::SelectedItems (myTreeView->selectionModel()->selectedIndexes());
666   for (QList<TreeModel_ItemBasePtr>::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt)
667   {
668     TreeModel_ItemBasePtr anItem = *anItemIt;
669     VInspector_ItemBasePtr aVItem = itemDynamicCast<VInspector_ItemBase>(anItem);
670     if (!aVItem)
671     continue;
672
673     const Handle(Standard_Transient)& anObject = aVItem->Object();
674     if (anObject.IsNull())
675       continue;
676
677     aParameters.Append (anObject);
678     anItemNames.Append (anObject->DynamicType()->Name());
679     anExportedPointers.append (Standard_Dump::GetPointerInfo (anObject, true).ToCString());
680   }
681
682   if (anExportedPointers.isEmpty())
683     return;
684
685   TCollection_AsciiString aPluginShortName = aPluginName.SubString (3, aPluginName.Length());
686   QString aMessage = QString ("Objects %1 are sent to %2.")
687     .arg (anExportedPointers.join(", "))
688     .arg (aPluginShortName.ToCString());
689   QString aQuestion = QString ("Would you like to activate %1 immediately?\n")
690     .arg (aPluginShortName.ToCString()).toStdString().c_str();
691   if (!myExportToShapeViewDialog)
692     myExportToShapeViewDialog = new ViewControl_MessageDialog (myParent, aMessage, aQuestion);
693   else
694     myExportToShapeViewDialog->SetInformation (aMessage);
695   myExportToShapeViewDialog->Start();
696
697   myParameters->SetSelectedNames (aPluginName, anItemNames);
698   myParameters->SetParameters (aPluginName, aParameters, myExportToShapeViewDialog->IsAccepted());
699 }
700
701 // =======================================================================
702 // function : onDisplayActionTypeClicked
703 // purpose :
704 // =======================================================================
705 void VInspector_Window::onDisplayActionTypeClicked()
706 {
707   QAction* anAction = (QAction*)sender();
708
709   displaySelectedPresentations (VInspector_Tools::DisplayActionTypeFromString (anAction->text().toStdString().c_str()));
710 }
711
712 // =======================================================================
713 // function : onExpand
714 // purpose :
715 // =======================================================================
716 void VInspector_Window::onExpand()
717 {
718   QApplication::setOverrideCursor (Qt::WaitCursor);
719
720   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
721   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
722   for (int aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++)
723   {
724     int aLevels = 2;
725     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], true, aLevels);
726   }
727   QApplication::restoreOverrideCursor();
728 }
729
730 // =======================================================================
731 // function : onExpandAll
732 // purpose :
733 // =======================================================================
734 void VInspector_Window::onExpandAll()
735 {
736   QApplication::setOverrideCursor (Qt::WaitCursor);
737
738   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
739   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
740   for (int  aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++)
741   {
742     int aLevels = -1;
743     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], true, aLevels);
744   }
745   QApplication::restoreOverrideCursor();
746 }
747
748 // =======================================================================
749 // function : onCollapseAll
750 // purpose :
751 // =======================================================================
752 void VInspector_Window::onCollapseAll()
753 {
754   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
755   QModelIndexList aSelectedIndices = aSelectionModel->selectedIndexes();
756   for (int aSelectedId = 0, aSize = aSelectedIndices.size(); aSelectedId < aSize; aSelectedId++)
757   {
758     int aLevels = -1;
759     TreeModel_Tools::SetExpanded (myTreeView, aSelectedIndices[aSelectedId], false, aLevels);
760   }
761 }
762
763 // =======================================================================
764 // function : UpdateTreeModel
765 // purpose :
766 // =======================================================================
767 void VInspector_Window::OnTestAddChild()
768 {
769   Handle(AIS_Shape) aPresentation = new AIS_Shape (BRepBuilderAPI_MakeVertex (gp_Pnt()));
770
771   aPresentation->AddChild (new AIS_Shape (BRepBuilderAPI_MakeVertex (gp_Pnt (10., 10., 10.))));
772   aPresentation->AddChild (new AIS_Shape (BRepBuilderAPI_MakeVertex (gp_Pnt(20., 10., 10.))));
773   aPresentation->AddChild (new AIS_Shape (BRepBuilderAPI_MakeVertex (gp_Pnt(30., 10., 10.))));
774
775   displayer()->DisplayPresentation (aPresentation);
776
777   UpdateTreeModel();
778 }
779
780 // =======================================================================
781 // function : UpdateTreeModel
782 // purpose :
783 // =======================================================================
784 void VInspector_Window::UpdateTreeModel()
785 {
786   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
787   if (aViewModel)
788     aViewModel->UpdateTreeModel();
789 }
790
791 // =======================================================================
792 // function : displaySelectedPresentations
793 // purpose :
794 // =======================================================================
795
796 void VInspector_Window::displaySelectedPresentations (const View_DisplayActionType theType)
797 {
798   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
799   if (!aViewModel)
800     return;
801
802   Handle(AIS_InteractiveContext) aContext = aViewModel->GetContext();
803   if (aContext.IsNull())
804     return;
805
806   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
807   if (!aSelectionModel)
808     return;
809
810   NCollection_List<Handle(AIS_InteractiveObject)> aSelectedPresentations = SelectedPresentations (aSelectionModel);
811   // the order of objects returned by AIS_InteractiveContext is changed because the processed object is moved from
812   // Erased to Displayed container or back
813   aSelectionModel->clear();
814
815
816   if (aSelectedPresentations.Extent() == 0)
817     return;
818
819   for (NCollection_List<Handle(AIS_InteractiveObject)>::Iterator anIOIt(aSelectedPresentations); anIOIt.More(); anIOIt.Next())
820   {
821     Handle(AIS_InteractiveObject) aPresentation = anIOIt.Value();
822     switch (theType)
823     {
824       case View_DisplayActionType_DisplayId:
825       {
826         aContext->Display(aPresentation, false);
827         aContext->Load(aPresentation, -1);
828       }
829       break;
830
831       case View_DisplayActionType_RedisplayId: aContext->Redisplay (aPresentation, false); break;
832       case View_DisplayActionType_EraseId: aContext->Erase (aPresentation, false); break;
833       case View_DisplayActionType_RemoveId: aContext->Remove (aPresentation, false); break;
834       default: break;
835     }
836   }
837   aContext->UpdateCurrentViewer();
838
839   UpdateTreeModel();
840 }
841
842 // =======================================================================
843 // function : highlightTreeViewItems
844 // purpose :
845 // =======================================================================
846 void VInspector_Window::highlightTreeViewItems (const QStringList& thePointers)
847 {
848   VInspector_ViewModel* aTreeModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
849   if (!aTreeModel)
850     return;
851
852   QModelIndexList anIndices;
853   aTreeModel->FindPointers (thePointers, QModelIndex(), anIndices);
854   for (int anIndicesId = 0, aSize = anIndices.size(); anIndicesId < aSize; anIndicesId++)
855   {
856     QModelIndex anIndex = anIndices[anIndicesId];
857     TreeModel_Tools::SetExpandedTo (myTreeView, anIndex);
858   }
859   aTreeModel->SetHighlighted (anIndices);
860
861   if (!anIndices.isEmpty())
862     myTreeView->scrollTo (anIndices.last());
863 }
864
865 // =======================================================================
866 // function : selectTreeViewItems
867 // purpose :
868 // =======================================================================
869 void VInspector_Window::selectTreeViewItems (const QStringList& thePointers)
870 {
871   VInspector_ViewModel* aTreeModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
872   if (!aTreeModel)
873     return;
874   
875   QModelIndexList anIndices;
876   aTreeModel->FindPointers (thePointers, QModelIndex(), anIndices);
877   QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
878   aSelectionModel->clear();
879   for (int anIndicesId = 0, aSize = anIndices.size(); anIndicesId < aSize; anIndicesId++)
880   {
881     QModelIndex anIndex = anIndices[anIndicesId];
882     TreeModel_Tools::SetExpandedTo (myTreeView, anIndex);
883     aSelectionModel->select (anIndex, QItemSelectionModel::Select);
884   }
885 }
886
887 // =======================================================================
888 // function : createView
889 // purpose :
890 // =======================================================================
891 Handle(AIS_InteractiveContext) VInspector_Window::createView()
892 {
893   // create two view windows
894   Handle(AIS_InteractiveContext) aContext = View_Viewer::CreateStandardViewer();
895
896   myViewWindow = new View_Window (0, aContext, false /*for opening several BREP files*/, true);
897   myViewWindow->ViewWidget()->SetPredefinedSize (VINSPECTOR_DEFAULT_VIEW_WIDTH, VINSPECTOR_DEFAULT_VIEW_HEIGHT);
898   myViewWindow->move (VINSPECTOR_DEFAULT_VIEW_POSITION_X, VINSPECTOR_DEFAULT_VIEW_POSITION_Y);
899   myViewWindow->show();
900
901   return aContext;
902 }
903
904 // =======================================================================
905 // function : displayer
906 // purpose :
907 // =======================================================================
908 View_Displayer* VInspector_Window::displayer()
909 {
910   if (myViewWindow)
911     return myViewWindow->Displayer();
912
913   return myDisplayer;
914 }