1 // Created on: 2017-06-16
2 // Created by: Natalia ERMOLAEVA
3 // Copyright (c) 2017 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <inspector/ShapeView_Window.hxx>
17 #include <inspector/ShapeView_ItemRoot.hxx>
18 #include <inspector/ShapeView_ItemShape.hxx>
19 #include <inspector/ShapeView_TreeModel.hxx>
20 #include <inspector/ShapeView_VisibilityState.hxx>
22 #include <inspector/TreeModel_Tools.hxx>
23 #include <inspector/TreeModel_ContextMenu.hxx>
25 #include <inspector/ViewControl_Tools.hxx>
26 #include <inspector/ViewControl_TreeView.hxx>
28 #include <inspector/View_Displayer.hxx>
29 #include <inspector/View_PresentationType.hxx>
30 #include <inspector/View_Tools.hxx>
31 #include <inspector/View_ToolBar.hxx>
32 #include <inspector/View_Widget.hxx>
33 #include <inspector/View_Window.hxx>
34 #include <inspector/View_Viewer.hxx>
36 #include <inspector/ShapeView_Window.hxx>
37 #include <inspector/ShapeView_OpenFileDialog.hxx>
38 #include <inspector/ShapeView_Tools.hxx>
40 #include <BRep_Builder.hxx>
41 #include <BRepTools.hxx>
43 #include <Standard_WarningsDisable.hxx>
44 #include <QApplication>
47 #include <QDockWidget>
50 #include <QFileDialog>
51 #include <QMainWindow>
53 #include <QPlainTextEdit>
54 #include <QPushButton>
56 #include <QTextStream>
58 #include <QToolButton>
61 #include <QVBoxLayout>
62 #include <Standard_WarningsRestore.hxx>
64 const int DEFAULT_TEXT_VIEW_WIDTH = 800;
65 const int DEFAULT_TEXT_VIEW_HEIGHT = 700;
66 const int DEFAULT_TEXT_VIEW_POSITION_X = 430;
67 const int DEFAULT_TEXT_VIEW_POSITION_Y = 30;
68 const int DEFAULT_TEXT_VIEW_DELTA = 100;
70 const int DEFAULT_SHAPE_VIEW_WIDTH = 900;
71 const int DEFAULT_SHAPE_VIEW_HEIGHT = 450;
72 const int DEFAULT_SHAPE_VIEW_POSITION_X = 60;
73 const int DEFAULT_SHAPE_VIEW_POSITION_Y = 60;
75 const int SHAPEVIEW_DEFAULT_TREE_VIEW_WIDTH = 600;
76 const int SHAPEVIEW_DEFAULT_TREE_VIEW_HEIGHT = 500;
78 const int SHAPEVIEW_DEFAULT_VIEW_WIDTH = 300;
79 const int SHAPEVIEW_DEFAULT_VIEW_HEIGHT = 1000;
81 // =======================================================================
82 // function : Constructor
84 // =======================================================================
85 ShapeView_Window::ShapeView_Window (QWidget* theParent)
86 : QObject (theParent), myNextPosition (0)
88 myMainWindow = new QMainWindow (theParent);
90 myTreeView = new ViewControl_TreeView (myMainWindow);
91 ((ViewControl_TreeView*)myTreeView)->SetPredefinedSize (QSize (SHAPEVIEW_DEFAULT_TREE_VIEW_WIDTH,
92 SHAPEVIEW_DEFAULT_TREE_VIEW_HEIGHT));
93 myTreeView->setContextMenuPolicy (Qt::CustomContextMenu);
94 connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)),
95 this, SLOT (onTreeViewContextMenuRequested (const QPoint&)));
96 new TreeModel_ContextMenu (myTreeView);
97 ShapeView_TreeModel* aModel = new ShapeView_TreeModel (myTreeView);
98 myTreeView->setModel (aModel);
99 ShapeView_VisibilityState* aVisibilityState = new ShapeView_VisibilityState (aModel);
100 aModel->SetVisibilityState (aVisibilityState);
101 TreeModel_Tools::UseVisibilityColumn (myTreeView);
103 QModelIndex aParentIndex = myTreeView->model()->index (0, 0);
104 myTreeView->setExpanded (aParentIndex, true);
105 myMainWindow->setCentralWidget (myTreeView);
108 myViewWindow = new View_Window (myMainWindow, false);
109 connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed()));
110 aVisibilityState->SetDisplayer (myViewWindow->GetDisplayer());
111 aVisibilityState->SetPresentationType (View_PresentationType_Main);
112 myViewWindow->GetView()->SetPredefinedSize (SHAPEVIEW_DEFAULT_VIEW_WIDTH, SHAPEVIEW_DEFAULT_VIEW_HEIGHT);
114 QDockWidget* aViewDockWidget = new QDockWidget (tr ("View"), myMainWindow);
115 aViewDockWidget->setObjectName (aViewDockWidget->windowTitle());
116 aViewDockWidget->setWidget (myViewWindow);
117 aViewDockWidget->setTitleBarWidget (myViewWindow->GetViewToolBar()->GetControl());
118 myMainWindow->addDockWidget (Qt::RightDockWidgetArea, aViewDockWidget);
120 myMainWindow->resize (DEFAULT_SHAPE_VIEW_WIDTH, DEFAULT_SHAPE_VIEW_HEIGHT);
121 myMainWindow->move (DEFAULT_SHAPE_VIEW_POSITION_X, DEFAULT_SHAPE_VIEW_POSITION_Y);
124 // =======================================================================
125 // function : Destructor
127 // =======================================================================
128 ShapeView_Window::~ShapeView_Window()
130 onCloseAllBREPViews();
133 // =======================================================================
134 // function : SetParent
136 // =======================================================================
137 void ShapeView_Window::SetParent (void* theParent)
139 QWidget* aParent = (QWidget*)theParent;
142 QLayout* aLayout = aParent->layout();
144 aLayout->addWidget (GetMainWindow());
148 // =======================================================================
149 // function : FillActionsMenu
151 // =======================================================================
152 void ShapeView_Window::FillActionsMenu (void* theMenu)
154 QMenu* aMenu = (QMenu*)theMenu;
155 QList<QDockWidget*> aDockwidgets = myMainWindow->findChildren<QDockWidget*>();
156 for (QList<QDockWidget*>::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it)
158 QDockWidget* aDockWidget = *it;
159 if (aDockWidget->parentWidget() == myMainWindow)
160 aMenu->addAction (aDockWidget->toggleViewAction());
164 // =======================================================================
165 // function : GetPreferences
167 // =======================================================================
168 void ShapeView_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem)
171 theItem.Bind ("geometry", TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str());
173 QMap<QString, QString> anItems;
174 TreeModel_Tools::SaveState (myTreeView, anItems);
175 View_Tools::SaveState(myViewWindow, anItems);
176 for (QMap<QString, QString>::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++)
177 theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str());
180 // =======================================================================
181 // function : SetPreferences
183 // =======================================================================
184 void ShapeView_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem)
186 if (theItem.IsEmpty())
188 TreeModel_Tools::SetDefaultHeaderSections (myTreeView);
192 for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next())
194 if (anItemIt.Key().IsEqual ("geometry"))
195 myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemIt.Value().ToCString()));
196 else if (TreeModel_Tools::RestoreState (myTreeView, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
198 else if (View_Tools::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString()))
203 // =======================================================================
204 // function : UpdateContent
206 // =======================================================================
207 void ShapeView_Window::UpdateContent()
209 TCollection_AsciiString aName = "TKShapeView";
210 if (myParameters->FindParameters (aName))
212 NCollection_List<Handle(Standard_Transient)> aParameters = myParameters->Parameters (aName);
213 // Init will remove from parameters those, that are processed only one time (TShape)
215 myParameters->SetParameters (aName, aParameters);
217 if (myParameters->FindFileNames(aName))
219 for (NCollection_List<TCollection_AsciiString>::Iterator aFilesIt(myParameters->FileNames(aName));
220 aFilesIt.More(); aFilesIt.Next())
221 OpenFile (aFilesIt.Value());
223 NCollection_List<TCollection_AsciiString> aNames;
224 myParameters->SetFileNames (aName, aNames);
226 // make TopoDS_TShape selected if exist in select parameters
227 NCollection_List<Handle(Standard_Transient)> anObjects;
228 if (myParameters->GetSelectedObjects(aName, anObjects))
230 ShapeView_TreeModel* aModel = dynamic_cast<ShapeView_TreeModel*> (myTreeView->model());
231 QItemSelectionModel* aSelectionModel = myTreeView->selectionModel();
232 aSelectionModel->clear();
233 for (NCollection_List<Handle(Standard_Transient)>::Iterator aParamsIt (anObjects);
234 aParamsIt.More(); aParamsIt.Next())
236 Handle(Standard_Transient) anObject = aParamsIt.Value();
237 Handle(TopoDS_TShape) aShapePointer = Handle(TopoDS_TShape)::DownCast (anObject);
238 if (aShapePointer.IsNull())
242 aShape.TShape (aShapePointer);
244 QModelIndex aShapeIndex = aModel->FindIndex (aShape);
245 if (!aShapeIndex.isValid())
247 aSelectionModel->select (aShapeIndex, QItemSelectionModel::Select);
248 myTreeView->scrollTo (aShapeIndex);
250 myParameters->SetSelected (aName, NCollection_List<Handle(Standard_Transient)>());
254 // =======================================================================
257 // =======================================================================
258 void ShapeView_Window::Init (NCollection_List<Handle(Standard_Transient)>& theParameters)
260 Handle(AIS_InteractiveContext) aContext;
261 NCollection_List<Handle(Standard_Transient)> aParameters;
263 TCollection_AsciiString aPluginName ("TKShapeView");
264 NCollection_List<TCollection_AsciiString> aSelectedParameters;
265 if (myParameters->FindSelectedNames (aPluginName)) // selected names have TShape parameters
266 aSelectedParameters = myParameters->GetSelectedNames (aPluginName);
268 NCollection_List<TCollection_AsciiString>::Iterator aParamsIt (aSelectedParameters);
269 for (NCollection_List<Handle(Standard_Transient)>::Iterator anObjectsIt (theParameters);
270 anObjectsIt.More(); anObjectsIt.Next())
272 Handle(Standard_Transient) anObject = anObjectsIt.Value();
273 Handle(TopoDS_TShape) aShapePointer = Handle(TopoDS_TShape)::DownCast (anObject);
274 if (!aShapePointer.IsNull())
277 aShape.TShape (aShapePointer);
278 if (aParamsIt.More())
280 // each Transient object has own location/orientation description
281 TInspectorAPI_PluginParameters::ParametersToShape (aParamsIt.Value(), aShape);
288 aParameters.Append (anObject);
289 if (aContext.IsNull())
290 aContext = Handle(AIS_InteractiveContext)::DownCast (anObject);
293 if (!aContext.IsNull())
294 myViewWindow->SetContext (View_ContextType_External, aContext);
296 theParameters = aParameters;
297 myParameters->SetSelectedNames (aPluginName, NCollection_List<TCollection_AsciiString>());
300 // =======================================================================
301 // function : OpenFile
303 // =======================================================================
304 void ShapeView_Window::OpenFile(const TCollection_AsciiString& theFileName)
306 TopoDS_Shape aShape = ShapeView_Tools::ReadShape (theFileName);
307 if (!aShape.IsNull())
311 // =======================================================================
312 // function : RemoveAllShapes
314 // =======================================================================
315 void ShapeView_Window::RemoveAllShapes()
317 ShapeView_TreeModel* aModel = dynamic_cast<ShapeView_TreeModel*> (myTreeView->model());
318 aModel->RemoveAllShapes();
320 onCloseAllBREPViews();
323 // =======================================================================
324 // function : addShape
326 // =======================================================================
327 void ShapeView_Window::addShape (const TopoDS_Shape& theShape)
329 ShapeView_TreeModel* aModel = dynamic_cast<ShapeView_TreeModel*> (myTreeView->model());
330 aModel->AddShape (theShape);
333 // =======================================================================
334 // function : onTreeViewContextMenuRequested
336 // =======================================================================
337 void ShapeView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition)
339 QItemSelectionModel* aModel = myTreeView->selectionModel();
343 QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0);
344 TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex);
348 QMenu* aMenu = new QMenu(myMainWindow);
349 ShapeView_ItemRootPtr aRootItem = itemDynamicCast<ShapeView_ItemRoot> (anItemBase);
351 aMenu->addAction (ViewControl_Tools::CreateAction ("Load BREP file", SLOT (onLoadFile()), myMainWindow, this));
352 aMenu->addAction (ViewControl_Tools::CreateAction ("Remove all shape items", SLOT (onClearView()), myMainWindow, this));
355 if (!GetTemporaryDirectory().IsEmpty())
356 aMenu->addAction (ViewControl_Tools::CreateAction ("BREP view", SLOT (onBREPView()), myMainWindow, this));
357 aMenu->addAction (ViewControl_Tools::CreateAction ("Close All BREP views", SLOT (onCloseAllBREPViews()), myMainWindow, this));
358 aMenu->addAction (ViewControl_Tools::CreateAction ("BREP directory", SLOT (onBREPDirectory()), myMainWindow, this));
361 QPoint aPoint = myTreeView->mapToGlobal (thePosition);
362 aMenu->exec (aPoint);
365 // =======================================================================
366 // function : onEraseAllPerformed
368 // =======================================================================
369 void ShapeView_Window::onEraseAllPerformed()
371 ShapeView_TreeModel* aTreeModel = dynamic_cast<ShapeView_TreeModel*> (myTreeView->model());
373 // TODO: provide update for only visibility state for better performance TopoDS_Shape myCustomShape;
376 aTreeModel->EmitLayoutChanged();
379 // =======================================================================
380 // function : onBREPDirectory
382 // =======================================================================
383 void ShapeView_Window::onBREPDirectory()
385 QString aFilter (tr ("BREP file (*.brep*)"));
386 QString aSelectedFilter;
387 QString aFileName = QFileDialog::getOpenFileName (0, tr ("Export shape to BREP file"),
388 GetTemporaryDirectory().ToCString(), aSelectedFilter);
389 if (!aFileName.isEmpty())
390 viewFile (aFileName);
393 // =======================================================================
394 // function : onLoadFile
396 // =======================================================================
397 void ShapeView_Window::onLoadFile()
399 QString aDataDirName = QDir::currentPath();
401 QString aFileName = ShapeView_OpenFileDialog::OpenFile(0, aDataDirName);
402 aFileName = QDir().toNativeSeparators (aFileName);
403 if (!aFileName.isEmpty())
404 onOpenFile(aFileName);
407 // =======================================================================
408 // function : onBREPView
410 // =======================================================================
411 void ShapeView_Window::onBREPView()
413 if (GetTemporaryDirectory().IsEmpty())
416 QItemSelectionModel* aModel = myTreeView->selectionModel();
420 QModelIndexList aSelectedRows = aModel->selectedRows();
421 if (aSelectedRows.size() == 0)
424 QModelIndex aSelectedIndex = aSelectedRows.at (0);
425 TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (aSelectedIndex);
429 ShapeView_ItemShapePtr anItem = itemDynamicCast<ShapeView_ItemShape>(anItemBase);
433 QString aFileName = anItem->GetFileName();
435 if (aFileName.isEmpty() || !aDir.exists (aFileName))
437 TCollection_AsciiString aFileNameIndiced = GetTemporaryDirectory() + TCollection_AsciiString ("\\") +
438 getNextTmpName (anItem->TShapePointer());
439 const TopoDS_Shape& aShape = anItem->GetItemShape();
440 BRepTools::Write (aShape, aFileNameIndiced.ToCString());
441 anItem->SetFileName (aFileNameIndiced.ToCString());
442 aFileName = aFileNameIndiced.ToCString();
444 viewFile (aFileName);
447 // =======================================================================
448 // function : onCloseAllBREPViews
450 // =======================================================================
451 void ShapeView_Window::onCloseAllBREPViews()
455 for (int aViewId = myBREPViews.size()-1; aViewId >= 0; aViewId--)
456 delete myBREPViews[aViewId];
461 // =======================================================================
462 // function : onEditorDestroyed
464 // =======================================================================
465 void ShapeView_Window::onEditorDestroyed(QObject* theObject)
467 QWidget* aWidget = dynamic_cast<QWidget*> (theObject);
469 for (int aViewId = myBREPViews.size()-1; aViewId >= 0; aViewId--)
471 if (myBREPViews[aViewId] == aWidget)
472 myBREPViews.removeAll(aWidget);
476 // =======================================================================
477 // function : viewFile
479 // =======================================================================
480 void ShapeView_Window::viewFile (const QString& theFileName)
482 QApplication::setOverrideCursor (Qt::WaitCursor);
484 QFile aFile (theFileName);
485 if (aFile.open (QIODevice::ReadOnly | QIODevice::Text))
487 QTextStream aStream(&aFile);
488 QString aLine = aStream.readLine();
489 while (!aLine.isNull())
491 aLine = aStream.readLine();
492 aFileText.append (aLine + QString ("\n"));
494 if (!aFileText.isEmpty())
496 QPlainTextEdit* anEditor = new QPlainTextEdit (0);
497 anEditor->setAttribute (Qt::WA_DeleteOnClose, true);
498 connect (anEditor, SIGNAL (destroyed(QObject*)), this, SLOT (onEditorDestroyed(QObject*)));
499 anEditor->setPlainText (aFileText);
500 anEditor->resize (DEFAULT_TEXT_VIEW_WIDTH, DEFAULT_TEXT_VIEW_HEIGHT);
501 anEditor->move (DEFAULT_TEXT_VIEW_POSITION_X + myNextPosition, DEFAULT_TEXT_VIEW_POSITION_Y);
502 myNextPosition += DEFAULT_TEXT_VIEW_DELTA;
504 myBREPViews.append (anEditor);
507 QApplication::restoreOverrideCursor();
510 // =======================================================================
511 // function : removeBREPFiles
513 // =======================================================================
514 void ShapeView_Window::removeBREPFiles()
516 QDir aDir (GetTemporaryDirectory().ToCString());
518 QStringList anEntries = aDir.entryList();
519 QString aPrefix(viewBREPPrefix().ToCString());
520 for (int anEntryId = 0, aSize = anEntries.size(); anEntryId < aSize; anEntryId++)
522 if (anEntries[anEntryId].contains (aPrefix))
523 aDir.remove (anEntries[anEntryId]);
527 // =======================================================================
528 // function : getNextTmpName
530 // =======================================================================
531 TCollection_AsciiString ShapeView_Window::getNextTmpName (const TCollection_AsciiString& thePointerInfo)
533 TCollection_AsciiString aTmpName(viewBREPPrefix());
534 aTmpName += thePointerInfo;