0031658: Inspector - using AIS_ViewController in View package
[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 #include <V3d_Viewer.hxx>
21
22 #include <inspector/Convert_Tools.hxx>
23
24 #include <inspector/TreeModel_ColumnType.hxx>
25 #include <inspector/TreeModel_ContextMenu.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 #include <inspector/View_Viewer.hxx>
53
54 #include <Standard_WarningsDisable.hxx>
55 #include <QApplication>
56 #include <QDockWidget>
57 #include <QHeaderView>
58 #include <QGridLayout>
59 #include <QItemSelectionModel>
60 #include <QMainWindow>
61 #include <QMenu>
62 #include <QMessageBox>
63 #include <QToolButton>
64 #include <QTreeView>
65 #include <QWidget>
66 #include <Standard_WarningsRestore.hxx>
67
68 const int VINSPECTOR_DEFAULT_PROPERTY_VIEW_WIDTH = 300;
69 const int VINSPECTOR_DEFAULT_PROPERTY_VIEW_HEIGHT = 1000;
70
71 const int VINSPECTOR_DEFAULT_WIDTH  = 1250;
72 const int VINSPECTOR_DEFAULT_HEIGHT = 800;
73
74 const int VINSPECTOR_DEFAULT_POSITION_X = 200;
75 const int VINSPECTOR_DEFAULT_POSITION_Y = 60;
76
77 const int VINSPECTOR_DEFAULT_VIEW_WIDTH = 400;
78 const int VINSPECTOR_DEFAULT_VIEW_HEIGHT = 1000;
79
80 const int VINSPECTOR_DEFAULT_HISTORY_VIEW_WIDTH = 400;
81 const int VINSPECTOR_DEFAULT_HISTORY_VIEW_HEIGHT = 50;
82
83 const int VINSPECTOR_DEFAULT_VIEW_POSITION_X = 200 + 900 + 100; // TINSPECTOR_DEFAULT_POSITION_X + TINSPECTOR_DEFAULT_WIDTH + 100
84 const int VINSPECTOR_DEFAULT_VIEW_POSITION_Y = 60; // TINSPECTOR_DEFAULT_POSITION_Y + 50
85
86 // =======================================================================
87 // function : Constructor
88 // purpose :
89 // =======================================================================
90 VInspector_Window::VInspector_Window()
91 : myParent (0), myExportToShapeViewDialog (0), myViewWindow (0)
92 {
93   myDisplayer = new View_Displayer();
94
95   myMainWindow = new QMainWindow (0);
96
97   QWidget* aCentralWidget = new QWidget (myMainWindow);
98   QGridLayout* aParentLay = new QGridLayout (aCentralWidget);
99   aParentLay->setContentsMargins (0, 0, 0, 0);
100   aParentLay->setSpacing(0);
101
102   // restore state of tool bar: on the bottom of the window
103   myToolBar = new VInspector_ToolBar(aCentralWidget);
104   connect (myToolBar, SIGNAL (actionClicked (int)), this, SLOT (onToolBarActionClicked (int)));
105   aParentLay->addWidget (myToolBar->GetControl(), 0, 0);
106
107   // tree view
108   myTreeView = new QTreeView (aCentralWidget);
109   myTreeView->setSelectionBehavior (QAbstractItemView::SelectRows);
110   myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection);
111   myTreeView->header()->setStretchLastSection (true);
112   myTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
113   VInspector_ViewModel* aTreeModel = new VInspector_ViewModel (myTreeView);
114   aTreeModel->InitColumns();
115   myTreeView->setModel (aTreeModel);
116   // hide Visibility column
117   TreeModel_HeaderSection anItem = aTreeModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility);
118   anItem.SetIsHidden (true);
119   aTreeModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem);
120
121   connect (myTreeView, SIGNAL(customContextMenuRequested(const QPoint&)),
122            this, SLOT (onTreeViewContextMenuRequested(const QPoint&)));
123   new TreeModel_ContextMenu (myTreeView);
124
125   QItemSelectionModel* aSelModel = new QItemSelectionModel (myTreeView->model(), myTreeView);
126   myTreeView->setSelectionModel (aSelModel);
127   connect (aSelModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
128            this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
129
130   aParentLay->addWidget(myTreeView, 1, 0);
131   aParentLay->setRowStretch (1, 1);
132   myMainWindow->setCentralWidget (aCentralWidget);
133
134   // property view
135   myPropertyView = new ViewControl_PropertyView (myMainWindow,
136     QSize(VINSPECTOR_DEFAULT_PROPERTY_VIEW_WIDTH, VINSPECTOR_DEFAULT_PROPERTY_VIEW_HEIGHT));
137   myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow);
138   myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle());
139   myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow));
140   myPropertyPanelWidget->setWidget (myPropertyView->GetControl());
141   myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget);
142   connect (myPropertyPanelWidget->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT (onPropertyPanelShown (bool)));
143
144   myHistoryView = new ViewControl_TreeView (myMainWindow);
145   myHistoryView->setSelectionBehavior (QAbstractItemView::SelectRows);
146   ((ViewControl_TreeView*)myHistoryView)->SetPredefinedSize (QSize (VINSPECTOR_DEFAULT_HISTORY_VIEW_WIDTH,
147                                                                     VINSPECTOR_DEFAULT_HISTORY_VIEW_HEIGHT));
148   myHistoryView->setContextMenuPolicy (Qt::CustomContextMenu);
149   myHistoryView->header()->setStretchLastSection (true);
150   new TreeModel_ContextMenu (myHistoryView);
151
152   myHistoryView->setSelectionMode (QAbstractItemView::ExtendedSelection);
153   VInspector_ViewModelHistory* aHistoryModel = new VInspector_ViewModelHistory (myHistoryView);
154   aHistoryModel->InitColumns();
155   myHistoryView->setModel (aHistoryModel);
156
157   QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aHistoryModel);
158   myHistoryView->setSelectionModel (aSelectionModel);
159   connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)),
160     this, SLOT (onHistoryViewSelectionChanged (const QItemSelection&, const QItemSelection&)));
161
162   anItem = aHistoryModel->GetHeaderItem (0);
163   // hide Visibility column
164   TreeModel_Tools::UseVisibilityColumn (myHistoryView, false);
165   anItem = aHistoryModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility);
166   anItem.SetIsHidden (true);
167   aHistoryModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem);
168
169   QModelIndex aParentIndex = myHistoryView->model()->index (0, 0);
170   myHistoryView->setExpanded (aParentIndex, true);
171
172   QDockWidget* aHistoryDockWidget = new QDockWidget (tr ("HistoryView"), myMainWindow);
173   aHistoryDockWidget->setObjectName (aHistoryDockWidget->windowTitle());
174   aHistoryDockWidget->setTitleBarWidget (new QWidget(myMainWindow));
175   aHistoryDockWidget->setWidget (myHistoryView);
176   myMainWindow->addDockWidget (Qt::BottomDockWidgetArea, aHistoryDockWidget);
177
178   myMainWindow->resize (450, 800);
179   myMainWindow->move (60, 20);
180
181   myMainWindow->resize (VINSPECTOR_DEFAULT_WIDTH, VINSPECTOR_DEFAULT_HEIGHT);
182   myMainWindow->move (VINSPECTOR_DEFAULT_POSITION_X, VINSPECTOR_DEFAULT_POSITION_Y);
183 }
184
185 // =======================================================================
186 // function : SetParent
187 // purpose :
188 // =======================================================================
189 void VInspector_Window::SetParent (void* theParent)
190 {
191   myParent = (QWidget*)theParent;
192   if (!myParent)
193     return;
194
195   QLayout* aLayout = myParent->layout();
196   if (aLayout)
197     aLayout->addWidget (GetMainWindow());
198 }
199
200 // =======================================================================
201 // function : FillActionsMenu
202 // purpose :
203 // =======================================================================
204 void VInspector_Window::FillActionsMenu (void* theMenu)
205 {
206   QMenu* aMenu = (QMenu*)theMenu;
207   QList<QDockWidget*> aDockwidgets = myMainWindow->findChildren<QDockWidget*>();
208   for (QList<QDockWidget*>::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it)
209   {
210     QDockWidget* aDockWidget = *it;
211     if (aDockWidget->parentWidget() == myMainWindow)
212       aMenu->addAction (aDockWidget->toggleViewAction());
213   }
214 }
215
216 // =======================================================================
217 // function : GetPreferences
218 // purpose :
219 // =======================================================================
220 void VInspector_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem)
221 {
222   theItem.Bind ("geometry",  TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str());
223
224   QMap<QString, QString> anItems;
225   TreeModel_Tools::SaveState (myTreeView, anItems);
226   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
227   {
228     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
229   }
230
231   anItems.clear();
232   View_PreviewParameters::SaveState (displayer()->DisplayPreview()->GetPreviewParameters(), anItems, "preview_parameters_");
233   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
234     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
235
236   anItems.clear();
237   TreeModel_Tools::SaveState (myTreeView, anItems);
238   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
239   {
240     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
241   }
242
243   anItems.clear();
244   ViewControl_PropertyView::SaveState (myPropertyView, anItems, "property_view_parameters_");
245   for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
246     theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
247
248   if (myViewWindow)
249   {
250     anItems.clear();
251     View_Window::SaveState(myViewWindow, anItems);
252     for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
253       theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
254   }
255 }
256
257 // =======================================================================
258 // function : SetPreferences
259 // purpose :
260 // =======================================================================
261 void VInspector_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem)
262 {
263   if (theItem.IsEmpty())
264   {
265     TreeModel_Tools::SetDefaultHeaderSections (myTreeView);
266     TreeModel_Tools::SetDefaultHeaderSections (myHistoryView);
267     return;
268   }
269
270   for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next())
271   {
272     TCollection_AsciiString anItemKey = anItemIt.Key();
273     TCollection_AsciiString anItemValue = anItemIt.Value();
274     if (anItemKey.IsEqual ("geometry"))
275       myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemValue.ToCString()));
276     else if (TreeModel_Tools::RestoreState (myTreeView, anItemKey.ToCString(), anItemValue.ToCString()))
277       continue;
278     else if (TreeModel_Tools::RestoreState (myHistoryView, anItemKey.ToCString(), anItemValue.ToCString(),
279                                             "history_view_"))
280       continue;
281     else if (View_PreviewParameters::RestoreState (displayer()->DisplayPreview()->GetPreviewParameters(), anItemKey.ToCString(),
282       anItemValue.ToCString(), "preview_parameters_"))
283       continue;
284     else if (ViewControl_PropertyView::RestoreState (myPropertyView, anItemKey.ToCString(),
285       anItemValue.ToCString(), "property_view_parameters_"))
286       continue;
287     else if (myViewWindow && View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
288       continue;
289   }
290 }
291
292 // =======================================================================
293 // function : UpdateContent
294 // purpose :
295 // =======================================================================
296 void VInspector_Window::UpdateContent()
297 {
298   TCollection_AsciiString aName = "TKVInspector";
299
300   bool isModelUpdated = false;
301   if (myParameters->FindParameters (aName))
302     isModelUpdated = Init (myParameters->Parameters (aName));
303   if (myParameters->FindFileNames (aName))
304   {
305     for (NCollection_List<TCollection_AsciiString>::Iterator aFileNamesIt (myParameters->FileNames (aName));
306          aFileNamesIt.More(); aFileNamesIt.Next())
307          isModelUpdated = OpenFile (aFileNamesIt.Value()) || isModelUpdated;
308
309     NCollection_List<TCollection_AsciiString> aNames;
310     myParameters->SetFileNames (aName, aNames);
311   }
312   if (!isModelUpdated)
313     UpdateTreeModel();
314
315   // make AIS_InteractiveObject selected selected if exist in select parameters
316   NCollection_List<Handle(Standard_Transient)> anObjects;
317   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*>(myTreeView->model());
318   if (aViewModel && myParameters->GetSelectedObjects(aName, anObjects))
319   {
320     QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
321     aSelectionModel->clear();
322     for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (anObjects);
323          aParamsIt.More(); aParamsIt.Next())
324     {
325       Handle(Standard_Transient) anObject = aParamsIt.Value();
326       Handle(AIS_InteractiveObject) aPresentation = Handle(AIS_InteractiveObject)::DownCast (anObject);
327       if (aPresentation.IsNull())
328         continue;
329
330       QModelIndex aPresentationIndex = aViewModel->FindIndex (aPresentation);
331       if (!aPresentationIndex.isValid())
332         continue;
333        aSelectionModel->select (aPresentationIndex, QItemSelectionModel::Select);
334        myTreeView->scrollTo (aPresentationIndex);
335     }
336   }
337
338   if (!myCallBack.IsNull())
339   {
340     VInspector_ViewModelHistory* aHistoryModel = dynamic_cast<VInspector_ViewModelHistory*>
341       (myHistoryView->model());
342     aHistoryModel->Reset();
343     aHistoryModel->EmitLayoutChanged();
344   }
345 }
346
347 // =======================================================================
348 // function : SelectedPresentations
349 // purpose :
350 // =======================================================================
351 NCollection_List<Handle(AIS_InteractiveObject)> VInspector_Window::SelectedPresentations (QItemSelectionModel* theModel)
352 {
353   NCollection_List<Handle(AIS_InteractiveObject)> aSelectedPresentations;
354
355   QList<TreeModel_ItemBasePtr> anItems = TreeModel_ModelBase::SelectedItems (theModel->selectedIndexes());
356
357   QList<size_t> aSelectedIds; // Remember of selected address in order to avoid duplicates
358   NCollection_List<Handle(Standard_Transient)> anItemPresentations;
359   for (QList<TreeModel_ItemBasePtr>::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt)
360   {
361     TreeModel_ItemBasePtr anItem = *anItemIt;
362     VInspector_ItemBasePtr aVItem = itemDynamicCast<VInspector_ItemBase>(anItem);
363     if (!aVItem)
364       continue;
365
366     anItemPresentations.Clear();
367     aVItem->Presentations (anItemPresentations);
368
369     for (NCollection_List<Handle(Standard_Transient)>::Iterator anIt (anItemPresentations); anIt.More(); anIt.Next())
370     {
371       Handle(AIS_InteractiveObject) aPresentation = Handle(AIS_InteractiveObject)::DownCast (anIt.Value());
372       if (aSelectedIds.contains ((size_t)aPresentation.get()))
373         continue;
374       aSelectedIds.append ((size_t)aPresentation.get());
375       if (!aPresentation.IsNull())
376         aSelectedPresentations.Append (aPresentation);
377     }
378   }
379   return aSelectedPresentations;
380 }
381
382 // =======================================================================
383 // function : SelectedShapes
384 // purpose :
385 // =======================================================================
386 void VInspector_Window::SelectedShapes (NCollection_List<Handle(Standard_Transient)>& theSelPresentations)
387 {
388   QModelIndexList theIndices = myTreeView->selectionModel()->selectedIndexes();
389
390   QList<TreeModel_ItemBasePtr> anItems = TreeModel_ModelBase::SelectedItems (theIndices);
391   for (QList<TreeModel_ItemBasePtr>::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt)
392   {                                                                                                                  
393     TreeModel_ItemBasePtr anItem = *anItemIt;
394     VInspector_ItemBasePtr aVItem = itemDynamicCast<VInspector_ItemBase>(anItem);
395     if (!aVItem /*|| aVItem->Row() == 0*/)
396     {
397       anItem->Presentations (theSelPresentations);
398       continue;
399     }
400
401     TopoDS_Shape aShape = aVItem->GetPresentationShape();
402     if (aShape.IsNull())
403       continue;
404
405     theSelPresentations.Append (new Convert_TransientShape (aShape));
406   }
407 }
408
409 // =======================================================================
410 // function : Init
411 // purpose :
412 // =======================================================================
413 bool VInspector_Window::Init (const NCollection_List<Handle(Standard_Transient)>& theParameters)
414 {
415   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
416   if (!aViewModel)
417     return Standard_False;
418
419   Handle(AIS_InteractiveContext) aContext;
420   Handle(VInspector_CallBack) aCallBack;
421   Standard_Boolean isModelUpdated = Standard_False;
422
423   for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (theParameters); aParamsIt.More(); aParamsIt.Next())
424   {
425     Handle(Standard_Transient) anObject = aParamsIt.Value();
426     if (aContext.IsNull())
427       aContext = Handle(AIS_InteractiveContext)::DownCast (anObject);
428
429     if (aCallBack.IsNull())
430       aCallBack = Handle(VInspector_CallBack)::DownCast (anObject);
431   }
432   if (aViewModel->GetContext() != aContext)
433     SetContext(aContext);
434   else
435     isModelUpdated = Standard_True;
436
437   if (!aCallBack.IsNull() && aCallBack != myCallBack)
438   {
439     myCallBack = aCallBack;
440     VInspector_ViewModelHistory* aHistoryModel = dynamic_cast<VInspector_ViewModelHistory*>
441       (myHistoryView->model());
442     myCallBack->SetContext(aContext);
443     myCallBack->SetHistoryModel(aHistoryModel);
444   }
445
446   if (isModelUpdated)
447     UpdateTreeModel();
448
449   return true;
450 }
451
452 // =======================================================================
453 // function : SetContext
454 // purpose :
455 // =======================================================================
456 void VInspector_Window::SetContext (const Handle(AIS_InteractiveContext)& theContext)
457 {
458   if (theContext.IsNull())
459     return;
460
461   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
462   aViewModel->SetContext (theContext);
463   myTreeView->setExpanded (aViewModel->index (0, 0), true);
464
465   if (!myCallBack.IsNull())
466     myCallBack->SetContext (theContext);
467
468   if (myDisplayer)
469     myDisplayer->SetContext (theContext);
470 }
471
472 // =======================================================================
473 // function : OpenFile
474 // purpose :
475 // =======================================================================
476 bool VInspector_Window::OpenFile(const TCollection_AsciiString& theFileName)
477 {
478   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
479   if (!aViewModel)
480     return false;
481
482   Handle(AIS_InteractiveContext) aContext = aViewModel->GetContext();
483   bool isModelUpdated = false;
484   if (aContext.IsNull())
485   {
486     aContext = createView();
487     SetContext (aContext);
488     isModelUpdated = true;
489   }
490
491   TopoDS_Shape aShape = Convert_Tools::ReadShape (theFileName);
492   if (aShape.IsNull())
493     return isModelUpdated;
494
495   Handle(AIS_Shape) aPresentation = new AIS_Shape (aShape);
496   View_Displayer* aDisplayer = myViewWindow->Displayer();
497   aDisplayer->DisplayPresentation (aPresentation);
498   aContext->UpdateCurrentViewer();
499
500   UpdateTreeModel();
501   myTreeView->setExpanded (aViewModel->index (0, 0), true);
502   return true;
503 }
504
505 // =======================================================================
506 // function : onTreeViewContextMenuRequested
507 // purpose :
508 // =======================================================================
509 void VInspector_Window::onTreeViewContextMenuRequested(const QPoint& thePosition)
510 {
511   QMenu* aMenu = new QMenu (GetMainWindow());
512   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export to ShapeView"), SLOT (onExportToShapeView()), GetMainWindow(), this));
513   aMenu->addSeparator();
514
515   QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (myTreeView->selectionModel()->selectedIndexes(), 0);
516   TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
517   if (anItemBase)
518   {
519     if (itemDynamicCast<VInspector_ItemContext> (anItemBase))
520     {
521       aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export to MessageView"), SLOT (onExportToMessageView()), GetMainWindow(), this));
522       aMenu->addSeparator();
523     }
524   }
525
526   aMenu->addSeparator();
527   for (int aTypeId = (int)View_DisplayActionType_DisplayId; aTypeId <= (int)View_DisplayActionType_RemoveId; aTypeId++)
528   {
529     aMenu->addAction (ViewControl_Tools::CreateAction (VInspector_Tools::DisplayActionTypeToString ((View_DisplayActionType) aTypeId),
530                       SLOT (onDisplayActionTypeClicked()), GetMainWindow(), this));
531   }
532   aMenu->addSeparator();
533
534   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand"), SLOT (onExpand()), GetMainWindow(), this));
535   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Expand All"), SLOT (onExpandAll()), GetMainWindow(), this));
536   aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Collapse All"), SLOT (onCollapseAll()), GetMainWindow(), this));
537
538   aMenu->addSeparator();
539   aMenu->addAction (ViewControl_Tools::CreateAction ("Test AddChild", SLOT (OnTestAddChild()), GetMainWindow(), this));
540
541   QPoint aPoint = myTreeView->mapToGlobal (thePosition);
542   aMenu->exec(aPoint);
543 }
544
545 // =======================================================================
546 // function : onToolBarActionClicked
547 // purpose :
548 // =======================================================================
549 void VInspector_Window::onToolBarActionClicked (const int theActionId)
550 {
551   VInspector_ViewModel* aViewModel = dynamic_cast<VInspector_ViewModel*> (myTreeView->model());
552   if (!aViewModel)
553     return;
554
555   switch (theActionId)
556   {
557     case VInspector_ToolActionType_UpdateId:
558     {
559       UpdateTreeModel();
560       break;
561     }
562     default:
563       break;
564   }
565 }
566
567 // =======================================================================
568 // function : onPropertyPanelShown
569 // purpose :
570 // =======================================================================
571 void VInspector_Window::onPropertyPanelShown (bool isToggled)
572 {
573   if (!isToggled)
574     return;
575
576   myPropertyView->Init (ViewControl_Tools::CreateTableModelValues (myTreeView->selectionModel()));
577 }
578
579 // =======================================================================
580 // function : onTreeViewSelectionChanged
581 // purpose :
582 // =======================================================================
583 void VInspector_Window::onTreeViewSelectionChanged (const QItemSelection&,
584                                                     const QItemSelection&)
585 {
586   if (myPropertyPanelWidget->toggleViewAction()->isChecked())
587     myPropertyView->Init (ViewControl_Tools::CreateTableModelValues (myTreeView->selectionModel()));
588
589   NCollection_List<Handle(Standard_Transient)> aSelPresentations;
590
591   QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes();
592   for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++)
593   {
594     QModelIndex anIndex = *aSelIt;
595     if (anIndex.column() != 0)
596       continue;
597
598     TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
599     if (!anItemBase)
600       continue;
601
602     anItemBase->Presentations (aSelPresentations);
603   }
604
605   SelectedShapes (aSelPresentations);
606   displayer()->UpdatePreview (View_DisplayActionType_DisplayId, aSelPresentations);
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->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 }