From: nds Date: Tue, 27 Oct 2020 16:24:59 +0000 (+0300) Subject: 0031362: Inspectors - MessageView plugin for message alerts X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=815c9d8df799e1f6eeca2fe76f6df4326ef0df13;p=occt-copy.git 0031362: Inspectors - MessageView plugin for message alerts - OSD_Timer in message alert, - DumpJson correction, - Selection owner should be dumped in selector. Sensitive entities might be used in the same owner, that leads to lots of the same dump in the result stream. - Inspector tools improvements (cherry picked from commit e8bde810616e61cbe925981176681f2840234fa4) # Conflicts: # src/Message/Message_Alert.hxx # src/Message/Message_Attribute.hxx # src/Message/Message_AttributeMeter.cxx # src/Message/Message_AttributeObject.hxx # src/Message/Message_AttributeStream.cxx # src/Message/Message_AttributeStream.hxx # src/Message/Message_CompositeAlerts.cxx # src/Message/Message_CompositeAlerts.hxx # src/Message/Message_MetricType.hxx # src/Message/Message_PrinterToReport.cxx # src/Message/Message_PrinterToReport.hxx # src/Message/Message_Report.cxx # src/Message/Message_Report.hxx # src/TopoDS/TopoDS_AlertAttribute.hxx # tools/MessageModel/MessageModel_Actions.cxx # tools/MessageModel/MessageModel_ItemAlert.cxx # tools/MessageModel/MessageModel_ItemReport.cxx # tools/MessageModel/MessageModel_TreeModel.cxx # tools/MessageView/MessageView_Window.cxx # tools/MessageView/MessageView_Window.hxx # tools/TInspectorEXE/TInspectorEXE.cxx # tools/TreeModel/TreeModel_ModelBase.cxx --- diff --git a/src/Message/Message.cxx b/src/Message/Message.cxx index 9dc3a7107e..31cc7a7632 100644 --- a/src/Message/Message.cxx +++ b/src/Message/Message.cxx @@ -25,10 +25,12 @@ namespace { - static Standard_CString Message_Table_PrintMetricTypeEnum[10] = + static Standard_CString Message_Table_PrintMetricTypeEnum[13] = { - "NONE", "UserTimeCPU", "SystemTimeInfo", "MemPrivate", "MemVirtual", - "MemWorkingSet", "MemWorkingSetPeak", "MemSwapUsage", "MemSwapUsagePeak", "MemHeapUsage" + "NONE", "WallClock", + "ThreadCPUUserTime", "ThreadCPUSystemTime", "ProcessCPUUserTime", "ProcessCPUSystemTime", + "MemPrivate", "MemVirtual", "MemWorkingSet", "MemWorkingSetPeak", + "MemSwapUsage", "MemSwapUsagePeak", "MemHeapUsage" }; } diff --git a/src/Message/Message_AttributeMeter.cxx b/src/Message/Message_AttributeMeter.cxx index d37cc8b7c3..875939ff3d 100644 --- a/src/Message/Message_AttributeMeter.cxx +++ b/src/Message/Message_AttributeMeter.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -128,6 +129,16 @@ void Message_AttributeMeter::SetAlertMetrics (const Handle(Message_AlertExtended const NCollection_IndexedMap& anActiveMetrics = aReport->ActiveMetrics(); // time metrics + if (anActiveMetrics.Contains (Message_MetricType_WallClock)) + { + OSD_Timer aTimer; + aTimer.Start(); + Standard_Real aTime = aTimer.StartTime(); + if (theStartValue) + aMeterAttribute->SetStartValue (Message_MetricType_WallClock, aTime); + else + aMeterAttribute->SetStopValue (Message_MetricType_WallClock, aTime); + } if (anActiveMetrics.Contains (Message_MetricType_ProcessCPUUserTime) || anActiveMetrics.Contains (Message_MetricType_ProcessCPUSystemTime) || anActiveMetrics.Contains (Message_MetricType_ThreadCPUUserTime) || @@ -244,13 +255,7 @@ void Message_AttributeMeter::DumpJson (Standard_OStream& theOStream, for (NCollection_IndexedDataMap::Iterator anIterator (myMetrics); anIterator.More(); anIterator.Next()) { - Message_MetricType aMetricType = anIterator.Key(); - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aMetricType) - - Standard_Real aStartValue = anIterator.Value().first; - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStartValue) - - Standard_Real aStopValue = anIterator.Value().second; - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aStopValue) + OCCT_DUMP_VECTOR_CLASS (theOStream, Message::MetricToString (anIterator.Key()), + 2, anIterator.Value().first, anIterator.Value().second) } } diff --git a/src/Message/Message_AttributeStream.cxx b/src/Message/Message_AttributeStream.cxx index ba0ff7e8a0..3574395584 100644 --- a/src/Message/Message_AttributeStream.cxx +++ b/src/Message/Message_AttributeStream.cxx @@ -47,6 +47,5 @@ void Message_AttributeStream::DumpJson (Standard_OStream& theOStream, OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Message_Attribute) - TCollection_AsciiString aStream = Standard_Dump::Text (myStream); - OCCT_DUMP_FIELD_VALUE_STRING (theOStream, aStream) + OCCT_DUMP_STREAM_VALUE_DUMPED (theOStream, myStream) } diff --git a/src/Message/Message_CompositeAlerts.cxx b/src/Message/Message_CompositeAlerts.cxx index 312b059634..e0a9cafca9 100644 --- a/src/Message/Message_CompositeAlerts.cxx +++ b/src/Message/Message_CompositeAlerts.cxx @@ -171,13 +171,17 @@ void Message_CompositeAlerts::DumpJson (Standard_OStream& theOStream, for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) { + if (myAlerts[i].IsEmpty()) + continue; + Message_Gravity aGravity = (Message_Gravity)i; OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, aGravity) - for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); anIt.Next()) + Standard_Integer anInc = 1; + for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); anIt.Next(), anInc++) { const Handle(Message_Alert)& anAlert = anIt.Value(); - OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anAlert.get()) + OCCT_DUMP_FIELD_VALUES_DUMPED_INC (theOStream, theDepth, anAlert.get(), anInc) } } } diff --git a/src/Message/Message_MetricType.hxx b/src/Message/Message_MetricType.hxx index 89a1ac4799..7f4d2b62f9 100644 --- a/src/Message/Message_MetricType.hxx +++ b/src/Message/Message_MetricType.hxx @@ -18,6 +18,7 @@ enum Message_MetricType { Message_MetricType_None, //!< no computation + Message_MetricType_WallClock, //!< OSD_Timer elapsed time Message_MetricType_ThreadCPUUserTime, //!< OSD_Chronometer::GetThreadCPU user time Message_MetricType_ThreadCPUSystemTime, //!< OSD_Chronometer::GetThreadCPU system time Message_MetricType_ProcessCPUUserTime, //!< OSD_Chronometer::GetProcessCPU user time diff --git a/src/Message/Message_PrinterToReport.cxx b/src/Message/Message_PrinterToReport.cxx index b59c4a1853..289c34b0fe 100644 --- a/src/Message/Message_PrinterToReport.cxx +++ b/src/Message/Message_PrinterToReport.cxx @@ -26,6 +26,18 @@ IMPLEMENT_STANDARD_RTTIEXT(Message_PrinterToReport, Message_Printer) +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +Message_PrinterToReport::~Message_PrinterToReport() +{ + if (!myReport.IsNull()) + { + myReport->UpdateActiveInMessenger(); + } +} + //======================================================================= //function : Report //purpose : @@ -40,6 +52,16 @@ const Handle(Message_Report)& Message_PrinterToReport::Report() const return Message::DefaultReport (Standard_True); } +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void Message_PrinterToReport::SetReport (const Handle(Message_Report)& theReport) +{ + myReport = theReport; + myReport->UpdateActiveInMessenger(); +} + //======================================================================= //function : SendStringStream //purpose : diff --git a/src/Message/Message_PrinterToReport.hxx b/src/Message/Message_PrinterToReport.hxx index 4004b409b5..1ba58332a7 100644 --- a/src/Message/Message_PrinterToReport.hxx +++ b/src/Message/Message_PrinterToReport.hxx @@ -32,14 +32,14 @@ public: Message_PrinterToReport() {} //! Destructor - virtual ~Message_PrinterToReport() {} + Standard_EXPORT ~Message_PrinterToReport(); //! Returns the current or default report Standard_EXPORT const Handle(Message_Report)& Report() const; //! Sets the printer report //! @param theReport report for messages processing, if NULL, the default report is used - void SetReport (const Handle(Message_Report)& theReport) { myReport = theReport; } + Standard_EXPORT void SetReport (const Handle(Message_Report)& theReport); //! Send a string message with specified trace level. //! Stream is converted to string value. diff --git a/src/OSD/OSD_Timer.hxx b/src/OSD/OSD_Timer.hxx index 2b483283bf..897d3442c0 100644 --- a/src/OSD/OSD_Timer.hxx +++ b/src/OSD/OSD_Timer.hxx @@ -79,6 +79,9 @@ public: //! the Timer. Standard_EXPORT virtual void Start() Standard_OVERRIDE; + //! Returns start time in seconds. + Standard_Real StartTime() const { return myTimeStart; } + //! Returns elapsed time in seconds. Standard_EXPORT Standard_Real ElapsedTime() const; diff --git a/src/Select3D/Select3D_SensitiveEntity.cxx b/src/Select3D/Select3D_SensitiveEntity.cxx index 95d94d6300..97bc6a3684 100644 --- a/src/Select3D/Select3D_SensitiveEntity.cxx +++ b/src/Select3D/Select3D_SensitiveEntity.cxx @@ -39,7 +39,7 @@ void Select3D_SensitiveEntity::DumpJson (Standard_OStream& theOStream, Standard_ { OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) - OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myOwnerId.get()) + OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myOwnerId.get()) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySFactor) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, NbSubElements()); diff --git a/src/SelectMgr/SelectMgr_Selection.cxx b/src/SelectMgr/SelectMgr_Selection.cxx index d31eeafd3b..34f60d1469 100644 --- a/src/SelectMgr/SelectMgr_Selection.cxx +++ b/src/SelectMgr/SelectMgr_Selection.cxx @@ -124,6 +124,27 @@ void SelectMgr_Selection::DumpJson (Standard_OStream& theOStream, Standard_Integ { OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) + NCollection_IndexedMap anOwners; + for (NCollection_Vector::Iterator anIterator (myEntities); anIterator.More(); anIterator.Next()) + { + const Handle(SelectMgr_SensitiveEntity)& anEntity = anIterator.Value(); + if (anEntity.IsNull() || anEntity->BaseSensitive().IsNull()) + { + continue; + } + const Handle(SelectMgr_EntityOwner)& anOwner = anEntity->BaseSensitive()->OwnerId(); + if (!anOwners.Contains (anOwner)) + { + anOwners.Add (anOwner); + } + } + + for (NCollection_IndexedMap::Iterator anIterator (anOwners); anIterator.More(); anIterator.Next()) + { + const Handle(SelectMgr_EntityOwner)& anOwner = anIterator.Value(); + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anOwner.get()) + } + for (NCollection_Vector::Iterator anIterator (myEntities); anIterator.More(); anIterator.Next()) { const Handle(SelectMgr_SensitiveEntity)& anEntity = anIterator.Value(); diff --git a/src/Standard/Standard_Dump.cxx b/src/Standard/Standard_Dump.cxx index 49e0d16c3b..27153bf43c 100644 --- a/src/Standard/Standard_Dump.cxx +++ b/src/Standard/Standard_Dump.cxx @@ -24,7 +24,7 @@ void Standard_Dump::AddValuesSeparator (Standard_OStream& theOStream) Standard_SStream aStream; aStream << theOStream.rdbuf(); TCollection_AsciiString aStreamStr = Standard_Dump::Text (aStream); - if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{")) + if (!aStreamStr.IsEmpty() && !aStreamStr.EndsWith ("{") && !aStreamStr.EndsWith (", ")) theOStream << ", "; } @@ -302,9 +302,15 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt Standard_Integer anIndentCount = 0; Standard_Boolean isMassiveValues = Standard_False; - for (Standard_Integer anIndex = 1; anIndex < aStreamStr.Length(); anIndex++) + for (Standard_Integer anIndex = 1; anIndex <= aStreamStr.Length(); anIndex++) { Standard_Character aSymbol = aStreamStr.Value (anIndex); + if (anIndex == 1 && aText.IsEmpty() && aSymbol != '{') + { + // append opening brace for json start + aSymbol = '{'; + anIndex--; + } if (aSymbol == '{') { anIndentCount++; @@ -350,6 +356,18 @@ TCollection_AsciiString Standard_Dump::FormatJson (const Standard_SStream& theSt } else aText += aSymbol; + + if (anIndex == aStreamStr.Length() && aSymbol != '}') + { + // append closing brace for json end + aSymbol = '}'; + + anIndentCount--; + aText += '\n'; + for (int anIndent = 0; anIndent < anIndentCount; anIndent++) + aText += anIndentStr; + aText += aSymbol; + } } return aText; } diff --git a/src/Standard/Standard_Dump.hxx b/src/Standard/Standard_Dump.hxx index d2b294c7d1..01a88e43cc 100644 --- a/src/Standard/Standard_Dump.hxx +++ b/src/Standard/Standard_Dump.hxx @@ -155,6 +155,35 @@ } \ } +//! @def OCCT_DUMP_FIELD_VALUES_DUMPED +//! Append into output value: "Name": { field dumped values } +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own Dump implementation. +//! The macros is recursive. Recursion is stopped when the depth value becomes equal to zero. +//! Depth = -1 is the default value, dump here is unlimited. +#define OCCT_DUMP_FIELD_VALUES_DUMPED_INC(theOStream, theDepth, theField, theIncName) \ +{ \ + if (theDepth != 0 && (void*)(theField) != NULL) \ + { \ + Standard_SStream aFieldStream; \ + (theField)->DumpJson (aFieldStream, theDepth - 1); \ + TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField) + theIncName; \ + Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (aFieldStream)); \ + } \ +} + +//! @def OCCT_DUMP_FIELD_VALUES_DUMPED +//! Append into output value: "Name": { field dumped values } +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own Dump implementation. +//! The macros is recursive. Recursion is stopped when the depth value becomes equal to zero. +//! Depth = -1 is the default value, dump here is unlimited. +#define OCCT_DUMP_STREAM_VALUE_DUMPED(theOStream, theField) \ +{ \ + TCollection_AsciiString aName = Standard_Dump::DumpFieldToName (#theField); \ + Standard_Dump::DumpKeyToClass (theOStream, aName, Standard_Dump::Text (theField)); \ +} + //! @def OCCT_INIT_FIELD_VALUES_DUMPED //! Append into output value: "Name": { field dumped values } //! It computes Dump of the fields. The expected field is a pointer. @@ -267,6 +296,7 @@ public: //! - for '{' append after '\n' and indent to the next value, increment current indent value //! - for '}' append '\n' and current indent before it, decrement indent value //! - for ',' append after '\n' and indent to the next value. If the current symbol is in massive container [], do nothing + //! Covers result with opened and closed brackets on the top level, if it has no symbols there. //! @param theStream source value //! @param theIndent count of ' ' symbols to apply hierarchical indent of the text values //! @return text presentation diff --git a/tools/Convert/Convert_Tools.cxx b/tools/Convert/Convert_Tools.cxx index 411fb1fd40..67803f2494 100644 --- a/tools/Convert/Convert_Tools.cxx +++ b/tools/Convert/Convert_Tools.cxx @@ -1,6 +1,6 @@ -// Created on: 2020-01-25 +// Created on: 2017-06-16 // Created by: Natalia ERMOLAEVA -// Copyright (c) 2020 OPEN CASCADE SAS +// Copyright (c) 2017 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -18,17 +18,17 @@ #include #include -#include -#include -#include -#include -#include #include #include #include -#include #include +#include +#include +#include #include +#include +#include +#include // ======================================================================= // function : ReadShape @@ -44,7 +44,7 @@ TopoDS_Shape Convert_Tools::ReadShape (const TCollection_AsciiString& theFileNam } //======================================================================= -//function : ConvertStreamToPresentations +//function : CreateShape //purpose : //======================================================================= void Convert_Tools::ConvertStreamToPresentations (const Standard_SStream& theSStream, @@ -202,11 +202,61 @@ Standard_Boolean Convert_Tools::CreateShape (const Bnd_OBB& theBoundingBox, Topo //======================================================================= Standard_Boolean Convert_Tools::CreateBoxShape (const gp_Pnt& thePntMin, const gp_Pnt& thePntMax, TopoDS_Shape& theShape) { - BRepPreviewAPI_MakeBox aMakeBox; - aMakeBox.Init (thePntMin, thePntMax); - theShape = aMakeBox.Shape(); + Standard_Boolean aThinOnX = fabs (thePntMin.X() - thePntMax.X()) < Precision::Confusion(); + Standard_Boolean aThinOnY = fabs (thePntMin.Y() - thePntMax.Y()) < Precision::Confusion(); + Standard_Boolean aThinOnZ = fabs (thePntMin.Z() - thePntMax.Z()) < Precision::Confusion(); - return Standard_True; + if (((int)aThinOnX + (int)aThinOnY + (int)aThinOnZ) > 1) // thin box in several directions is a point + { + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeVertex (thePntMin)); + theShape = aCompound; + return Standard_True; + } + + if (aThinOnX || aThinOnY || aThinOnZ) + { + gp_Pnt aPnt1, aPnt2, aPnt3, aPnt4 ; + if (aThinOnX) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMax.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMax.Z()); + } + else if (aThinOnY) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMax.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMax.Z()); + } + else if (aThinOnZ) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMax.X(), thePntMax.Y(), thePntMin.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMin.Z()); + } + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt1, aPnt2)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt2, aPnt3)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt3, aPnt4)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt4, aPnt1)); + + theShape = aCompound; + return Standard_True; + } + else + { + BRepPrimAPI_MakeBox aBoxBuilder (thePntMin, thePntMax); + theShape = aBoxBuilder.Shape(); + return Standard_True; + } } //======================================================================= @@ -218,6 +268,7 @@ void Convert_Tools::CreatePresentation (const Handle(Geom_Plane)& thePlane, { Handle(AIS_Plane) aPlanePrs = new AIS_Plane (thePlane); + // TODO - default fields to be defined in another place aPlanePrs->Attributes()->SetPlaneAspect (new Prs3d_PlaneAspect()); Handle (Prs3d_PlaneAspect) aPlaneAspect = aPlanePrs->Attributes()->PlaneAspect(); aPlaneAspect->SetPlaneLength (100, 100); @@ -248,11 +299,13 @@ void Convert_Tools::CreatePresentation (const gp_Trsf& theTrsf, return; Handle(AIS_Shape) aSourcePrs = new AIS_Shape (aBoxShape); + // TODO - default fields to be defined in another place aSourcePrs->SetColor (Quantity_NOC_WHITE); aSourcePrs->SetTransparency (0.5); thePresentations.Append (aSourcePrs); Handle(AIS_Shape) aTransformedPrs = new AIS_Shape (aBoxShape); + // TODO - default fields to be defined in another place aTransformedPrs->SetColor (Quantity_NOC_TOMATO); aTransformedPrs->SetTransparency (0.5); aTransformedPrs->SetLocalTransformation (theTrsf); diff --git a/tools/Convert/Convert_Tools.hxx b/tools/Convert/Convert_Tools.hxx index 728c096c74..bdcd05c09b 100644 --- a/tools/Convert/Convert_Tools.hxx +++ b/tools/Convert/Convert_Tools.hxx @@ -1,6 +1,6 @@ -// Created on: 2020-01-25 +// Created on: 2017-06-16 // Created by: Natalia ERMOLAEVA -// Copyright (c) 2020 OPEN CASCADE SAS +// Copyright (c) 2017 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -42,7 +42,7 @@ class Geom_Plane; class Geom_Transformation; //! \class Convert_Tools -//! \brief The tool that gives auxiliary methods for qt elements manipulation. +//! \brief The tool that gives auxiliary methods for qt elements manipulation class Convert_Tools { public: @@ -81,9 +81,7 @@ public: //! \param thePntMin minimum point on the bounding box //! \param thePntMax maximum point on the bounding box //! \return created shape - Standard_EXPORT static Standard_Boolean CreateBoxShape (const gp_Pnt& thePntMin, - const gp_Pnt& thePntMax, - TopoDS_Shape& theShape); + Standard_EXPORT static Standard_Boolean CreateBoxShape (const gp_Pnt& thePntMin, const gp_Pnt& thePntMax, TopoDS_Shape& theShape); //! Creates presentation AIS_Plane //! \param thePlane source plane diff --git a/tools/DFBrowser/DFBrowser_Communicator.cxx b/tools/DFBrowser/DFBrowser_Communicator.cxx index 6ae5f5c016..d34580c772 100644 --- a/tools/DFBrowser/DFBrowser_Communicator.cxx +++ b/tools/DFBrowser/DFBrowser_Communicator.cxx @@ -16,6 +16,7 @@ #include +//#include #include #include diff --git a/tools/DFBrowser/DFBrowser_TreeModel.cxx b/tools/DFBrowser/DFBrowser_TreeModel.cxx index 23ab2c2aa8..70857bc046 100644 --- a/tools/DFBrowser/DFBrowser_TreeModel.cxx +++ b/tools/DFBrowser/DFBrowser_TreeModel.cxx @@ -49,7 +49,7 @@ DFBrowser_TreeModel::DFBrowser_TreeModel (QObject* theParent) // ======================================================================= void DFBrowser_TreeModel::InitColumns() { - SetHeaderItem (0, TreeModel_HeaderSection ("Name")); + setHeaderItem (0, TreeModel_HeaderSection ("Name")); } // ======================================================================= diff --git a/tools/DFBrowser/DFBrowser_Window.cxx b/tools/DFBrowser/DFBrowser_Window.cxx index b7e94c7ffb..7b67da368e 100644 --- a/tools/DFBrowser/DFBrowser_Window.cxx +++ b/tools/DFBrowser/DFBrowser_Window.cxx @@ -51,10 +51,11 @@ #include #include #include -#include + #include #include #include +#include #include #include @@ -62,7 +63,6 @@ #include #include -#include #include #include #include @@ -192,7 +192,7 @@ DFBrowser_Window::DFBrowser_Window() // view myViewWindow = new View_Window (myMainWindow); - myViewWindow->SetPredefinedSize (DFBROWSER_DEFAULT_VIEW_WIDTH, DFBROWSER_DEFAULT_VIEW_HEIGHT); + myViewWindow->ViewWidget()->SetPredefinedSize (DFBROWSER_DEFAULT_VIEW_WIDTH, DFBROWSER_DEFAULT_VIEW_HEIGHT); QDockWidget* aViewDockWidget = new QDockWidget (tr ("View"), myMainWindow); aViewDockWidget->setObjectName (aViewDockWidget->windowTitle()); diff --git a/tools/DFBrowserPane/DFBrowserPane_TDataStdTreeNodeModel.cxx b/tools/DFBrowserPane/DFBrowserPane_TDataStdTreeNodeModel.cxx index 4f8a4847f0..0d6b98f12f 100644 --- a/tools/DFBrowserPane/DFBrowserPane_TDataStdTreeNodeModel.cxx +++ b/tools/DFBrowserPane/DFBrowserPane_TDataStdTreeNodeModel.cxx @@ -37,7 +37,7 @@ DFBrowserPane_TDataStdTreeNodeModel::DFBrowserPane_TDataStdTreeNodeModel (QObjec // ======================================================================= void DFBrowserPane_TDataStdTreeNodeModel::InitColumns() { - SetHeaderItem (0, TreeModel_HeaderSection ("Name")); + setHeaderItem (0, TreeModel_HeaderSection ("Name")); } // ======================================================================= diff --git a/tools/MessageModel/FILES b/tools/MessageModel/FILES new file mode 100644 index 0000000000..5fbdcbc86b --- /dev/null +++ b/tools/MessageModel/FILES @@ -0,0 +1,16 @@ +MessageModel.qrc +MessageModel_Actions.cxx +MessageModel_Actions.hxx +MessageModel_ActionType.hxx +MessageModel_ItemAlert.cxx +MessageModel_ItemAlert.hxx +MessageModel_ItemBase.cxx +MessageModel_ItemBase.hxx +MessageModel_ItemReport.cxx +MessageModel_ItemReport.hxx +MessageModel_ItemRoot.cxx +MessageModel_ItemRoot.hxx +MessageModel_Tools.cxx +MessageModel_Tools.hxx +MessageModel_TreeModel.cxx +MessageModel_TreeModel.hxx diff --git a/tools/MessageModel/MessageModel.qrc b/tools/MessageModel/MessageModel.qrc new file mode 100644 index 0000000000..8b794a8599 --- /dev/null +++ b/tools/MessageModel/MessageModel.qrc @@ -0,0 +1,6 @@ + + + icons/item_shape.png + icons/item_streamValues.png + + diff --git a/tools/MessageModel/MessageModel_ActionType.hxx b/tools/MessageModel/MessageModel_ActionType.hxx new file mode 100644 index 0000000000..3415c9d0d2 --- /dev/null +++ b/tools/MessageModel/MessageModel_ActionType.hxx @@ -0,0 +1,33 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ActionType_H +#define MessageModel_ActionType_H + +//! Kind of action type for tree view context menu item +enum MessageModel_ActionType +{ + MessageModel_ActionType_Activate, //!< set Message_Report active + MessageModel_ActionType_Deactivate, //!< set Message_Report not active + MessageModel_ActionType_Clear, //!< clear Message_Report alerts + MessageModel_ActionType_ExportToShapeView, //!< export TopoDS_Shape of selected item into TKShapeView plugin + MessageModel_ActionType_TestMetric, //!< test alerts + MessageModel_ActionType_TestProperties, //!< test alerts + MessageModel_ActionType_TestMessenger, //!< test message view on messenger printer to report + MessageModel_ActionType_TestReportTree, //!< test message view on hierarchical report + MessageModel_ActionType_TestReportTree2 //!< test message view on hierarchical report +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Actions.cxx b/tools/MessageModel/MessageModel_Actions.cxx new file mode 100644 index 0000000000..8ca4217c74 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.cxx @@ -0,0 +1,269 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_Actions::MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel) +: QObject (theParent), myTreeModel (theTreeModel), mySelectionModel (theModel) +{ + myActions.insert (MessageModel_ActionType_Activate, + ViewControl_Tools::CreateAction ("Activate", SLOT (OnActivateReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_Deactivate, + ViewControl_Tools::CreateAction ("Deactivate", SLOT (OnDeactivateReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_Clear, + ViewControl_Tools::CreateAction ("Clear", SLOT (OnClearReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_ExportToShapeView, + ViewControl_Tools::CreateAction (tr ("Export to ShapeView"), SLOT (OnExportToShapeView()), parent(), this)); +} + +// ======================================================================= +// function : GetAction +// purpose : +// ======================================================================= +QAction* MessageModel_Actions::GetAction (const MessageModel_ActionType& theType) +{ + if (myActions.contains (theType)) + return myActions[theType]; + + return 0; +} + +// ======================================================================= +// function : AddMenuActions +// purpose : +// ======================================================================= +void MessageModel_Actions::AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu) +{ + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + MessageModel_ItemAlertPtr anAlertItem; + for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin(); aSelIt != theSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + + anAlertItem = itemDynamicCast (anItemBase); + if (anAlertItem) + break; + } + + if (aReportItem && !aReportItem->GetReport().IsNull()) + { + theMenu->addAction (myActions[MessageModel_ActionType_Deactivate]); + theMenu->addAction (myActions[MessageModel_ActionType_Activate]); + theMenu->addAction (myActions[MessageModel_ActionType_Clear]); + } + else if (anAlertItem) + { + theMenu->addAction (myActions[MessageModel_ActionType_ExportToShapeView]); + } + + theMenu->addSeparator(); +} + +// ======================================================================= +// function : getSelectedReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageModel_Actions::getSelectedReport (QModelIndex& theReportIndex) const +{ + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aReportItem = itemDynamicCast (anItemBase); + theReportIndex = anIndex; + if (aReportItem) + break; + } + if (!aReportItem) + return NULL; + + return aReportItem->GetReport(); +} + +// ======================================================================= +// function : OnActivateReport +// purpose : +// ======================================================================= +static Handle(Message_PrinterToReport) MyPrinterToReport; +static Message_SequenceOfPrinters MyDeactivatedPrinters; + +void MessageModel_Actions::OnActivateReport() +{ + if (MyPrinterToReport.IsNull()) + MyPrinterToReport = new Message_PrinterToReport(); + + if (MyPrinterToReport->Report()->IsActiveInMessenger()) + return; + + MyDeactivatedPrinters = Message::DefaultMessenger()->Printers(); + Message::DefaultMessenger()->ChangePrinters().Clear(); + + Message::DefaultMessenger()->AddPrinter (MyPrinterToReport); + Message::DefaultMessenger()->SetTraceLevel (1); + Message::DefaultReport()->UpdateActiveInMessenger(); + + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnDeactivateReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnDeactivateReport() +{ + if (MyPrinterToReport.IsNull() || !MyPrinterToReport->Report()->IsActiveInMessenger()) + return; + + Message::DefaultMessenger()->RemovePrinter (MyPrinterToReport); + Message::DefaultMessenger()->ChangePrinters().Assign (MyDeactivatedPrinters); + + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnClearReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnClearReport() +{ + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + aReport->Clear(); + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnExportToShapeView +// purpose : +// ======================================================================= +void MessageModel_Actions::OnExportToShapeView() +{ + TCollection_AsciiString aPluginName ("TKShapeView"); + + NCollection_List aPluginParameters; + if (myParameters->FindParameters (aPluginName)) + aPluginParameters = myParameters->Parameters (aPluginName); + NCollection_List anItemNames; + if (myParameters->FindSelectedNames (aPluginName)) + anItemNames = myParameters->GetSelectedNames (aPluginName); + + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + QStringList anExportedPointers; + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast (anItemBase); + if (!anAlertItem) + continue; + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + continue; + + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (anAlert); + if (anExtAlert.IsNull()) + continue; + + Handle(Message_Attribute) anAttribute = anExtAlert->Attribute(); + if (anAttribute.IsNull()) + continue; + + if (!anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + continue; + + const TopoDS_Shape aShape = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape(); + if (aShape.IsNull()) + continue; + aPluginParameters.Append (aShape.TShape()); + anItemNames.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape)); + + anExportedPointers.append (MessageModel_Tools::GetPointerInfo (aShape.TShape(), true).ToCString()); + } + + if (anExportedPointers.empty()) + return; + myParameters->SetSelectedNames (aPluginName, anItemNames); + myParameters->SetParameters (aPluginName, aPluginParameters); + QMessageBox::information (0, "Information", QString ("TShapes '%1' are sent to %2 tool.") + .arg (anExportedPointers.join (", ")).arg (QString (aPluginName.ToCString()))); +} diff --git a/tools/MessageModel/MessageModel_Actions.hxx b/tools/MessageModel/MessageModel_Actions.hxx new file mode 100644 index 0000000000..39eab429e2 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.hxx @@ -0,0 +1,98 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_Actions_H +#define MessageModel_Actions_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Message_Report; +class MessageModel_TreeModel; + +class QAction; +class QItemSelectionModel; +class QMenu; +class QWidget; + +//! \class MessageModel_Actions +//! \brief This is a listener of popup context menu items and selection change in message model +class MessageModel_Actions : public QObject +{ + Q_OBJECT + +public: + + //! Constructor + Standard_EXPORT MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, + QItemSelectionModel* theModel); + + //! Destructor + virtual ~MessageModel_Actions() Standard_OVERRIDE {} + + //! Returns action by the type + //! \param theType an action type + //! \return an action instance if it exists + Standard_EXPORT QAction* GetAction (const MessageModel_ActionType& theType); + + //! Fills popup menu with actions depending on the current selection + //! \param theSelectedIndices tree model selected indices + //! \param theMenu menu to be filled + Standard_EXPORT void AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu); + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) + { myParameters = theParameters; } + +public slots: + //! Set selected report active + void OnActivateReport(); + + //! Set selected report not active + void OnDeactivateReport(); + + //! Clears container of alerts of selected report + void OnClearReport(); + + //! Exports the first selected shape into ShapeViewer plugin. + void OnExportToShapeView(); + +protected: + //! Returns report of selected tree view item if a report item is selected + //! \param theReportIndex tree model index of the found report + //! \return report instance or NULL + Handle(Message_Report) getSelectedReport (QModelIndex& theReportIndex) const; + +protected: + MessageModel_TreeModel* myTreeModel; //< tree model + QItemSelectionModel* mySelectionModel; //< selection model + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + QMap myActions; //!< container of all actions +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemAlert.cxx b/tools/MessageModel/MessageModel_ItemAlert.cxx new file mode 100644 index 0000000000..a0904ec5c1 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.cxx @@ -0,0 +1,352 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemAlert::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + MessageModel_ItemReportPtr aReportItem = MessageModel_ItemReport::FindReportItem (Parent()); + if (!aReportItem) + return QVariant(); + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport.IsNull()) + return QVariant(); + + if (theRole == Qt::ForegroundRole) + { + if (!aReport->IsActiveInMessenger()) + return QColor(Qt::darkGray); + + return QVariant(); + } + + Handle(Message_Alert) anAlert = getAlert(); + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + + // if the alert is composite, process the real alert + if (theRole == Qt::DecorationRole && Column() == 0) + { + if (anExtendedAlert.IsNull()) + return QVariant(); + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return QVariant(); + + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + return QIcon (":/icons/item_shape.png"); + else if (!Handle(Message_AttributeStream)::DownCast (anAttribute).IsNull()) + return QIcon (":/icons/item_streamValues.png"); + else + return QVariant(); + } + + if (theRole != Qt::DisplayRole && theRole != Qt::ToolTipRole) + return QVariant(); + + if (anAlert.IsNull()) + return QVariant(); + + if (Column() == 0) + { + if (theRole == Qt::DisplayRole) + { + TCollection_AsciiString aMessageKey = anAlert->GetMessageKey(); + if (aMessageKey.IsEmpty() && !Properties().IsNull()) + aMessageKey = Properties()->Key(); + return aMessageKey.ToCString(); + } + else + return anAlert->DynamicType()->Name(); + } + + Message_MetricType aMetricType; + int aPosition; + if (MessageModel_TreeModel::IsMetricColumn (Column(), aMetricType, aPosition)) + { + if (anExtendedAlert.IsNull()) + return QVariant(); + + Handle(Message_AttributeMeter) anAttribute = Handle(Message_AttributeMeter)::DownCast (anExtendedAlert->Attribute()); + if (anAttribute.IsNull() || !anAttribute->HasMetric (aMetricType)) + return QVariant(); + + if (!anAttribute->IsMetricValid (aMetricType)) + return QVariant ("in process"); + + if (aMetricType == Message_MetricType_UserTimeCPU || + aMetricType == Message_MetricType_SystemTimeInfo || + aMetricType == Message_MetricType_WallClock) + { + Standard_Real aCumulativeMetric = anAttribute->StopValue (aMetricType) - anAttribute->StartValue (aMetricType); + if (fabs (aCumulativeMetric) < Precision::Confusion()) + return QVariant(); + + if (aPosition == 0) return aCumulativeMetric; + else if (aPosition == 1) + { + Standard_Real aReportCumulativeMetric = MessageModel_ItemReport::CumulativeMetric (aReport, aMetricType); + if (fabs (aReportCumulativeMetric) > Precision::Confusion()) + return 100. * aCumulativeMetric / aReportCumulativeMetric; + else + return QVariant(); + } + } + else + { + if (aPosition == 0) return anAttribute->StopValue (aMetricType); + else if (aPosition == 1) + { + Standard_Real aCumulativeMetric = anAttribute->StopValue (aMetricType) - anAttribute->StartValue (aMetricType); + if (fabs (aCumulativeMetric) < Precision::Confusion()) + return QVariant(); + else + return aCumulativeMetric; + } + + } + } + return QVariant(); +} + +// ======================================================================= +// function : initRowCount +// purpose : +// ======================================================================= +int MessageModel_ItemAlert::initRowCount() const +{ + const Handle(Message_Alert)& anAlert = getAlert(); + if (anAlert.IsNull()) + return 0; + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + if (anExtendedAlert.IsNull()) + return 0; + + Handle(Message_CompositeAlerts) aCompositeAlert = anExtendedAlert->CompositeAlerts(); + if (aCompositeAlert.IsNull()) + return 0; + + MessageModel_ItemAlert* aCurrentItem = (MessageModel_ItemAlert*)this; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts ((Message_Gravity)aGravityId); + { + for (Message_ListOfAlert::Iterator anIt(anAlerts); anIt.More(); anIt.Next()) + { + Message_ListOfAlert aCurAlerts; + aCurAlerts.Append (anIt.Value()); + aCurrentItem->myChildAlerts.Bind(myChildAlerts.Size(), aCurAlerts); + } + } + } + + return aCurrentItem->myChildAlerts.Size(); +} + +// ======================================================================= +// function : initStream +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::initStream (Standard_OStream& OS) const +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (getAlert()); + if (anExtendedAlert.IsNull() || anExtendedAlert->Attribute().IsNull()) + return; + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return; + + if (Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + return; + + Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + OS << anAttributeStream->Stream().str(); +} + +// ======================================================================= +// function : SetStream +// purpose : +// ======================================================================= +bool MessageModel_ItemAlert::SetStream (const Standard_SStream& theSStream, Standard_Integer& theStartPos, + Standard_Integer& theLastPos) const +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (getAlert()); + if (anExtendedAlert.IsNull() || anExtendedAlert->Attribute().IsNull()) + return false; + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return false; + + if (Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + return false; + + Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + TCollection_AsciiString aStreamValue = Standard_Dump::Text (anAttributeStream->Stream()); + + TCollection_AsciiString aNewValue = Standard_Dump::Text (theSStream); + + Standard_SStream aStream; + aStream << aStreamValue.SubString (1, theStartPos - 1); + aStream << aNewValue; + if (theLastPos + 1 <= aStreamValue.Length()) + aStream << aStreamValue.SubString (theLastPos + 1, aStreamValue.Length()); + + //TCollection_AsciiString aStreamValue_debug = Standard_Dump::Text (aStream); + + anAttributeStream->SetStream (aStream); + + return true; +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemAlert::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemAlert::CreateItem (currentItem(), theRow, theColumn); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::Init() +{ + MessageModel_ItemReportPtr aReportItem = itemDynamicCast (Parent()); + MessageModel_ItemAlertPtr anAlertItem; + Handle(Message_Alert) anAlert; + if (aReportItem) + { + Message_ListOfAlert anAlerts; + if (aReportItem->GetChildAlerts (Row(), anAlerts)) + { + myAlert = anAlerts.First(); + } + } + else + { + anAlertItem = itemDynamicCast (Parent()); + if (anAlertItem) + { + Message_ListOfAlert anAlerts; + if (anAlertItem->GetChildAlerts (Row(), anAlerts)) + { + myAlert = anAlerts.First(); + } + } + } + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(myAlert); + if (!anExtendedAlert.IsNull() && !anExtendedAlert->Attribute().IsNull()) + { + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (!anAttribute.IsNull()) + { + //if (!Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + //{ + // if (GetProperties().IsNull()) + // { + // TreeModel_ItemBasePtr anItem = Parent()->Child (Row(), Column(), false); + // SetProperties (new MessageModel_ItemPropertiesAttributeStream (anItem)); + // } + // Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + // Handle(MessageModel_ItemPropertiesAttributeStream) aProperties = Handle(MessageModel_ItemPropertiesAttributeStream)::DownCast (GetProperties()); + // aProperties->Init (anAttributeStream->GetStream()); + //} + ////if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + //// myPresentation = Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject(); + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + myPresentation = new Convert_TransientShape (Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape()); + } + //TCollection_AsciiString aDescription = anExtendedAlert->Attribute()->GetDescription(); + //Bnd_Box aBox; + //if (aBox.Init (Standard_SStream (aDescription.ToCString()))) + // myPresentation =new Convert_TransientShape (Convert_Tools::CreateShape (aBox)); + } + MessageModel_ItemBase::Init(); +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::Reset() +{ + MessageModel_ItemBase::Reset(); + myAlert = Handle(Message_Alert)(); + myChildAlerts.Clear(); + myPresentation = NULL; +} + +// ======================================================================= +// function : initItem +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::initItem() const +{ + if (IsInitialized()) + return; + const_cast(this)->Init(); +} + +// ======================================================================= +// function : getAlert +// purpose : +// ======================================================================= +const Handle(Message_Alert)& MessageModel_ItemAlert::getAlert() const +{ + initItem(); + return myAlert; +} diff --git a/tools/MessageModel/MessageModel_ItemAlert.hxx b/tools/MessageModel/MessageModel_ItemAlert.hxx new file mode 100644 index 0000000000..c9b5d0b781 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.hxx @@ -0,0 +1,137 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemAlert_H +#define MessageModel_ItemAlert_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +class QAbstractTableModel; + +class MessageModel_ItemAlert; +typedef QExplicitlySharedDataPointer MessageModel_ItemAlertPtr; + +//! \class MessageModel_ItemAlert +//! This item is connected to Message_Alert. +//! Parent is either MessageModel_ItemRoot or MessageModel_ItemAlert, children are MessageModel_ItemAlert or no children +class MessageModel_ItemAlert : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + //! \return the pointer to the created item + static MessageModel_ItemAlertPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemAlertPtr (new MessageModel_ItemAlert (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemAlert() Standard_OVERRIDE {}; + + //! Returns the current shape + const Handle(Message_Alert)& GetAlert() const { return myAlert; } + + //! Returns alert of the report for the parameter row + Standard_Boolean GetChildAlerts (const int theRow, Message_ListOfAlert& theAlerts) const { return myChildAlerts.Find(theRow, theAlerts); } + + //! Inits the item, fills internal containers + Standard_EXPORT virtual void Init() Standard_OVERRIDE; + + //! Resets cached values + Standard_EXPORT virtual void Reset() Standard_OVERRIDE; + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + Standard_EXPORT virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + Standard_EXPORT virtual int initRowCount() const Standard_OVERRIDE; + + //! Returns stream value of the item to fulfill property panel. + //! \return stream value or dummy + Standard_EXPORT virtual bool SetStream (const Standard_SStream& theSStream, Standard_Integer& theStartPos, + Standard_Integer& theLastPos) const Standard_OVERRIDE; + + //! Sets some shape to present the item + //! \param theShape shape instance + void SetCustomShape (const TopoDS_Shape& theShape) { myCustomShape = theShape; } + + //! Returns custom shape to present the item + //! \return instance of the shape + const TopoDS_Shape& GetCustomShape() const { return myCustomShape; } + + //! Returns presentation of the attribute to be visualized in the view + //! \param theRow a model index row + //! \param theColumn a model index column + //! \thePresentations [out] container of presentation handles to be visualized + virtual void Presentations (NCollection_List& thePresentations) Standard_OVERRIDE + { TreeModel_ItemBase::Presentations (thePresentations); thePresentations.Append (myPresentation); } + + + ////! Returns summ of children alert elapsed times. The method is recusive. + ////! \param theAlert a message alert + ////! \return double value + //Standard_EXPORT static double CumulativeMetric (const Handle(Message_Alert)& theAlert); + +protected: + + //! Initialize the current item. It is empty because Reset() is also empty. + virtual void initItem() const Standard_OVERRIDE; + + //! Returns stream value of the item to fulfill property panel. + //! \return stream value or dummy + Standard_EXPORT virtual void initStream (Standard_OStream& OS) const Standard_OVERRIDE; + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + + //! Returns current alert, initialized item if it has not been initialized yet + //! \return alert value + const Handle(Message_Alert)& getAlert() const; + +private: + + //! Constructor + MessageModel_ItemAlert (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn) {} + +private: + Handle(Message_Alert) myAlert; + + NCollection_DataMap myChildAlerts; //!< container of child alerts + + TopoDS_Shape myCustomShape; + Handle(Standard_Transient) myPresentation; +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemBase.cxx b/tools/MessageModel/MessageModel_ItemBase.cxx new file mode 100644 index 0000000000..de74f85a3c --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.cxx @@ -0,0 +1,47 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include + +// ======================================================================= +// function : isReversed +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemBase::isReversed() const +{ + TreeModel_ItemBasePtr aParentItem = GetRootItem(); + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (aParentItem); + return aRootItem ? aRootItem->IsReversed() : Standard_False; +} + +// ======================================================================= +// function : GetRootItem +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemBase::GetRootItem() const +{ + TreeModel_ItemBasePtr anItem = Parent(); + while (anItem) + { + if (MessageModel_ItemRootPtr aThisRootItem = itemDynamicCast (anItem)) + { + return aThisRootItem; + } + anItem = anItem->Parent(); + } + return TreeModel_ItemBasePtr(); +} diff --git a/tools/MessageModel/MessageModel_ItemBase.hxx b/tools/MessageModel/MessageModel_ItemBase.hxx new file mode 100644 index 0000000000..dfd9e7fb61 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.hxx @@ -0,0 +1,56 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemBase_H +#define MessageModel_ItemBase_H + +#include +#include +#include + +class MessageModel_ItemBase; +typedef QExplicitlySharedDataPointer MessageModel_ItemBasePtr; + +//! \class MessageModel_ItemBase +// \brief Declaration of the tree model base item. +class MessageModel_ItemBase : public TreeModel_ItemBase +{ +public: + + //! Resets cached values + virtual void Reset() Standard_OVERRIDE { TreeModel_ItemBase::Reset(); } + +protected: + + //! Initialize the current item. It creates a backup of the specific item information + virtual void initItem() const {}; + + //! Constructor + //! param theParent a parent item + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + MessageModel_ItemBase (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : TreeModel_ItemBase (theParent, theRow, theColumn) {} + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean isReversed() const; + + //! Return root item + //! \return an item instance + TreeModel_ItemBasePtr GetRootItem() const; +}; + +#endif \ No newline at end of file diff --git a/tools/MessageModel/MessageModel_ItemReport.cxx b/tools/MessageModel/MessageModel_ItemReport.cxx new file mode 100644 index 0000000000..bf4fc5a7f7 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.cxx @@ -0,0 +1,233 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemReport::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + const Handle(Message_Report)& aReport = getReport(); + if (aReport.IsNull()) + return QVariant(); + + if (theRole == Qt::ForegroundRole) + { + if (!aReport->IsActiveInMessenger()) + return QColor(Qt::darkGray); + + return QVariant(); + } + if (theRole == Qt::ToolTipRole && !myDescription.IsEmpty() && Column() == 0) // display the exported file name in tool tip + { + OSD_Path aPath(myDescription); + return QString ("%1%2").arg (aPath.Name().ToCString()).arg (aPath.Extension().ToCString()); + } + + if (theRole != Qt::DisplayRole) + return QVariant(); + + if (Column() == 0) + return aReport->DynamicType()->Name(); + + Message_MetricType aMetricType; + int aPosition; + if (MessageModel_TreeModel::IsMetricColumn (Column(), aMetricType, aPosition) && + (aMetricType == Message_MetricType_UserTimeCPU || aMetricType == Message_MetricType_SystemTimeInfo || + aMetricType == Message_MetricType_WallClock)) + { + if (aPosition == 0) return CumulativeMetric (aReport, aMetricType); + else if (aPosition == 1) return "100"; + } + return QVariant(); +} + +// ======================================================================= +// function : initRowCount +// purpose : +// ======================================================================= +int MessageModel_ItemReport::initRowCount() const +{ + const Handle(Message_Report)& aReport = getReport(); + if (aReport.IsNull()) + return 0; + + MessageModel_ItemReport* aCurrentItem = (MessageModel_ItemReport*)this; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aReport->GetAlerts ((Message_Gravity)aGravityId); + for (Message_ListOfAlert::Iterator anIt(anAlerts); anIt.More(); anIt.Next()) + { + Message_ListOfAlert aCurAlerts; + aCurAlerts.Append (anIt.Value()); + aCurrentItem->myChildAlerts.Bind(myChildAlerts.Size(), aCurAlerts); + } + } + return aCurrentItem->myChildAlerts.Size(); +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemReport::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemAlert::CreateItem (currentItem(), theRow, theColumn); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageModel_ItemReport::Init() +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (Parent()); + myReport = aRootItem ? aRootItem->GetReport (Row(), myDescription) : Handle(Message_Report)(); + + MessageModel_ItemBase::Init(); +} + +// ======================================================================= +// function : getReport +// purpose : +// ======================================================================= +const Handle(Message_Report)& MessageModel_ItemReport::getReport() const +{ + initItem(); + return myReport; +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +void MessageModel_ItemReport::Reset() +{ + MessageModel_ItemBase::Reset(); + myReport = Handle(Message_Report)(); + myChildAlerts.Clear(); +} + +// ======================================================================= +// function : initItem +// purpose : +// ======================================================================= +void MessageModel_ItemReport::initItem() const +{ + if (IsInitialized()) + return; + const_cast(this)->Init(); +} + +// ======================================================================= +// function : FindReportItem +// purpose : +// ======================================================================= +MessageModel_ItemReportPtr MessageModel_ItemReport::FindReportItem (const TreeModel_ItemBasePtr& theItem) +{ + TreeModel_ItemBasePtr anItem = theItem; + while (anItem) + { + if (MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItem)) + return aReportItem; + + anItem = anItem->Parent(); + } + return MessageModel_ItemReportPtr(); +} + +// ======================================================================= +// function : FindReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageModel_ItemReport::FindReport (const MessageModel_ItemBasePtr& theItem) +{ + Handle(Message_Report) aReport; + + MessageModel_ItemBasePtr anItem = theItem; + while (anItem) + { + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItem); + + if (aReportItem) + return aReportItem->GetReport(); + + anItem = itemDynamicCast(anItem->Parent()); + } + return NULL; +} + +// ======================================================================= +// function : CumulativeMetric +// purpose : +// ======================================================================= +Standard_Real MessageModel_ItemReport::CumulativeMetric (const Handle(Message_Report)& theReport, const Message_MetricType theMetricType) +{ + if (!theReport->ActiveMetrics().Contains (theMetricType)) + return 0; + + Standard_Real aMetric = 0; + for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + { + const Message_ListOfAlert& anAlerts = theReport->GetAlerts ((Message_Gravity)iGravity); + Handle(Message_AttributeMeter) aFirstAttribute/*, aLastAttribute*/; + for (Message_ListOfAlert::Iterator anAlertsIterator (anAlerts); anAlertsIterator.More(); anAlertsIterator.Next()) + { + Handle(Message_AlertExtended) anAlert = Handle(Message_AlertExtended)::DownCast (anAlertsIterator.Value()); + if (anAlert.IsNull()) + continue; + Handle(Message_AttributeMeter) anAttribute = Handle(Message_AttributeMeter)::DownCast (anAlert->Attribute()); + if (anAttribute.IsNull() || !anAttribute->HasMetric (theMetricType) || !anAttribute->IsMetricValid (theMetricType)) + continue; + + //if (aFirstAttribute.IsNull()) + // aFirstAttribute = anAttribute; + //else + //{ + //aLastAttribute = anAttribute; + //} + aMetric += anAttribute->StopValue (theMetricType) - anAttribute->StartValue (theMetricType); + } + //if (aFirstAttribute.IsNull()) + // continue; + //if (aLastAttribute.IsNull()) + // aLastAttribute = aFirstAttribute; + + //aMetric += aLastAttribute->StopValue (theMetricType) - aFirstAttribute->StartValue (theMetricType); + } + return aMetric; +} diff --git a/tools/MessageModel/MessageModel_ItemReport.hxx b/tools/MessageModel/MessageModel_ItemReport.hxx new file mode 100644 index 0000000000..f03d98e58d --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.hxx @@ -0,0 +1,117 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemReport_H +#define MessageModel_ItemReport_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class MessageModel_ItemReport; +typedef QExplicitlySharedDataPointer MessageModel_ItemReportPtr; + +//! \class MessageModel_ItemReport +//! This item is connected to Message_Alert. +//! Parent is MessageModel_ItemRoot, children are MessageModel_ItemAlert or no children +class MessageModel_ItemReport : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + //! \return the pointer to the created item + static MessageModel_ItemReportPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemReportPtr (new MessageModel_ItemReport (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemReport() Standard_OVERRIDE {}; + + //! Returns the current shape + const Handle(Message_Report)& GetReport() const { return myReport; } + + //! Returns alert of the report for the parameter row + Standard_Boolean GetChildAlerts (const int theRow, Message_ListOfAlert& theAlerts) const { return myChildAlerts.Find(theRow, theAlerts); } + + //! Returns the report description or NULL + const TCollection_AsciiString& GetDescription() const { return myDescription; } + + //! Inits the item, fills internal containers + Standard_EXPORT virtual void Init() Standard_OVERRIDE; + + //! Resets cached values + Standard_EXPORT virtual void Reset() Standard_OVERRIDE; + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + Standard_EXPORT virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + Standard_EXPORT virtual int initRowCount() const Standard_OVERRIDE; + + //! Returns report of the tree model item. Iterates up by parents intil the report item is found. + //! \return an item or NULL + Standard_EXPORT static MessageModel_ItemReportPtr FindReportItem (const TreeModel_ItemBasePtr& theItem); + + //! Returns report of the item + static Handle(Message_Report) FindReport (const MessageModel_ItemBasePtr& thetItem); + + //! Returns report cumulative metric as stop time of the last alert minus start time of the first alert + Standard_EXPORT static Standard_Real CumulativeMetric (const Handle(Message_Report)& theReport, const Message_MetricType theMetricType); + +protected: + + //! Initialize the current item. It is empty because Reset() is also empty. + virtual void initItem() const Standard_OVERRIDE; + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + + //! Returns number of child shapes. Init item if it is not initialized + //! \return integer value + int getRowCount() const; + + //! Returns current shape, initialized item if it has not been initialized yet + //! \return shape value + const Handle(Message_Report)& getReport() const; + +private: + + //! Constructor + MessageModel_ItemReport (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn) {} + +private: + + NCollection_DataMap myChildAlerts; //!< container of child alerts + + Handle(Message_Report) myReport; //!< current report + TCollection_AsciiString myDescription; //!< description +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemRoot.cxx b/tools/MessageModel/MessageModel_ItemRoot.cxx new file mode 100644 index 0000000000..b42dcc8864 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.cxx @@ -0,0 +1,96 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include + +// ======================================================================= +// function : SetReport +// purpose : +// ======================================================================= +void MessageModel_ItemRoot::SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aRowId == theRowId) + break; + } + aReportsIt.Value().myReport = theReport; + aReportsIt.Value().myDescription = theReportDescription; +} + +// ======================================================================= +// function : GetReport +// purpose : +// ======================================================================= +const Handle(Message_Report)& MessageModel_ItemRoot::GetReport (const int theRowId, + TCollection_AsciiString& theReportDescription) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aRowId == theRowId) + break; + } + theReportDescription = aReportsIt.Value().myDescription; + return aReportsIt.Value().myReport; +} + +// ======================================================================= +// function : HasReport +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemRoot::HasReport (const Handle(Message_Report)& theReport) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aReportsIt.Value().myReport == theReport) + return Standard_True; + } + return Standard_False; +} + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemRoot::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + if (Column() != 0) + return QVariant(); + + if (theRole == Qt::DisplayRole) + return myName.IsEmpty() ? "Message_Reports" : myName.ToCString(); + + return QVariant(); +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemRoot::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemReport::CreateItem (currentItem(), theRow, theColumn); +} + diff --git a/tools/MessageModel/MessageModel_ItemRoot.hxx b/tools/MessageModel/MessageModel_ItemRoot.hxx new file mode 100644 index 0000000000..197bd1eb9a --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.hxx @@ -0,0 +1,126 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemRoot_H +#define MessageModel_ItemRoot_H + +#include +#include +#include +#include +#include + +#include + +class MessageModel_ItemRoot; +typedef QExplicitlySharedDataPointer MessageModel_ItemRootPtr; + +//! \struct to extend report by description +struct MessageModel_ReportInformation +{ + //! Constructor + MessageModel_ReportInformation (Handle(Message_Report) theReport, const TCollection_AsciiString& theDescription) + : myReport (theReport), myDescription (theDescription) {} + + Handle(Message_Report) myReport; //! report + TCollection_AsciiString myDescription; //! report description +}; + +//! \class MessageModel_ItemRoot +//! Collects message reports that should be visualized in tree view. Reports are cached and if reports are not needed, +//! cache should be cleared using RemoveAllReports +//! Parent is NULL, children are MessageModel_ItemReport items. +class MessageModel_ItemRoot : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + static MessageModel_ItemRootPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemRootPtr (new MessageModel_ItemRoot (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemRoot() Standard_OVERRIDE {}; + + //! Appends new report + //! \param theReport a report instance + //! \param theReportDescription an additional report information + void AddReport (const Handle(Message_Report)& theReport, const TCollection_AsciiString& theReportDescription) + { myReports.Append (MessageModel_ReportInformation (theReport, theReportDescription)); } + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Returns true if report exists is in the list of the current reports + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //!< Returns processed reports + const NCollection_List& Reports() const { return myReports; } + + //! Clears internal container of added reports + void RemoveAllReports() { myReports.Clear(); } + + //! Returns report by the number + //! \param theRowId an index of the report in the internal container. + Standard_EXPORT const Handle(Message_Report)& GetReport (const int theRowId, TCollection_AsciiString& theReportDescription); + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void SetReversed (const Standard_Boolean& theReversed) { myIsReversed = theReversed; } + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void SetName (const TCollection_AsciiString& theName) { myName = theName; } + +protected: + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + virtual int initRowCount() const Standard_OVERRIDE { return myReports.Size(); } + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + +private: + + //! Constructor + //! param theParent a parent item + MessageModel_ItemRoot (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn), myIsReversed (Standard_False) {} + +private: + + NCollection_List myReports; //!< reports sent by algorithms + Standard_Boolean myIsReversed; //!< state if the model is reversed + TCollection_AsciiString myName; //!< DisplayRole data, if defined +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Tools.cxx b/tools/MessageModel/MessageModel_Tools.cxx new file mode 100644 index 0000000000..5348d47ca8 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.cxx @@ -0,0 +1,59 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ======================================================================= +// function : GetPointerInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetPointerInfo (const Handle(Standard_Transient)& thePointer, const bool isShortInfo) +{ + if (thePointer.IsNull()) + return TCollection_AsciiString(); + + std::ostringstream aPtrStr; + aPtrStr << thePointer.operator->(); + if (!isShortInfo) + return aPtrStr.str().c_str(); + + TCollection_AsciiString anInfoPtr (aPtrStr.str().c_str()); + for (int aSymbolId = 1; aSymbolId < anInfoPtr.Length(); aSymbolId++) + { + if (anInfoPtr.Value(aSymbolId) != '0') + { + anInfoPtr = anInfoPtr.SubString (aSymbolId, anInfoPtr.Length()); + anInfoPtr.Prepend("0x"); + return anInfoPtr; + } + } + return aPtrStr.str().c_str(); +} diff --git a/tools/MessageModel/MessageModel_Tools.hxx b/tools/MessageModel/MessageModel_Tools.hxx new file mode 100644 index 0000000000..c83922aed6 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.hxx @@ -0,0 +1,53 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_Tools_H +#define MessageModel_Tools_H + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +class Message_Alert; +class ViewControl_TableModelValues; + +class ViewControl_Table; + +//! \class MessageModel_Tools +//! It gives auxiliary methods for Message classes manipulation +class MessageModel_Tools +{ +public: + + //! Convert pointer to string value + //! \param thePointer a pointer + //! \param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped + //! \return the string value + Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const Handle(Standard_Transient)& thePointer, + const bool isShortInfo = true); +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TreeModel.cxx b/tools/MessageModel/MessageModel_TreeModel.cxx new file mode 100644 index 0000000000..b5950bd8b5 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.cxx @@ -0,0 +1,213 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include + +const int COLUMN_NAME_WIDTH = 230; +const int COLUMN_SIZE_WIDTH = 30; + +const int COLUMN_REAL_VALUE_WIDTH = 115; +const int COLUMN_PERCENT_VALUE_WIDTH = 50; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_TreeModel::MessageModel_TreeModel (QObject* theParent) +: TreeModel_ModelBase (theParent), myIsReversed (Standard_False) +{ +} + +// ======================================================================= +// function : InitColumns +// purpose : +// ======================================================================= +void MessageModel_TreeModel::InitColumns() +{ + // 0 - Name, 1 - visibility, 2 - Row + setHeaderItem (TreeModel_ColumnType_Name, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + setHeaderItem (TreeModel_ColumnType_Visibility, TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth())); + setHeaderItem (TreeModel_ColumnType_Row, TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH, Standard_True /*hidden*/)); + + int aNextIndex = 3; + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + OSD_MemInfo::Counter aMemInfo; + bool isMemInfo = Message::ToOSDMetric (aMetricType, aMemInfo); + + setHeaderItem (aNextIndex++, + TreeModel_HeaderSection (QString("%1 [%2]").arg (Message::MetricToString (aMetricType)).arg(isMemInfo ? "Mb" : "s"), + COLUMN_REAL_VALUE_WIDTH)); + setHeaderItem (aNextIndex++, TreeModel_HeaderSection (isMemInfo ? "Delta" : "%", COLUMN_PERCENT_VALUE_WIDTH)); + } +} + +// ======================================================================= +// function : GetMetricColumns +// purpose : +// ======================================================================= +void MessageModel_TreeModel::GetMetricColumns (const Message_MetricType theMetricType, QList& theMetricColumns) +{ + theMetricColumns.clear(); + int aNextIndex = 3; // after default parent columns, see InitColumns + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + if (theMetricType != (Message_MetricType)aMetricId) + { + aNextIndex += 2; + continue; + } + theMetricColumns.append (aNextIndex++); + theMetricColumns.append (aNextIndex++); + } +} + +// ======================================================================= +// function : IsMetricColumn +// purpose : +// ======================================================================= +bool MessageModel_TreeModel::IsMetricColumn (const int theColumnId, Message_MetricType& theMetricType, int& thePosition) +{ + int aNextIndex = 3; // after default parent columns, see InitColumns + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + if (theColumnId == aNextIndex || theColumnId == aNextIndex + 1) + { + theMetricType = (Message_MetricType)aMetricId; + thePosition = theColumnId - aNextIndex; + return true; + } + aNextIndex += 2; + } + return false; +} + +// ======================================================================= +// function : createRootItem +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_TreeModel::createRootItem (const int theColumnId) +{ + return MessageModel_ItemRoot::CreateItem (TreeModel_ItemBasePtr(), 0, theColumnId); +} + +// ======================================================================= +// function : HasShape +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_TreeModel::HasReport (const Handle(Message_Report)& theReport) +{ + if (columnCount() == 0) + return Standard_False; + + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + return aRootItem && aRootItem->HasReport (theReport); +} + +// ======================================================================= +// function : AddShape +// purpose : +// ======================================================================= +void MessageModel_TreeModel::AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (!aRootItem) + continue; + aRootItem->AddReport (theReport, theReportDescription); + aRootItem->SetReversed (myIsReversed); + } + + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : SetReport +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (!aRootItem) + continue; + aRootItem->SetReport (theRowId, theReport, theReportDescription); + } + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : Reports +// purpose : +// ======================================================================= +const NCollection_List& MessageModel_TreeModel::Reports() const +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + return aRootItem->Reports(); +} + +// ======================================================================= +// function : SetReversed +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetReversed (const Standard_Boolean& theReversed) +{ + myIsReversed = theReversed; + + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (aRootItem) + aRootItem->SetReversed (myIsReversed); + } + + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : UpdateTreeModel +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetRootItemName (const TCollection_AsciiString& theName) +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + if (aRootItem) + aRootItem->SetName (theName); +} + +// ======================================================================= +// function : UpdateTreeModel +// purpose : +// ======================================================================= +void MessageModel_TreeModel::UpdateTreeModel() +{ + Reset(); + EmitLayoutChanged(); +} diff --git a/tools/MessageModel/MessageModel_TreeModel.hxx b/tools/MessageModel/MessageModel_TreeModel.hxx new file mode 100644 index 0000000000..01eeba4144 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.hxx @@ -0,0 +1,105 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_TreeModel_H +#define MessageModel_TreeModel_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class MessageModel_TreeModel; + +//! \class MessageModel_TreeModel +//! View model to visualize MessageReport/s content +class MessageModel_TreeModel : public TreeModel_ModelBase +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TreeModel (QObject* theParent); + + //! Destructor + virtual ~MessageModel_TreeModel() Standard_OVERRIDE {}; + + //! Creates model columns and root items. + Standard_EXPORT virtual void InitColumns() Standard_OVERRIDE; + + //!< Returns columns of the model for the metric + //!< \param theMetricType metric + //!< \param theMetricColumns [out] container of metric columns + static Standard_EXPORT void GetMetricColumns (const Message_MetricType theMetricType, QList& theMetricColumns); + + //!< Returns metric type for the column + //!< \param theColumnId [in] index of the tree column + //!< \param theMetricType [out] metric type if found + //!< \param thePosition [out] index of the metric column, 0 - is metric, 1 - is delta + //!< \return true if the column has metric parameters + static Standard_EXPORT bool IsMetricColumn (const int theColumnId, Message_MetricType& theMetricType, int& thePosition); + + //! Returns true if parameter report was added into the model + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //! Add shape, append it to the model root item + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //!< Returns processed reports + Standard_EXPORT const NCollection_List& Reports() const; + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + Standard_EXPORT void SetReversed (const Standard_Boolean& theReversed); + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! Sets the text value of the Root item, only "Name" column accepts the parameter value + //! \theName visulized text of root item + Standard_EXPORT void SetRootItemName (const TCollection_AsciiString& theName); + + //! Updates tree model + Standard_EXPORT void UpdateTreeModel(); + +protected: + //! Creates root item + //! \param theColumnId index of a column + virtual TreeModel_ItemBasePtr createRootItem (const int theColumnId) Standard_OVERRIDE; + +private: + Standard_Boolean myIsReversed; //!< state if the model is reversed +}; + +#endif diff --git a/tools/MessageModel/icons/item_shape.png b/tools/MessageModel/icons/item_shape.png new file mode 100644 index 0000000000..a808bc55e5 Binary files /dev/null and b/tools/MessageModel/icons/item_shape.png differ diff --git a/tools/MessageModel/icons/item_shape.svg b/tools/MessageModel/icons/item_shape.svg new file mode 100644 index 0000000000..14313ed68a --- /dev/null +++ b/tools/MessageModel/icons/item_shape.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_streamValues.png b/tools/MessageModel/icons/item_streamValues.png new file mode 100644 index 0000000000..7181f9460e Binary files /dev/null and b/tools/MessageModel/icons/item_streamValues.png differ diff --git a/tools/MessageModel/icons/item_streamValues.svg b/tools/MessageModel/icons/item_streamValues.svg new file mode 100644 index 0000000000..38b1032701 --- /dev/null +++ b/tools/MessageModel/icons/item_streamValues.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/tools/MessageView/FILES b/tools/MessageView/FILES new file mode 100644 index 0000000000..5fe2f52661 --- /dev/null +++ b/tools/MessageView/FILES @@ -0,0 +1,8 @@ +MessageView_ActionsTest.cxx +MessageView_ActionsTest.hxx +MessageView_Communicator.cxx +MessageView_Communicator.hxx +MessageView_VisibilityState.cxx +MessageView_VisibilityState.hxx +MessageView_Window.cxx +MessageView_Window.hxx diff --git a/tools/MessageView/MessageView_ActionsTest.cxx b/tools/MessageView/MessageView_ActionsTest.cxx new file mode 100644 index 0000000000..439c595921 --- /dev/null +++ b/tools/MessageView/MessageView_ActionsTest.cxx @@ -0,0 +1,485 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_ALERTS + +#ifdef DEBUG_ALERTS +#include +#endif + +#include + + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageView_ActionsTest::MessageView_ActionsTest (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel) +: QObject (theParent), myTreeModel (theTreeModel), mySelectionModel (theModel) +{ + myActions.insert (MessageModel_ActionType_TestMetric, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestMetric()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestProperties, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestPropertyPanel()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestMessenger, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestMessenger()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestReportTree, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestReportTree()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestReportTree2, + ViewControl_Tools::CreateAction ("Test 2", SLOT (OnTestReportTree2()), parent(), this)); +} + +// ======================================================================= +// function : AddMenuActions +// purpose : +// ======================================================================= +void MessageView_ActionsTest::AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu) +{ + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + MessageModel_ItemAlertPtr anAlertItem; + for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin(); aSelIt != theSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + + anAlertItem = itemDynamicCast (anItemBase); + if (anAlertItem) + break; + } + + if (aReportItem && !aReportItem->GetReport().IsNull()) + { + theMenu->addAction (myActions[MessageModel_ActionType_TestMetric]); + theMenu->addAction (myActions[MessageModel_ActionType_TestProperties]); + theMenu->addAction (myActions[MessageModel_ActionType_TestMessenger]); + theMenu->addAction (myActions[MessageModel_ActionType_TestReportTree]); + theMenu->addAction (myActions[MessageModel_ActionType_TestReportTree2]); + + bool isReportEnabled = aReportItem->GetReport()->IsActiveInMessenger(); + + myActions[MessageModel_ActionType_TestMetric]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestProperties]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestMessenger]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestReportTree]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestReportTree2]->setEnabled (isReportEnabled); + } + theMenu->addSeparator(); +} + +// ======================================================================= +// function : getSelectedReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageView_ActionsTest::getSelectedReport (QModelIndex& theReportIndex) const +{ + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aReportItem = itemDynamicCast (anItemBase); + theReportIndex = anIndex; + if (aReportItem) + break; + } + if (!aReportItem) + return NULL; + + return aReportItem->GetReport(); +} + +// ======================================================================= +// function : OnTestMetric +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestMetric() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestMetric()"); + unsigned int start_time = clock(); + //Standard_Real aSystemSeconds, aCurrentSeconds; + //OSD_Chronometer::GetThreadCPU (aCurrentSeconds, aSystemSeconds); + + Standard_Integer aCounter = 1500;//0; + Standard_Real aValue = 0., aValue2 = 0.1; + + double* aMemValue; + for (int aTopIt = 0; aTopIt < 4; aTopIt++) + { + Message::SendInfo() << "Calculate"; + for (int j = 0; j < aCounter; j++) + { + for (int i = 0; i < aCounter; i++) + { + aValue = (aValue * 2. + 3.) * 0.5 - 0.3 * 0.5; + + Standard_Real aValue3 = aValue + aValue2 * 0.2; + (void)aValue3; + + aMemValue = new double; + } + } + } + + //((MessageModel_TreeModel*)mySelectionModel->model())->EmitLayoutChanged(); + + myTreeModel->UpdateTreeModel(); + + //Standard_Real aSystemSeconds1, aCurrentSeconds1; + //OSD_Chronometer::GetThreadCPU (aCurrentSeconds1, aSystemSeconds1); + + //std::cout << aValue << std::endl; + //std::cout << "user time = " << aCurrentSeconds1 - aCurrentSeconds + // << ", system time = " << aSystemSeconds1 - aSystemSeconds << std::endl; + + unsigned int end_time = clock(); + std::cout << "clock() = " << end_time - start_time << std::endl; +#endif +} + +// ======================================================================= +// function : OnTestPropertyPanel +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestPropertyPanel() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestPropertyPanel()"); + + OCCT_SEND_MESSAGE ("Values") + OCCT_SEND_MESSAGE ("Values2") + // gp_XYZ + { + gp_XYZ aCoords (1.3, 2.3, 3.4); + OCCT_SEND_DUMPJSON (&aCoords, "gp_XYZ") + } + // gp_Dir + { + gp_Dir aDir (0.3, 0.3, 0.4); + OCCT_SEND_DUMPJSON (&aDir, "gp_Dir") + } + // gp_Ax1 + { + gp_Ax1 aCoords (gp_Pnt (1.3, 2.3, 3.4), gp_Dir (0.3, 0.3, 0.4)); + OCCT_SEND_DUMPJSON (&aCoords, "gp_Ax1") + } + // gp_Ax2 + { + gp_Ax2 aCoords (gp_Pnt (10.3, 20.3, 30.4), gp_Dir (0.3, 0.3, 0.4)); + OCCT_SEND_DUMPJSON (&aCoords, "gp_Ax2") + } + // gp_Ax3 + { + gp_Ax3 aPln (gp_Pnt (10., 20., 15.), gp_Dir (0., 0., 1.), gp_Dir (1., 0., 0.)); + OCCT_SEND_DUMPJSON (&aPln, "gp_Ax3") + } + // gp_Trsf + { + gp_Trsf aTrsf; + aTrsf.SetRotation (gp::OZ(), 0.3); + aTrsf.SetTranslationPart (gp_Vec (15., 15., 15.)); + aTrsf.SetScaleFactor (3.); + + OCCT_SEND_DUMPJSON (&aTrsf, "gp_Trsf") + } + // Bnd_Box + { + Bnd_Box aBox (gp_Pnt (20., 15., 10.), gp_Pnt (25., 20., 15.)); + OCCT_SEND_DUMPJSON (&aBox, "Bnd_Box") + } + // Bnd_OBB + { + Bnd_OBB anOBB (gp_Pnt (-10., -15., -10.), gp_Dir (1., 0., 0.), gp_Dir (0., 1., 0.), gp_Dir (0., 0., 1.), + 5., 10., 5.); + OCCT_SEND_DUMPJSON (&anOBB, "Bnd_OBB"); + } + // Quantity_ColorRGBA + { + Quantity_ColorRGBA aColor (0.2f, 0.8f, 0.8f, 0.2f); + OCCT_SEND_DUMPJSON (&aColor, "Quantity_ColorRGBA"); + } + // Quantity_Color + { + Quantity_Color aColor (0.8, 0.8, 0.8, Quantity_TOC_RGB); + OCCT_SEND_DUMPJSON (&aColor, "Quantity_Color"); + } + + // stream of some table values + { + Standard_SStream aStream; + OCCT_DUMP_FIELD_VALUES_NUMERICAL (aStream, "value_1", 1, 100); + OCCT_DUMP_FIELD_VALUES_STRING (aStream, "value_2", 2, "value_1", "value_2"); + OCCT_SEND_STREAM (aStream, "Table: Name to value"); + } + + // SHAPE messages + { + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + } + + myTreeModel->UpdateTreeModel(); +#endif +} + +// ======================================================================= +// function : createShapeOnLevel +// purpose : +// ======================================================================= +void createShapeOnLevel() +{ + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("createShapeOnLevel") + + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge ON LEVEL"); + //sout << "Shape message edge" << aShape; +} + +// ======================================================================= +// function : createShape +// purpose : +// ======================================================================= +void createShape() +{ + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + //sout << "Shape message edge" << aShape; + + createShapeOnLevel(); +} + +// ======================================================================= +// function : OnTestMessenger +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestMessenger() +{ + // string messages + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + Standard_Integer aTraceLevel_prev = Message::DefaultMessenger()->TraceLevel(); + Message::DefaultMessenger()->SetTraceLevel (1); + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestMessenger()") + + sout << "IGESBasic_Hierarchy" << std::endl; + sout << "Number of property valueaMessenger : " << 15 << std::endl; + sout << "Line Font : " << 1 << std::endl << "View Number : " << 3 << std::endl; + sout << "Entity level : " << 1 << std::endl; + sout << "Blank statuaMessenger : " << 0 << std::endl; + sout << "Line weight : " << 14 << std::endl; + sout << "Color number : " << 5 << std::endl; + + // stream messages + // gp_XYZ + { + gp_XYZ aCoords (1.3, 2.3, 3.4); + Standard_SStream aStream; + //aCoords.DumpJson (aStream); + //sout << "gp_XYZ" << aStream << std::endl; + aCoords.DumpJson (sout); + } + // Bnd_Box + { + Bnd_Box aBox (gp_Pnt (20., 15., 10.), gp_Pnt (25., 20., 15.)); + Standard_SStream aStream; + //aBox.DumpJson (aStream); + //sout << "Bnd_Box" << aStream; + aBox.DumpJson (sout); + } + + // object messages + Handle(Standard_Transient) anObject = new Message_AlertExtended(); + //sout << "Message_AlertExtended" << anObject; + + // shape messages + { + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + //sout << "Shape message edge" << aShape; + + createShape(); + } + myTreeModel->UpdateTreeModel(); + Message::DefaultMessenger()->SetTraceLevel (aTraceLevel_prev); +} + +// ======================================================================= +// function : levelAlerts +// purpose : +// ======================================================================= +void levelAlerts (const int theCurrentLevel, const int theTopLevel) +{ + if (theTopLevel - theCurrentLevel <= 0) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY (TCollection_AsciiString ("Level: " ) + theCurrentLevel) + + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + sout << "Alert(" << theCurrentLevel << "): " << 1 << ", " << 2 << std::endl; + sout << "Alert(" << theCurrentLevel << "): " << 3 << ", " << 4 << std::endl; + + //for (int i = 0; i < 2; i++) + levelAlerts (theCurrentLevel + 1, theTopLevel); + + sout << "Alert(" << theCurrentLevel << "): " << 4 << ", " << 5 << std::endl; +} + +// ======================================================================= +// function : levelAlert +// purpose : +// ======================================================================= +void levelAlert (const int theCurrentLevel, const int theTopLevel) +{ + if (theTopLevel - theCurrentLevel <= 0) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("levelAlert") + + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + sout << "Level: " << theCurrentLevel << "(Single, no alerts on the level)" << std::endl; + + //for (int i = 0; i < 2; i++) + levelAlerts (theCurrentLevel + 1, theTopLevel); +} + +// ======================================================================= +// function : OnTestReportTree +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestReportTree() +{ + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestReportTree()") + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + + // string messages + //sout << "Alert: " << 1 << std::endl; + //sout << "Alert: " << 2 << std::endl; + + int aTopLevel = 3; + levelAlerts (1, aTopLevel); + + //sout << "Alert: " << 3 << std::endl; + //levelAlerts (1, aTopLevel); + + sout << "Alert: " << 4 << std::endl; + levelAlert (1, aTopLevel); + + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnTestReportTree2 +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestReportTree2() +{ + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestReportTree()") + Message_Messenger::StreamBuffer sout = Message::SendInfo(); + + // string messages + //sout << "Alert: " << 1 << std::endl; + //sout << "Alert: " << 2 << std::endl; + + int aTopLevel = 3; + levelAlerts (1, aTopLevel); + + //sout << "Alert: " << 3 << std::endl; + //levelAlerts (1, aTopLevel); + + //sout << "Alert: " << 4 << std::endl; + //levelAlert (1, aTopLevel); + + myTreeModel->UpdateTreeModel(); +} diff --git a/tools/MessageView/MessageView_ActionsTest.hxx b/tools/MessageView/MessageView_ActionsTest.hxx new file mode 100644 index 0000000000..bf58b17ec9 --- /dev/null +++ b/tools/MessageView/MessageView_ActionsTest.hxx @@ -0,0 +1,85 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_ActionsTest_H +#define MessageView_ActionsTest_H + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +class Message_Report; +class MessageModel_TreeModel; +class QItemSelectionModel; + +class QAction; +class QWidget; +class QMenu; + +//! \class MessageView_ActionsTest +//! Window that unites all MessageView controls. +class MessageView_ActionsTest : public QObject +{ + Q_OBJECT +public: + + //! Constructor + MessageView_ActionsTest (QWidget* theParent, MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel); + + //! Destructor + virtual ~MessageView_ActionsTest() {} + + //! Fills popup menu with actions depending on the current selection + //! \param theSelectedIndices tree model selected indices + //! \param theMenu menu to be filled + Standard_EXPORT void AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu); + +public slots: + //! Sending several alerts to check metric of message-alert-tool mechanizm + void OnTestMetric(); + + //! Sending several alerts to check property panel/presentations of message-alert-tool mechanizm + void OnTestPropertyPanel(); + + //! Sending several alerts to check property panel/presentations of messenger-alert-tool mechanizm + void OnTestMessenger(); + + //! Check tree of alerts + void OnTestReportTree(); + + //! Check tree of alerts + void OnTestReportTree2(); + +protected: + //! Returns report of selected tree view item if a report item is selected + //! \param theReportIndex tree model index of the found report + //! \return report instance or NULL + Handle(Message_Report) getSelectedReport (QModelIndex& theReportIndex) const; + +protected: + MessageModel_TreeModel* myTreeModel; //< tree model + QItemSelectionModel* mySelectionModel; //< selection model + QMap myActions; //!< container of all actions +}; + +#endif diff --git a/tools/MessageView/MessageView_Communicator.cxx b/tools/MessageView/MessageView_Communicator.cxx new file mode 100644 index 0000000000..10b95480f7 --- /dev/null +++ b/tools/MessageView/MessageView_Communicator.cxx @@ -0,0 +1,26 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + + +// ======================================================================= +// function : CreateCommunicator +// purpose : Creates a communicator by the library loading +// ======================================================================= +Standard_EXPORTEXTERNC TInspectorAPI_Communicator* CreateCommunicator() +{ + return new MessageView_Communicator(); +} diff --git a/tools/MessageView/MessageView_Communicator.hxx b/tools/MessageView/MessageView_Communicator.hxx new file mode 100644 index 0000000000..7d93c21b55 --- /dev/null +++ b/tools/MessageView/MessageView_Communicator.hxx @@ -0,0 +1,66 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_Communicator_H +#define MessageView_Communicator_H + +#include +#include + +//! \class MessageView_Communicator. +//! \brief This is a connector from TInspector application to MessageView window +class MessageView_Communicator : public TInspectorAPI_Communicator +{ +public: + + //! Constructor + MessageView_Communicator() : TInspectorAPI_Communicator(), myWindow (new MessageView_Window (0)) {} + + //! Destructor + virtual ~MessageView_Communicator() Standard_OVERRIDE {} + + //! Provides the container with a parent where this container should be inserted. + //! If Qt implementation, it should be QWidget with QLayout set inside + //! \param theParent a parent class + virtual void SetParent (void* theParent) Standard_OVERRIDE { myWindow->SetParent (theParent); } + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + virtual void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) Standard_OVERRIDE + { myWindow->SetParameters (theParameters); } + + //! Provide container for actions available in inspector on general level + //! \param theMenu if Qt implementation, it is QMenu object + virtual void FillActionsMenu(void* theMenu) Standard_OVERRIDE { myWindow->FillActionsMenu (theMenu); } + + //! Returns plugin preferences, empty implementation by default + //! \param theItem container of preference elements + virtual void GetPreferences (TInspectorAPI_PreferencesDataMap& theItem) Standard_OVERRIDE + { myWindow->GetPreferences (theItem); } + + //! Stores plugin preferences, empty implementation by default + //! \param theItem container of preference elements + virtual void SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem) Standard_OVERRIDE + { myWindow->SetPreferences (theItem); } + + //! Calls update of the plugin's content + virtual void UpdateContent() Standard_OVERRIDE { myWindow->UpdateContent(); } + +private: + + MessageView_Window* myWindow; //!< current window +}; + +#endif diff --git a/tools/MessageView/MessageView_VisibilityState.cxx b/tools/MessageView/MessageView_VisibilityState.cxx new file mode 100644 index 0000000000..9b7993528a --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.cxx @@ -0,0 +1,150 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include + +#include + +// ======================================================================= +// function : CanBeVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::CanBeVisible (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (anAlertItem) + { + NCollection_List aPresentations; + anAlertItem->Presentations (aPresentations); + if (!aPresentations.IsEmpty()) + return true; + } + + return !Shape (theIndex).IsNull();// || hasTableValues (theIndex); +} + +// ======================================================================= +// function : SetVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::SetVisible (const QModelIndex& theIndex, const bool theState, const bool toEmitDataChanged) +{ + TopoDS_Shape aShape = Shape (theIndex); + if (aShape.IsNull()) + return false; + + myDisplayer->SetVisible (aShape, theState, myPresentationType); + + if (!theState) { + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (anAlertItem && !anAlertItem->GetCustomShape().IsNull()) + anAlertItem->SetCustomShape (TopoDS_Shape()); + } + + if (toEmitDataChanged) + { + QModelIndex anIndex = theIndex; + if (theIndex.column() != TreeModel_ColumnType_Visibility) + anIndex = theIndex.model()->index(theIndex.row(), TreeModel_ColumnType_Visibility, theIndex.parent()); + + getModel()->EmitDataChanged (anIndex, anIndex); + } + return true; +} + +// ======================================================================= +// function : IsVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::IsVisible (const QModelIndex& theIndex) const +{ + return myDisplayer->IsVisible (Shape (theIndex), myPresentationType); +} + +// ======================================================================= +// function : OnClicked +// purpose : +// ======================================================================= +void MessageView_VisibilityState::OnClicked (const QModelIndex& theIndex) +{ + processClicked (theIndex); + emit itemClicked (theIndex); +} + +// ======================================================================= +// function : getAlertItem +// purpose : +// ======================================================================= +MessageModel_ItemAlertPtr MessageView_VisibilityState::getAlertItem (const QModelIndex& theIndex) const +{ + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (theIndex); + if (!anItemBase) + return MessageModel_ItemAlertPtr(); + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + return anAlertItem; +} + +// ======================================================================= +// function : Shape +// purpose : +// ======================================================================= +TopoDS_Shape MessageView_VisibilityState::Shape (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (!anAlertItem) + return TopoDS_Shape(); + + /*if (!anAlertItem->GetCustomShape().IsNull()) + return anAlertItem->GetCustomShape(); + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + return TopoDS_Shape(); + + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast(anAlert); + if (anAlertExtended.IsNull()) + return TopoDS_Shape(); + + Handle(TopoDS_AlertAttribute) aShapeAttribute = Handle(TopoDS_AlertAttribute)::DownCast (anAlertExtended->Attribute()); + if (!aShapeAttribute.IsNull()) + return aShapeAttribute->GetShape(); + */ + return TopoDS_Shape(); +} + +// ======================================================================= +// function : hasTableValues +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::hasTableValues (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (!anAlertItem) + return false; + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + return false; + + if (anAlert->IsKind (STANDARD_TYPE (Message_AttributeStream))) + return true; + + return false; +} \ No newline at end of file diff --git a/tools/MessageView/MessageView_VisibilityState.hxx b/tools/MessageView/MessageView_VisibilityState.hxx new file mode 100644 index 0000000000..b26e73f4ef --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.hxx @@ -0,0 +1,99 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_VisibilityState_H +#define MessageView_VisibilityState_H + +#include + +#include + +#include + +#include +#include +#include + +class TreeModel_ModelBase; + +//! \class MessageView_VisibilityState +//! \brief Class provides connection between model and visualization control +class MessageView_VisibilityState : public QObject, public TreeModel_VisibilityState +{ + Q_OBJECT +public: + //! Constructor + MessageView_VisibilityState (TreeModel_ModelBase* theModel) + : TreeModel_VisibilityState (theModel), myPresentationType (View_PresentationType_Main) {} + + //! Destructor + ~MessageView_VisibilityState() {} + + //! Sets current displayer + //! \theDisplayer class that provides connection to visualized objects + void SetDisplayer (View_Displayer* theDisplayer) { myDisplayer = theDisplayer; } + + //! Sets presentation type for displayer + //! \param theType type value + void SetPresentationType (const View_PresentationType theType) { myPresentationType = theType; } + + //! Returns true if visibility of the item can be changed + //! \param theIndex tree model index + //! \return boolean value + Standard_EXPORT virtual bool CanBeVisible (const QModelIndex& theIndex) const Standard_OVERRIDE; + + //! Sets visibility state + //! \theIndex tree model index + //! \param theState visibility state + //! \param toEmitDataChanged boolean flag whether emit of the model should be done immediatelly + //! \return true if state is changed + Standard_EXPORT virtual bool SetVisible (const QModelIndex& theIndex, const bool theState, const bool toEmitDataChanged) Standard_OVERRIDE; + + //! Returns visibility state value + Standard_EXPORT virtual bool IsVisible (const QModelIndex& theIndex) const Standard_OVERRIDE; + +public slots: + //! Processes the mouse clicked on the index. + //! It changes the item visibility if model allows to change it. + //! \theIndex tree model index + void OnClicked (const QModelIndex& theIndex); + +signals: + //! Signal after OnClicked is performed + //! \theIndex tree model index + void itemClicked (const QModelIndex& theIndex); + +protected: + //! Gets the alert item + //! \theIndex tree model index + //! \return item or NULL + MessageModel_ItemAlertPtr getAlertItem (const QModelIndex& theIndex) const; + + //! Gets shape of the view model by the parameter index if it has a shape + //! \param theIndex tree model index + //! \return shape instance + TopoDS_Shape Shape (const QModelIndex& theIndex) const; + + //! Returns true if alert of the item has table values + //! \param theIndex tree model index + //! \return boolean result + bool hasTableValues (const QModelIndex& theIndex) const; + +private: + View_Displayer* myDisplayer; //! view displayer + View_PresentationType myPresentationType; //! presentation type +}; + +#endif diff --git a/tools/MessageView/MessageView_Window.cxx b/tools/MessageView/MessageView_Window.cxx new file mode 100644 index 0000000000..a2270827d1 --- /dev/null +++ b/tools/MessageView/MessageView_Window.cxx @@ -0,0 +1,941 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_ALERTS + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int DEFAULT_TEXT_VIEW_WIDTH = 800;// 800; +const int DEFAULT_TEXT_VIEW_HEIGHT = 700; +const int DEFAULT_TEXT_VIEW_POSITION_X = 430; +const int DEFAULT_TEXT_VIEW_POSITION_Y = 30; +const int DEFAULT_TEXT_VIEW_DELTA = 100; + +const int DEFAULT_SHAPE_VIEW_WIDTH = 400;// 900; +const int DEFAULT_SHAPE_VIEW_HEIGHT = 450; +const int DEFAULT_SHAPE_VIEW_POSITION_X = 60; +const int DEFAULT_SHAPE_VIEW_POSITION_Y = 60; + +const int DEFAULT_DETACH_POSITION_X = 5; +const int DEFAULT_DETACH_POSITION_Y = 450; + +const int MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH = 950; //600 +const int MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT = 500; + +const int MESSAGEVIEW_DEFAULT_VIEW_WIDTH = 200;// 400; +const int MESSAGEVIEW_DEFAULT_VIEW_HEIGHT = 300;// 1000; + +#include +#include +Handle(Prs3d_Drawer) GetPreviewAttributes (const Handle(AIS_InteractiveContext)& theContext) +{ + Handle(Prs3d_Drawer) myDrawer = new Prs3d_Drawer(); + myDrawer->Link (theContext->DefaultDrawer()); + + Quantity_Color aColor(Quantity_NOC_TOMATO);//Quantity_NOC_GREENYELLOW));//Quantity_NOC_BLUE1)); + Standard_ShortReal aTransparency = 0.8; + + // point parameters + myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_O_PLUS, aColor, 3.0)); + + // shading parameters + Graphic3d_MaterialAspect aShadingMaterial; + aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR); + aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT); + + myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); + myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID); + myDrawer->ShadingAspect()->SetColor (aColor); + myDrawer->ShadingAspect()->SetMaterial (aShadingMaterial); + + myDrawer->ShadingAspect()->Aspect()->ChangeFrontMaterial().SetTransparency (aTransparency); + myDrawer->ShadingAspect()->Aspect()->ChangeBackMaterial() .SetTransparency (aTransparency); + myDrawer->SetTransparency (aTransparency); + + // common parameters + myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost); + + return myDrawer; +} + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageView_Window::MessageView_Window (QWidget* theParent) +: QObject (theParent) +{ + myMainWindow = new QMainWindow (theParent); + + myTreeView = new ViewControl_TreeView (myMainWindow); + ((ViewControl_TreeView*)myTreeView)->SetPredefinedSize (QSize (MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH, + MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT)); + MessageModel_TreeModel* aModel = new MessageModel_TreeModel (myTreeView); + aModel->InitColumns(); + //aModel->SetReversed (Standard_True); + + connect (myTreeView->header(), SIGNAL (sectionResized (int, int, int)), + this, SLOT(onHeaderResized (int, int, int))); + + myTreeView->setModel (aModel); + MessageView_VisibilityState* aVisibilityState = new MessageView_VisibilityState (aModel); + aModel->SetVisibilityState (aVisibilityState); + connect (aVisibilityState, SIGNAL (itemClicked (const QModelIndex&)), this, SLOT(onTreeViewVisibilityClicked(const QModelIndex&))); + + TreeModel_Tools::UseVisibilityColumn (myTreeView); + TreeModel_Tools::SetDefaultHeaderSections (myTreeView); + + QItemSelectionModel* aSelectionModel = new QItemSelectionModel (aModel); + myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection); + myTreeView->setSelectionModel (aSelectionModel); + connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), + this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&))); + + myTreeViewActions = new MessageModel_Actions (myMainWindow, aModel, aSelectionModel); + myTestViewActions = new MessageView_ActionsTest (myMainWindow, aModel, aSelectionModel); + + myTreeView->setContextMenuPolicy (Qt::CustomContextMenu); + connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)), + this, SLOT (onTreeViewContextMenuRequested (const QPoint&))); + //new TreeModel_ContextMenu (myTreeView); + + connect (myTreeView->header(), SIGNAL (sectionResized (int, int, int)), + this, SLOT(onHeaderResized (int, int, int))); + + QModelIndex aParentIndex = myTreeView->model()->index (0, 0); + myTreeView->setExpanded (aParentIndex, true); + + myMainWindow->setCentralWidget (myTreeView); + + // property view + myPropertyView = new ViewControl_PropertyView (myMainWindow); + myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow); + myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle()); + myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow)); + myPropertyPanelWidget->setWidget (myPropertyView->GetControl()); + myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget); + connect (myPropertyPanelWidget->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT (onPropertyPanelShown (bool))); + connect (myPropertyView, SIGNAL (propertyViewDataChanged()), this, SLOT (onPropertyViewDataChanged())); + + + // view + myViewWindow = new View_Window (myMainWindow, false); + connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed())); + aVisibilityState->SetDisplayer (myViewWindow->Displayer()); + aVisibilityState->SetPresentationType (View_PresentationType_Main); + myViewWindow->ViewWidget()->SetPredefinedSize (MESSAGEVIEW_DEFAULT_VIEW_WIDTH, MESSAGEVIEW_DEFAULT_VIEW_HEIGHT); + + myViewDockWidget = new QDockWidget (tr ("View"), myMainWindow); + myViewDockWidget->setObjectName (myViewDockWidget->windowTitle()); + myViewDockWidget->setWidget (myViewWindow); + myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myViewDockWidget); + + myMainWindow->resize (DEFAULT_SHAPE_VIEW_WIDTH, DEFAULT_SHAPE_VIEW_HEIGHT); + myMainWindow->move (DEFAULT_SHAPE_VIEW_POSITION_X, DEFAULT_SHAPE_VIEW_POSITION_Y); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : SetParent +// purpose : +// ======================================================================= +void MessageView_Window::SetParent (void* theParent) +{ + QWidget* aParent = (QWidget*)theParent; + if (aParent) + { + QLayout* aLayout = aParent->layout(); + if (aLayout) + aLayout->addWidget (GetMainWindow()); + } + else + { + GetMainWindow()->setParent (0); + GetMainWindow()->setVisible (true); + } +} + +// ======================================================================= +// function : FillActionsMenu +// purpose : +// ======================================================================= +void MessageView_Window::FillActionsMenu (void* theMenu) +{ + QMenu* aMenu = (QMenu*)theMenu; + QList aDockwidgets = myMainWindow->findChildren(); + for (QList::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it) + { + QDockWidget* aDockWidget = *it; + if (aDockWidget->parentWidget() == myMainWindow) + aMenu->addAction (aDockWidget->toggleViewAction()); + } +} + +// ======================================================================= +// function : GetPreferences +// purpose : +// ======================================================================= +void MessageView_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem) +{ + theItem.Clear(); + theItem.Bind ("geometry", TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str()); + + QMap anItems; + TreeModel_Tools::SaveState (myTreeView, anItems); + for (QMap::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++) + { + theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str()); + } + + anItems.clear(); + View_Window::SaveState(myViewWindow, anItems); + for (QMap::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++) + { + theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str()); + } +} + +// ======================================================================= +// function : SetPreferences +// purpose : +// ======================================================================= +void MessageView_Window::SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem) +{ + for (TInspectorAPI_IteratorOfPreferencesDataMap anItemIt (theItem); anItemIt.More(); anItemIt.Next()) + { + if (anItemIt.Key().IsEqual ("geometry")) + myMainWindow->restoreState (TreeModel_Tools::ToByteArray (anItemIt.Value().ToCString())); + else if (TreeModel_Tools::RestoreState (myTreeView, anItemIt.Key().ToCString(), anItemIt.Value().ToCString())) + continue; + else if (myViewWindow && View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString())) + continue; + } +} + +// ======================================================================= +// function : UpdateContent +// purpose : +// ======================================================================= +void MessageView_Window::UpdateContent() +{ + bool isUpdated = false; + TCollection_AsciiString aName = "TKMessageView"; + if (myParameters->FindParameters (aName)) + { + NCollection_List aParameters = myParameters->Parameters (aName); + // Init will remove from parameters those, that are processed only one time (TShape) + Init (aParameters); + myParameters->SetParameters (aName, aParameters); + isUpdated = true; + } + if (myParameters->FindFileNames (aName)) + { + for (NCollection_List::Iterator aFilesIt (myParameters->FileNames (aName)); + aFilesIt.More(); aFilesIt.Next()) + openFile (aFilesIt.Value()); + + NCollection_List aNames; + myParameters->SetFileNames (aName, aNames); + isUpdated = true; + } + Handle(Message_Report) aDefaultReport = Message::DefaultReport(); + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aDefaultReport.IsNull() && !aViewModel->HasReport (aDefaultReport)) + { + addReport (aDefaultReport); + } + // reload report of selected item + //onReloadReport(); + + updateTreeModel(); + updateVisibleColumns(); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageView_Window::Init (NCollection_List& theParameters) +{ + Handle(AIS_InteractiveContext) aContext; + NCollection_List aParameters; + + Handle(Graphic3d_Camera) aViewCamera; + + for (NCollection_List::Iterator aParamsIt (theParameters); + aParamsIt.More(); aParamsIt.Next()) + { + Handle(Standard_Transient) anObject = aParamsIt.Value(); + Handle(Message_Report) aMessageReport = Handle(Message_Report)::DownCast (anObject); + if (!aMessageReport.IsNull()) + { + addReport (aMessageReport); + } + else if (!Handle(AIS_InteractiveContext)::DownCast (anObject).IsNull()) + { + aParameters.Append (anObject); + if (aContext.IsNull()) + aContext = Handle(AIS_InteractiveContext)::DownCast (anObject); + } + else if (!Handle(Graphic3d_Camera)::DownCast (anObject).IsNull()) + { + aViewCamera = Handle(Graphic3d_Camera)::DownCast (anObject); + } + } + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + if (!aTreeModel) + return; + + aTreeModel->EmitLayoutChanged(); + + if (!aContext.IsNull()) + { + myViewWindow->SetContext (View_ContextType_External, aContext); + //myViewWindow->GetViewToolBar()->SetCurrentContextType (View_ContextType_External); + } + + //if (!aViewCamera.IsNull()) + // myViewWindow->View()->Viewer()->View()->Camera()->Copy (aViewCamera); + + theParameters = aParameters; +} + +// ======================================================================= +// function : openFile +// purpose : +// ======================================================================= +void MessageView_Window::openFile(const TCollection_AsciiString& theFileName) +{ + if (theFileName.IsEmpty()) + return; + + const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True); + + //Handle(Message_Report) aReport = new Message_Report(); + if (aReport->MessageWriter().IsNull()) + aReport->SetMessageWriter (new XmlDrivers_MessageReportStorage()); + + aReport->MessageWriter()->SetFileName (TCollection_AsciiString (theFileName)); + aReport->MessageWriter()->ImportReport (aReport); + + addReport (aReport, theFileName); +} + +// ======================================================================= +// function : updateTreeModel +// purpose : +// ======================================================================= +void MessageView_Window::updateTreeModel() +{ + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aViewModel) + return; + + aViewModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : addReport +// purpose : +// ======================================================================= +void MessageView_Window::addReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + MessageModel_TreeModel* aModel = dynamic_cast (myTreeView->model()); + aModel->AddReport (theReport, theReportDescription); + + //updateVisibleColumns(); +} + +// ======================================================================= +// function : onTreeViewVisibilityClicked +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewVisibilityClicked(const QModelIndex& theIndex) +{ + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + TreeModel_VisibilityState* aVisibilityState = aTreeModel->GetVisibilityState(); + if (!aVisibilityState->IsVisible (theIndex)) + myPropertyView->ClearActiveTablesSelection(); +} + +// ======================================================================= +// function : onTreeViewSelectionChanged +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&) +{ + if (!myPropertyPanelWidget->toggleViewAction()->isChecked()) + return; + + updatePropertyPanelBySelection(); + updatePreviewPresentation(); +} + +// ======================================================================= +// function : onTreeViewContextMenuRequested +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition) +{ + QMenu* aMenu = new QMenu (GetMainWindow()); + + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + } + if (aRootItem) + { + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Create Default Report"), + SLOT (onCreateDefaultReport()), myMainWindow, this)); + // unite + //MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + //aMenu->addAction (ViewControl_Tools::CreateAction (aTreeModel->IsUniteAlerts() ? tr ("SetUniteAlerts - OFF") : tr ("SetUniteAlerts - ON"), + // SLOT (onUniteAlerts()), myMainWindow, this)); + // reversed + //aMenu->addAction (ViewControl_Tools::CreateAction (aTreeModel->IsReversed() ? tr ("SetReversed - OFF") : tr ("SetReversed - ON"), + // SLOT (onSetReversedAlerts()), myMainWindow, this)); + } + else if (aReportItem) + { + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export Report"), SLOT (onExportReport()), myMainWindow, this)); + const TCollection_AsciiString& aDescription = aReportItem->GetDescription(); + if (!aDescription.IsEmpty()) + { + OSD_Path aPath(aDescription); + OSD_File aDescriptionFile (aPath); + if (aDescriptionFile.IsReadable()) + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Reload"), SLOT (onReloadReport()), myMainWindow, this)); + } + Handle(Message_Report) aReport = aReportItem->GetReport(); + QAction* anAction = ViewControl_Tools::CreateAction (tr ("Export by alert"), SLOT (onAutoExportActivate()), myMainWindow, this); + anAction->setCheckable (true); + anAction->setChecked (aReport->WriteFileOnEachAlert()); + aMenu->addAction (anAction); + + anAction = ViewControl_Tools::CreateAction (tr ("Export trace only"), SLOT (onExportTraceOnly()), myMainWindow, this); + anAction->setCheckable (true); + bool isTraceOnly = aReport->MessageWriter().IsNull() ? false : aReport->MessageWriter()->Gravity() == Message_Trace; + anAction->setChecked (isTraceOnly); + aMenu->addAction (anAction); + } + aMenu->addSeparator(); + + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Preview children presentations"), SLOT (onPreviewChildren()), myMainWindow, this)); + aMenu->addSeparator(); + + myTreeViewActions->AddMenuActions (aSelectedIndices, aMenu); + addActivateMetricActions (aMenu); + +#ifdef DEBUG_ALERTS + aMenu->addSeparator(); + myTestViewActions->AddMenuActions (aSelectedIndices, aMenu); +#endif + + QPoint aPoint = myTreeView->mapToGlobal (thePosition); + aMenu->exec (aPoint); +} + +// ======================================================================= +// function : onPropertyPanelShown +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyPanelShown (bool isToggled) +{ + if (!isToggled) + return; + + updatePropertyPanelBySelection(); +} + +// ======================================================================= +// function : onPropertyViewDataChanged +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyViewDataChanged() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + + updatePropertyPanelBySelection(); + updatePreviewPresentation(); +} + +// ======================================================================= +// function : onHeaderResized +// purpose : +// ======================================================================= +void MessageView_Window::onHeaderResized (int theSectionId, int, int) +{ + TreeModel_ModelBase* aViewModel = dynamic_cast (myTreeView->model()); + + TreeModel_HeaderSection* aSection = aViewModel->ChangeHeaderItem (theSectionId); + aSection->SetWidth (myTreeView->columnWidth (theSectionId)); +} + +// ======================================================================= +// function : onEraseAllPerformed +// purpose : +// ======================================================================= +void MessageView_Window::onEraseAllPerformed() +{ + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + + // TODO: provide update for only visibility state for better performance TopoDS_Shape myCustomShape; + + aTreeModel->Reset(); + aTreeModel->EmitLayoutChanged(); +} + +// ======================================================================= +// function : onExportReport +// purpose : +// ======================================================================= +void MessageView_Window::onExportReport() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + return; + + QString aFilter (tr ("Document file (*.json *)")); + QString aSelectedFilter; + QString aFileName = QFileDialog::getSaveFileName (0, tr ("Export report to file"), QString(), aFilter, &aSelectedFilter); + + Handle(Message_Report) aReport = aReportItem->GetReport(); + Standard_SStream aStream; + aReport->DumpJson(aStream); + + QFile aLogFile(aFileName); + if (!aLogFile.open(QFile::WriteOnly | QFile::Text)) + { + return; + } + QTextStream anOut( &aLogFile ); + anOut << Standard_Dump::FormatJson (aStream).ToCString();//aStream.str().c_str(); + aLogFile.close(); +} + +// ======================================================================= +// function : onCreateDefaultReport +// purpose : +// ======================================================================= +void MessageView_Window::onCreateDefaultReport() +{ + if (!Message::DefaultReport().IsNull()) + { + return; + } + + addReport (Message::DefaultReport (Standard_True)); +} + +// ======================================================================= +// function : onImportReport +// purpose : +// ======================================================================= +//void MessageView_Window::onUniteAlerts() +//{ + //MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + //Standard_Boolean isUniteAlerts = aTreeModel->IsUniteAlerts(); + + //aTreeModel->SetUniteAlerts (!isUniteAlerts); +//} + +// ======================================================================= +// function : onSetReversedAlerts +// purpose : +// ======================================================================= +void MessageView_Window::onSetReversedAlerts() +{ + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + Standard_Boolean isReversed = aTreeModel->IsReversed(); + + aTreeModel->SetReversed (!isReversed); +} + +// ======================================================================= +// function : onReloadReport +// purpose : +// ======================================================================= +void MessageView_Window::onReloadReport() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + const TCollection_AsciiString aDescription = aReportItem->GetDescription(); + if (aDescription.IsEmpty()) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + aReport->Clear(); + if (aReport->MessageWriter().IsNull()) + aReport->SetMessageWriter (new XmlDrivers_MessageReportStorage()); + + aReport->MessageWriter()->SetFileName (TCollection_AsciiString (aDescription)); + if (!aReport->MessageWriter()->ImportReport (aReport)) + return; + + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + aModel->clearSelection(); + aTreeModel->SetReport (aReportItem->Row(), aReport, aDescription); +} + +// ======================================================================= +// function : onAutoExportActivate +// purpose : +// ======================================================================= +void MessageView_Window::onAutoExportActivate() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + QAction* anAction = (QAction*)(sender()); + aReport->SetWriteFileOnEachAlert (anAction->isChecked()); +} + +// ======================================================================= +// function : onExportTraceOnly +// purpose : +// ======================================================================= +void MessageView_Window::onExportTraceOnly() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport->MessageWriter().IsNull()) + return; + + QAction* anAction = (QAction*)(sender()); + aReport->MessageWriter()->SetGravity (anAction->isChecked() ? Message_Trace : Message_Info); +} + +// ======================================================================= +// function : onPreviewChildren +// purpose : +// ======================================================================= +void MessageView_Window::onPreviewChildren() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + NCollection_List aPresentations; + TreeModel_ModelBase::SubItemsPresentations (aSelectedIndices, aPresentations); + + displayer()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations); +} + +// ======================================================================= +// function : addActivateMetricActions +// purpose : +// ======================================================================= +void MessageView_Window::addActivateMetricActions (QMenu* theMenu) +{ + Handle(Message_Report) aReport = Message::DefaultReport(); + if (aReport.IsNull()) + { + return; + } + + QMenu* aSubMenu = new QMenu ("Activate metric"); + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + QAction* anAction = ViewControl_Tools::CreateAction (Message::MetricToString (aMetricType), + SLOT (OnActivateMetric()), parent(), this); + anAction->setCheckable (true); + anAction->setChecked (aReport->ActiveMetrics().Contains (aMetricType)); + aSubMenu->addAction (anAction); + } + aSubMenu->addSeparator(); + aSubMenu->addAction (ViewControl_Tools::CreateAction ("Deactivate all", SLOT (OnDeactivateAllMetrics()), parent(), this)); + + theMenu->addMenu (aSubMenu); +} + +// ======================================================================= +// function : OnActivateMetric +// purpose : +// ======================================================================= +void MessageView_Window::OnActivateMetric() +{ + QAction* anAction = (QAction*)(sender()); + + Message_MetricType aMetricType; + if (!Message::MetricFromString (anAction->text().toStdString().c_str(), aMetricType)) + return; + + Handle(Message_Report) aReport = Message::DefaultReport(); + const NCollection_Map& anActiveMetrics = aReport->ActiveMetrics(); + + aReport->SetActiveMetric (aMetricType, !anActiveMetrics.Contains (aMetricType)); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : OnDeactivateAllMetrics +// purpose : +// ======================================================================= +void MessageView_Window::OnDeactivateAllMetrics() +{ + Handle(Message_Report) aReport = Message::DefaultReport(); + if (aReport.IsNull()) + return; + aReport->ClearMetrics(); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : displayer +// purpose : +// ======================================================================= +View_Displayer* MessageView_Window::displayer() +{ + return myViewWindow->Displayer(); +} + +// ======================================================================= +// function : updatePropertyPanelBySelection +// purpose : +// ======================================================================= +void MessageView_Window::updatePropertyPanelBySelection() +{ + /*QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + + QList aTableValues; + MessageModel_Tools::GetPropertyTableValues (anItemBase, aTableValues); + + myPropertyView->Init (aTableValues);*/ + ViewControl_TableModelValues* aTableValues = 0; + + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (anItemBase) + { + Handle(TreeModel_ItemProperties) anItemProperties = anItemBase->Properties (); + if (!anItemProperties.IsNull()) + { + aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (anItemProperties); + } + } + myPropertyView->Init (aTableValues); +} + +// ======================================================================= +// function : updatePreviewPresentation +// purpose : +// ======================================================================= +void MessageView_Window::updatePreviewPresentation() +{ + Handle(AIS_InteractiveContext) aContext = myViewWindow->ViewToolBar()->CurrentContext(); + if (aContext.IsNull()) + return; + + NCollection_List aPresentations; + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + anItemBase->Presentations (aPresentations); + } + + displayer()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations); +} + +// ======================================================================= +// function : updateVisibleColumns +// purpose : +// ======================================================================= +void MessageView_Window::updateVisibleColumns() +{ + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + + NCollection_Map anActiveMetrics; + for (NCollection_List::Iterator anIterator (aViewModel->Reports()); anIterator.More(); anIterator.Next()) + { + Handle(Message_Report) aReport = anIterator.Value().myReport; + for (NCollection_Map::Iterator aMetricsIterator (aReport->ActiveMetrics()); aMetricsIterator.More(); aMetricsIterator.Next()) + { + if (anActiveMetrics.Contains (aMetricsIterator.Value())) + continue; + anActiveMetrics.Add (aMetricsIterator.Value()); + } + } + + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + QList aMetricColumns; + aViewModel->GetMetricColumns (aMetricType, aMetricColumns); + bool isColumnHidden = !anActiveMetrics.Contains (aMetricType); + for (int i = 0; i < aMetricColumns.size(); i++) + { + int aColumnId = aMetricColumns[i]; + myTreeView->setColumnHidden (aColumnId, isColumnHidden); + TreeModel_HeaderSection* aSection = aViewModel->ChangeHeaderItem (aColumnId); + aSection->SetIsHidden (isColumnHidden); + } + } +} diff --git a/tools/MessageView/MessageView_Window.hxx b/tools/MessageView/MessageView_Window.hxx new file mode 100644 index 0000000000..bae2ad6fa8 --- /dev/null +++ b/tools/MessageView/MessageView_Window.hxx @@ -0,0 +1,209 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_Window_H +#define MessageView_Window_H + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // conditional expression is constant +#endif +#include +#include +#include +#include +#include +#include +#include + +class View_Displayer; +class View_Window; + +class ViewControl_PropertyView; + +class MessageView_ActionsTest; + +class QDockWidget; +class QMainWindow; +class QMenu; +class QWidget; + +//! \class MessageView_Window +//! Window that unites all MessageView controls. +class MessageView_Window : public QObject +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT MessageView_Window (QWidget* theParent); + + //! Destructor + virtual ~MessageView_Window() {} + + //! Provides the container with a parent where this container should be inserted. + //! If Qt implementation, it should be QWidget with QLayout set inside + //! \param theParent a parent class + Standard_EXPORT void SetParent (void* theParent); + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) + { myParameters = theParameters; myTreeViewActions->SetParameters (theParameters); } + + //! Provide container for actions available in inspector on general level + //! \param theMenu if Qt implementation, it is QMenu object + Standard_EXPORT virtual void FillActionsMenu (void* theMenu); + + //! Returns plugin preferences: dock widgets state, tree view columns. + //! \param theItem container of preference elements + Standard_EXPORT void GetPreferences (TInspectorAPI_PreferencesDataMap& theItem); + + //! Applies plugin preferences + //! \param theItem container of preference elements + Standard_EXPORT void SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem); + + //! Applyes parameters to Init controls, opens files if there are in parameters, updates OCAF tree view model + Standard_EXPORT void UpdateContent(); + + //! Returns main control + QMainWindow* GetMainWindow() const { return myMainWindow; } + + //! Returns current tree view + QTreeView* GetTreeView() const { return myTreeView; } + +protected: + //! Appends shape into tree view model + //! \param theShape a shape instance + //! \param theReportDescription an additional report information + void addReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + +private: + + //! Fills controls of the plugin by parameters: + //! - Fine AIS_InteractiveObject and fills View if it if it differs from the current context + //! \param theParameters a parameters container + void Init (NCollection_List& theParameters); + + //! Read Shape from the file name, add Shape into tree view + //! \param theFileName BREP file name + void openFile (const TCollection_AsciiString& theFileName); + + //! Updates tree model + void updateTreeModel(); + +protected slots: + //! Updates property view selection in table if the item is hidden + //! \param theIndex tree view model index + void onTreeViewVisibilityClicked(const QModelIndex& theIndex); + + //! Udpates all controls by changed selection in OCAF tree view + //! \param theSelected list of selected tree view items + //! \param theDeselected list of deselected tree view items + void onTreeViewSelectionChanged (const QItemSelection& theSelected, const QItemSelection& theDeselected); + + //! Shows context menu for tree view selected item. It contains expand/collapse actions. + //! \param thePosition a clicked point + void onTreeViewContextMenuRequested (const QPoint& thePosition); + + //! Display content of selected tree view item if isToggled is true + //! \param isToggled true if the property dock widget is shown + void onPropertyPanelShown (bool isToggled); + + //! Update tree view item, preview presentation by item value change + void onPropertyViewDataChanged(); + + //! Update tree view header item width + void onHeaderResized (int theSectionId, int, int); + + //! Updates visibility states by erase all in context + void onEraseAllPerformed(); + + //! Export report into document + void onExportReport(); + + //! Create default report into document + void onCreateDefaultReport(); + + //! Unite alerts in view model + //void onUniteAlerts(); + + //! Sets report reversed + void onSetReversedAlerts(); + + //! Reads if possible report of a selected item and updates this report in tree view + void onReloadReport(); + + //! Sets report state to write it by each message alert + void onAutoExportActivate(); + + //! Sets report writer state to write only trace information of alerts + void onExportTraceOnly(); + + //! Iterates by children items of selected items and display its presentations if found + void onPreviewChildren(); + + //! Switch active state in report for clicked type of metric + void OnActivateMetric(); + + //! Deactivate all types of metrics for the current report + void OnDeactivateAllMetrics(); + +protected: + //! Appends items to activate report metrics + void addActivateMetricActions (QMenu* theMenu); + + //! Returns displayer where the presentations/preview should be shown/erased + //! If default view is created, it returns displayer of this view + Standard_EXPORT View_Displayer* displayer(); + + //! Updates property panel content by item selected in tree view. + void updatePropertyPanelBySelection(); + + //!< Updates presentation of preview for parameter shapes. Creates a compound of the shapes + void updatePreviewPresentation(); + + //!< Sets reports metric columns visible if used + void updateVisibleColumns(); + +private: + QMainWindow* myMainWindow; //!< main control, parent for all MessageView controls + QDockWidget* myViewDockWidget; //!< view dock widget to hide/show + + QDockWidget* myPropertyPanelWidget; //!< property pane dockable widget + ViewControl_PropertyView* myPropertyView; //!< property control to display model item values if exist + + View_Window* myViewWindow; //!< OCC 3d view to visualize presentations + QTreeView* myTreeView; //!< tree view visualized shapes + MessageModel_Actions* myTreeViewActions; //!< processing history view actions + MessageView_ActionsTest* myTestViewActions; //!< check view actions + + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + + Handle(AIS_InteractiveObject) myPreviewPresentation; //!< presentation of preview for a selected object +}; + +#endif diff --git a/tools/ShapeView/ShapeView_Window.cxx b/tools/ShapeView/ShapeView_Window.cxx index d6f54d75cc..7ae4fb55c4 100644 --- a/tools/ShapeView/ShapeView_Window.cxx +++ b/tools/ShapeView/ShapeView_Window.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -38,8 +40,15 @@ #include #include +#include +#include #include #include +#include +#include +#include +#include +#include #include #include @@ -106,6 +115,7 @@ ShapeView_Window::ShapeView_Window (QWidget* theParent) aVisibilityState, SLOT (OnClicked(const QModelIndex&))); QItemSelectionModel* aSelModel = new QItemSelectionModel (myTreeView->model(), myTreeView); + myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection); myTreeView->setSelectionModel (aSelModel); connect (aSelModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&))); @@ -128,7 +138,7 @@ ShapeView_Window::ShapeView_Window (QWidget* theParent) connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed())); aVisibilityState->SetDisplayer (myViewWindow->Displayer()); aVisibilityState->SetPresentationType (View_PresentationType_Main); - myViewWindow->SetPredefinedSize (SHAPEVIEW_DEFAULT_VIEW_WIDTH, SHAPEVIEW_DEFAULT_VIEW_HEIGHT); + myViewWindow->ViewWidget()->SetPredefinedSize (SHAPEVIEW_DEFAULT_VIEW_WIDTH, SHAPEVIEW_DEFAULT_VIEW_HEIGHT); QDockWidget* aViewDockWidget = new QDockWidget (tr ("View"), myMainWindow); aViewDockWidget->setObjectName (aViewDockWidget->windowTitle()); @@ -359,42 +369,47 @@ void ShapeView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); - if (!anItemBase) - return; - QMenu* aMenu = new QMenu(myMainWindow); + ShapeView_ItemRootPtr aRootItem = itemDynamicCast (anItemBase); if (aRootItem) { aMenu->addAction (ViewControl_Tools::CreateAction ("Load BREP file", SLOT (onLoadFile()), myMainWindow, this)); aMenu->addAction (ViewControl_Tools::CreateAction ("Remove all shape items", SLOT (onClearView()), myMainWindow, this)); } - else { + else if (anItemBase) { // single selection aMenu->addAction (ViewControl_Tools::CreateAction ("Export to BREP", SLOT (onExportToBREP()), myMainWindow, this)); + ShapeView_ItemShapePtr aShapeItem = itemDynamicCast(anItemBase); - const TopoDS_Shape& aShape = aShapeItem->GetItemShape(); - TopAbs_ShapeEnum anExplodeType = aShapeItem->ExplodeType(); - NCollection_List anExplodeTypes; - ShapeView_Tools::IsPossibleToExplode (aShape, anExplodeTypes); - if (anExplodeTypes.Size() > 0) + if (aShapeItem) { - QMenu* anExplodeMenu = aMenu->addMenu ("Explode"); - for (NCollection_List::Iterator anExpIterator (anExplodeTypes); anExpIterator.More(); - anExpIterator.Next()) + const TopoDS_Shape& aShape = aShapeItem->GetItemShape(); + TopAbs_ShapeEnum anExplodeType = aShapeItem->ExplodeType(); + NCollection_List anExplodeTypes; + ShapeView_Tools::IsPossibleToExplode (aShape, anExplodeTypes); + if (anExplodeTypes.Size() > 0) { - TopAbs_ShapeEnum aType = anExpIterator.Value(); - QAction* anAction = ViewControl_Tools::CreateAction (TopAbs::ShapeTypeToString (aType), SLOT (onExplode()), myMainWindow, this); - anExplodeMenu->addAction (anAction); - if (anExplodeType == aType) + QMenu* anExplodeMenu = aMenu->addMenu ("Explode"); + for (NCollection_List::Iterator anExpIterator (anExplodeTypes); anExpIterator.More(); + anExpIterator.Next()) { - anAction->setCheckable (true); - anAction->setChecked (true); + TopAbs_ShapeEnum aType = anExpIterator.Value(); + QAction* anAction = ViewControl_Tools::CreateAction (TopAbs::ShapeTypeToString (aType), SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addAction (anAction); + if (anExplodeType == aType) + { + anAction->setCheckable (true); + anAction->setChecked (true); + } } + QAction* anAction = ViewControl_Tools::CreateAction ("NONE", SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addSeparator(); + anExplodeMenu->addAction (anAction); } - QAction* anAction = ViewControl_Tools::CreateAction ("NONE", SLOT (onExplode()), myMainWindow, this); - anExplodeMenu->addSeparator(); - anExplodeMenu->addAction (anAction); } } + aMenu->addAction (ViewControl_Tools::CreateAction ("Create Face", SLOT (onCreateFace()), myMainWindow, this)); + aMenu->addAction (ViewControl_Tools::CreateAction ("Create Compound", SLOT (onCreateCompound()), myMainWindow, this)); + aMenu->addAction (ViewControl_Tools::CreateAction ("Algo: Incremental Mesh", SLOT (onIncrementalMesh()), myMainWindow, this)); QPoint aPoint = myTreeView->mapToGlobal (thePosition); aMenu->exec (aPoint); @@ -520,3 +535,84 @@ void ShapeView_Window::onExportToBREP() anItem->SetFileName (aFileNameIndiced.ToCString()); aFileName = aFileNameIndiced.ToCString(); } + +// ======================================================================= +// function : onCreateFace +// purpose : +// ======================================================================= +void ShapeView_Window::onCreateFace() +{ + /*QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QList anItems = TreeModel_ModelBase::SelectedItems (aModel->selectedIndexes()); + + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + NCollection_List anItemPresentations; + + BRepBuilderAPI_MakeWire aWireBuilder; + for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + { + ShapeView_ItemShapePtr anItem = itemDynamicCast(*anItemIt); + if (!anItem) + continue; + + const TopoDS_Shape& aShape = anItem->GetItemShape(); + if (aShape.ShapeType() != TopAbs_EDGE) + continue; + + const TopoDS_Edge& aSourceEdge = TopoDS::Edge (aShape); + const TopoDS_Edge& anEdgeCopied = TopoDS::Edge (aSourceEdge.EmptyCopied()); + + aWireBuilder.Add (anEdgeCopied);//aSourceEdge); + } + if (!aWireBuilder.IsDone()) + return; + + BRepBuilderAPI_MakeFace aFaceBuilder; + + const TopoDS_Wire& aWire = aWireBuilder.Wire(); + const TopoDS_Wire& aWireCopied = TopoDS::Wire (aWire.EmptyCopied()); + + aFaceBuilder.Add (aWireCopied); + + addShape (aFaceBuilder.Face()); + */ +} + +// ======================================================================= +// function : onCreateCompound +// purpose : +// ======================================================================= +void ShapeView_Window::onCreateCompound() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QList anItems = TreeModel_ModelBase::SelectedItems (aModel->selectedIndexes()); + + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + NCollection_List anItemPresentations; + + BRep_Builder aBB; + TopoDS_Compound aC; + aBB.MakeCompound(aC); + + for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + { + ShapeView_ItemShapePtr anItem = itemDynamicCast(*anItemIt); + if (!anItem) + return; + + aBB.Add(aC, anItem->GetItemShape()); + } + addShape (aC); +} + +// ======================================================================= +// function : onIncrementalMesh +// purpose : +// ======================================================================= +void ShapeView_Window::onIncrementalMesh() +{ +} diff --git a/tools/ShapeView/ShapeView_Window.hxx b/tools/ShapeView/ShapeView_Window.hxx index 950119326e..5119fd9039 100644 --- a/tools/ShapeView/ShapeView_Window.hxx +++ b/tools/ShapeView/ShapeView_Window.hxx @@ -129,6 +129,15 @@ protected slots: //! Views BREP files of selected items if exist void onExportToBREP(); + //! Create a wire of selected edges + void onCreateFace(); + + //! Create a compound of selected shapes + void onCreateCompound(); + + //! Perform BRepMesh_IncrementalMesh on the selected shape + void onIncrementalMesh(); + //! Convers file name to Ascii String and perform opeging file //! \param theFileName a file name to be opened void onOpenFile(const QString& theFileName) { OpenFile (TCollection_AsciiString (theFileName.toUtf8().data())); } diff --git a/tools/TInspectorEXE/TInspectorEXE.cxx b/tools/TInspectorEXE/TInspectorEXE.cxx index b22e57eb81..f3b29732f2 100644 --- a/tools/TInspectorEXE/TInspectorEXE.cxx +++ b/tools/TInspectorEXE/TInspectorEXE.cxx @@ -19,6 +19,8 @@ #include +#include +#include #include #include @@ -104,6 +106,9 @@ int main (int argc, char** argv) if (!strcmp (argv[anArgId], "vinspector")) aPlugins.insert ("TKVInspector"); + + if (!strcmp (argv[anArgId], "messageview")) + aPlugins.insert ("TKMessageView"); } NCollection_List aParameters; @@ -123,7 +128,14 @@ int main (int argc, char** argv) aPlugins.insert("TKShapeView"); aPlugins.insert("TKVInspector"); - anActivatedPluginName = "TKDFBrowser"; + //Handle(Message_Report) aReport = Message::DefaultReport (Standard_True); + //aReport->SetLimit (100);//30); + aPlugins.insert("TKMessageView"); + + //anActivatedPluginName = "TKVInspector"; + //anActivatedPluginName = "TKMessageView"; + //anActivatedPluginName = "TKDFBrowser"; + anActivatedPluginName = "TKShapeView"; } else anActivatedPluginName = *aPlugins.rbegin(); diff --git a/tools/TKMessageModel/CMakeLists.txt b/tools/TKMessageModel/CMakeLists.txt new file mode 100644 index 0000000000..911ffb1fbe --- /dev/null +++ b/tools/TKMessageModel/CMakeLists.txt @@ -0,0 +1,5 @@ +project(TKMessageModel) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) diff --git a/tools/TKMessageModel/EXTERNLIB b/tools/TKMessageModel/EXTERNLIB new file mode 100644 index 0000000000..54b02742af --- /dev/null +++ b/tools/TKMessageModel/EXTERNLIB @@ -0,0 +1,10 @@ +TKMath +TKBin +TKBRep +TKGeomBase +TKG3d +TKTInspectorAPI +TKService +TKTopAlgo +TKTreeModel +CSF_QT diff --git a/tools/TKMessageModel/FILES b/tools/TKMessageModel/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/tools/TKMessageModel/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/tools/TKMessageModel/PACKAGES b/tools/TKMessageModel/PACKAGES new file mode 100644 index 0000000000..9021fbf297 --- /dev/null +++ b/tools/TKMessageModel/PACKAGES @@ -0,0 +1 @@ +MessageModel diff --git a/tools/TKMessageView/CMakeLists.txt b/tools/TKMessageView/CMakeLists.txt new file mode 100644 index 0000000000..9b3c1aaec7 --- /dev/null +++ b/tools/TKMessageView/CMakeLists.txt @@ -0,0 +1,5 @@ +project(TKMessageView) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) diff --git a/tools/TKMessageView/EXTERNLIB b/tools/TKMessageView/EXTERNLIB new file mode 100644 index 0000000000..84e5b5d8b5 --- /dev/null +++ b/tools/TKMessageView/EXTERNLIB @@ -0,0 +1,13 @@ +TKTInspectorAPI +TKMath +TKMessageModel +TKBin +TKBRep +TKGeomBase +TKG3d +TKService +TKTopAlgo +TKTreeModel +TKView +TKXml +CSF_QT diff --git a/tools/TKMessageView/FILES b/tools/TKMessageView/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/tools/TKMessageView/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/tools/TKMessageView/PACKAGES b/tools/TKMessageView/PACKAGES new file mode 100644 index 0000000000..46a67b229d --- /dev/null +++ b/tools/TKMessageView/PACKAGES @@ -0,0 +1 @@ +MessageView diff --git a/tools/ToolsDraw/ToolsDraw.cxx b/tools/ToolsDraw/ToolsDraw.cxx index c0abd7766a..104bda3336 100644 --- a/tools/ToolsDraw/ToolsDraw.cxx +++ b/tools/ToolsDraw/ToolsDraw.cxx @@ -62,6 +62,7 @@ Standard_Boolean convertToPluginName (const TCollection_AsciiString& theArgument if (anArgument == "dfbrowser") { thePluginName = "TKDFBrowser"; return Standard_True; } else if (anArgument == "shapeview") { thePluginName = "TKShapeView"; return Standard_True; } else if (anArgument == "vinspector") { thePluginName = "TKVInspector"; return Standard_True; } + else if (anArgument == "messageview") { thePluginName = "TKMessageView"; return Standard_True; } return Standard_False; } @@ -305,6 +306,7 @@ static int tinspector (Draw_Interpretor& di, Standard_Integer theArgsNb, const c aPlugins.Append ("TKDFBrowser"); aPlugins.Append ("TKShapeView"); aPlugins.Append ("TKVInspector"); + aPlugins.Append ("TKMessageView"); } aPluginNameToActivate = !aPluginNameToActivate.IsEmpty() ? aPluginNameToActivate : aPlugins.First(); } @@ -391,10 +393,10 @@ void ToolsDraw::Commands(Draw_Interpretor& theCommands) "\n\t\t: Starts tool of inspection." "\n\t\t: Options:" "\n\t\t: -plugins enters plugins that should be added in the inspector." - "\n\t\t: Available names are: dfbrowser, vinspector and shapeview." + "\n\t\t: Available names are: dfbrowser, vinspector, shapeview and messageview." "\n\t\t: Plugins order will be the same as defined in arguments." "\n\t\t: 'all' adds all available plugins in the order:" - "\n\t\t: DFBrowser, VInspector and ShapeView." + "\n\t\t: DFBrowser, VInspector, ShapeView and MessageView." "\n\t\t: If at the first call this option is not used, 'all' option is applied;" "\n\t\t: -activate activates the plugin in the tool view." "\n\t\t: If at the first call this option is not used, the first plugin is activated;" diff --git a/tools/TreeModel/TreeModel_ColumnType.hxx b/tools/TreeModel/TreeModel_ColumnType.hxx index 80cb3f97da..520cec6fdf 100644 --- a/tools/TreeModel/TreeModel_ColumnType.hxx +++ b/tools/TreeModel/TreeModel_ColumnType.hxx @@ -24,7 +24,8 @@ enum TreeModel_ColumnType { TreeModel_ColumnType_Name = 0, //! name column - TreeModel_ColumnType_Visibility //! visibility state column + TreeModel_ColumnType_Visibility, //! visibility state column + TreeModel_ColumnType_Row //! row of the item column }; #endif diff --git a/tools/TreeModel/TreeModel_ContextMenu.cxx b/tools/TreeModel/TreeModel_ContextMenu.cxx index 9a60792c60..9cd0d07ab6 100644 --- a/tools/TreeModel/TreeModel_ContextMenu.cxx +++ b/tools/TreeModel/TreeModel_ContextMenu.cxx @@ -55,7 +55,7 @@ void TreeModel_ContextMenu::onTreeViewHeaderContextMenuRequested (const QPoint& int aNbSections = aModel->columnCount(); for (int aColumnId = 0; aColumnId < aNbSections; aColumnId++) { - QAction* anAction = ViewControl_Tools::CreateAction (aModel->GetHeaderItem (aColumnId).GetName(), + QAction* anAction = ViewControl_Tools::CreateAction (aModel->ChangeHeaderItem (aColumnId)->GetName(), SLOT (onColumnVisibilityChanged()), myTreeView, this); anAction->setCheckable (true); anAction->setChecked (!myTreeView->isColumnHidden (aColumnId)); diff --git a/tools/TreeModel/TreeModel_ItemBase.cxx b/tools/TreeModel/TreeModel_ItemBase.cxx index 1b23b909cb..359ed39018 100644 --- a/tools/TreeModel/TreeModel_ItemBase.cxx +++ b/tools/TreeModel/TreeModel_ItemBase.cxx @@ -14,6 +14,8 @@ // commercial license or contractual agreement. #include + +#include #include #include #include @@ -195,7 +197,7 @@ QVariant TreeModel_ItemBase::initValue (const int theItemRole) const switch (Column()) { - case 1: { return Row(); } + case TreeModel_ColumnType_Row: { return Row(); } } return QVariant(); diff --git a/tools/TreeModel/TreeModel_ItemBase.hxx b/tools/TreeModel/TreeModel_ItemBase.hxx index 4c121f8213..8654b06876 100644 --- a/tools/TreeModel/TreeModel_ItemBase.hxx +++ b/tools/TreeModel/TreeModel_ItemBase.hxx @@ -16,12 +16,12 @@ #ifndef TreeModel_ItemBase_H #define TreeModel_ItemBase_H -#include #include #include #include #include #include +#include #include @@ -150,7 +150,10 @@ public: //! Returns the item properties const Handle(TreeModel_ItemProperties)& Properties() const { return myProperties; } + //! Returns presentation of the attribute to be visualized in the view + //! \thePresentations [out] container of presentation handles to be visualized Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + protected: //! \param theParent the parent item diff --git a/tools/TreeModel/TreeModel_ItemProperties.cxx b/tools/TreeModel/TreeModel_ItemProperties.cxx index 631d2f2c18..8aa7a0d81d 100644 --- a/tools/TreeModel/TreeModel_ItemProperties.cxx +++ b/tools/TreeModel/TreeModel_ItemProperties.cxx @@ -39,6 +39,15 @@ void TreeModel_ItemProperties::Init () const Standard_SStream& aStream = Item()->Stream(); + InitByStream (aStream); +} + +// ======================================================================= +// function : InitByStream +// purpose : +// ======================================================================= +void TreeModel_ItemProperties::InitByStream (const Standard_SStream& aStream) +{ NCollection_IndexedDataMap aValues; TCollection_AsciiString aStreamText = Standard_Dump::Text (aStream); Standard_Dump::SplitJson (aStreamText, aValues); @@ -48,8 +57,15 @@ void TreeModel_ItemProperties::Init () Standard_DumpValue aKeyValue; if (!aStreamParent) { - const Handle(Standard_Transient)& anItemObject = Item()->Object(); - aKey = anItemObject.IsNull() ? "Dump" : anItemObject->DynamicType()->Name(); + if (!Item() || Item()->Object().IsNull()) + { + aKey = "Dump"; + } + else + { + const Handle(Standard_Transient)& anItemObject = Item()->Object(); + aKey = anItemObject.IsNull() ? "Dump" : anItemObject->DynamicType()->Name(); + } aKeyValue = Standard_DumpValue (aStreamText, 1); myKey = aKey; @@ -95,6 +111,11 @@ void TreeModel_ItemProperties::Init () (int)(aGreen * aDelta), (int)(aBlue * aDelta))); } } + // in case if the stream alert has empty key avalue, use as the key the first row value + if ((myKey.IsEmpty() || myKey.IsEqual ("Dump")) && myRowValues.Size() > 0) + { + myKey = myRowValues.FindFromIndex (1).Value.toString().toStdString().c_str(); + } } // ======================================================================= @@ -172,10 +193,16 @@ ViewControl_EditType TreeModel_ItemProperties::EditType (const int, const int th // function : SetData // purpose : // ======================================================================= -bool TreeModel_ItemProperties::SetData (const int /*theRow*/, const int theColumn, const QVariant& /*theValue*/, int) +bool TreeModel_ItemProperties::SetData (const int theRow, const int theColumn, const QVariant& theValue, int theRole) { if (theColumn == 0) return false; + + if (theRole == Qt::DisplayRole || theRole == Qt::EditRole) + { + myRowValues.ChangeFromIndex (theRow + 1).Value = theValue; + } + return false; } @@ -185,6 +212,8 @@ bool TreeModel_ItemProperties::SetData (const int /*theRow*/, const int theColum // ======================================================================= void TreeModel_ItemProperties::Presentations (NCollection_List& thePresentations) { + if (!Item()) + return; const Standard_SStream& aStream = Item()->Stream(); Convert_Tools::ConvertStreamToPresentations (aStream, 1, -1, thePresentations); } diff --git a/tools/TreeModel/TreeModel_ItemProperties.hxx b/tools/TreeModel/TreeModel_ItemProperties.hxx index 7f498d70e4..a86ef9baec 100644 --- a/tools/TreeModel/TreeModel_ItemProperties.hxx +++ b/tools/TreeModel/TreeModel_ItemProperties.hxx @@ -73,6 +73,9 @@ public: //! Sets the current item void SetItem (const TreeModel_ItemBasePtr& theItem) { myItem = theItem; } + //! Fills properties with the stream value + Standard_EXPORT void InitByStream (const Standard_SStream& theStream); + //! Returns the current item TreeModel_ItemBasePtr Item() const { return myItem; } @@ -80,7 +83,7 @@ public: Standard_EXPORT void Init(); //! If the item has internal values, there should be reseted here. - Standard_EXPORT virtual void Reset(); + Standard_EXPORT void Reset(); //! Returns number of table rows //! \return an integer value @@ -108,18 +111,18 @@ public: //! \param theColumn a model index column //! \param theRole a view role //! \return true if the value is changed - Standard_EXPORT virtual bool SetData (const int theRow, const int theColumn, const QVariant& theValue, - int theRole = Qt::DisplayRole); + Standard_EXPORT bool SetData (const int theRow, const int theColumn, const QVariant& theValue, + int theRole = Qt::DisplayRole); //! Returns presentation of the attribute to be visualized in the view //! \thePresentations [out] container of presentation handles to be visualized - Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + Standard_EXPORT void Presentations (NCollection_List& thePresentations); //! Returns flags for the item: ItemIsEnabled | Qt::ItemIsSelectable. //! Additional flag for the column 1 is Qt::ItemIsEditable. //! \param theIndex a model index //! \return flags - Standard_EXPORT virtual Qt::ItemFlags TableFlags (const int theRow, const int theColumn) const; + Standard_EXPORT Qt::ItemFlags TableFlags (const int theRow, const int theColumn) const; //! Returns stream value of the item to fulfill property panel. //! \return stream value or dummy diff --git a/tools/TreeModel/TreeModel_ModelBase.cxx b/tools/TreeModel/TreeModel_ModelBase.cxx index a87cbe662e..5dd4055b7e 100644 --- a/tools/TreeModel/TreeModel_ModelBase.cxx +++ b/tools/TreeModel/TreeModel_ModelBase.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -46,9 +47,9 @@ TreeModel_ModelBase::TreeModel_ModelBase (QObject* theParent) // ======================================================================= void TreeModel_ModelBase::InitColumns() { - SetHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); - SetHeaderItem (1, TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth())); - SetHeaderItem (2, TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH)); + setHeaderItem (TreeModel_ColumnType_Name, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + setHeaderItem (TreeModel_ColumnType_Visibility, TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth())); + setHeaderItem (TreeModel_ColumnType_Row, TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH)); } // ======================================================================= @@ -177,7 +178,7 @@ QVariant TreeModel_ModelBase::headerData (int theSection, Qt::Orientation theOri if (IsUseVisibilityColumn() && theSection == TreeModel_ColumnType_Visibility) return QVariant(); - return GetHeaderItem (theSection).GetName(); + return myHeaderValues[theSection].GetName(); } // ======================================================================= @@ -231,23 +232,6 @@ void TreeModel_ModelBase::EmitDataChanged (const QModelIndex& theTopLeft, const #endif } -// ======================================================================= -// function : SetHeaderItem -// purpose : -// ======================================================================= -void TreeModel_ModelBase::SetHeaderItem (const int theColumnId, const TreeModel_HeaderSection& theSection) -{ - if (theSection.IsEmpty()) - { - // remove section - myHeaderValues.remove (theColumnId); - myRootItems.remove (theColumnId); - } - - myHeaderValues[theColumnId] = theSection; - createRoot (theColumnId); -} - // ======================================================================= // function : Selected // purpose : @@ -295,6 +279,40 @@ QList TreeModel_ModelBase::SelectedItems (const QModelInd return anItems; } +// ======================================================================= +// function : SubItemsPresentations +// purpose : +// ======================================================================= +void TreeModel_ModelBase::SubItemsPresentations (const QModelIndexList& theIndices, + NCollection_List& thePresentations) +{ + QList anItems; + + for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++) + { + TreeModel_ItemBasePtr anItem = TreeModel_ModelBase::GetItemByIndex (*anIndicesIt); + if (!anItem || anItems.contains (anItem)) + continue; + subItemsPresentations (anItem, thePresentations); + } +} + +// ======================================================================= +// function : subItemPresentations +// purpose : +// ======================================================================= +void TreeModel_ModelBase::subItemsPresentations (const TreeModel_ItemBasePtr& theItem, + NCollection_List& thePresentations) +{ + theItem->Presentations (thePresentations); + + QList anItems; + for (int aRowId = 0; aRowId < theItem->rowCount(); aRowId++) + { + subItemsPresentations (theItem->Child (aRowId, theItem->Column()), thePresentations); + } +} + // ======================================================================= // function : createRoot // purpose : @@ -304,6 +322,23 @@ void TreeModel_ModelBase::createRoot (const int theColumnId) myRootItems.insert (theColumnId, createRootItem (theColumnId)); } +// ======================================================================= +// function : setHeaderItem +// purpose : +// ======================================================================= +void TreeModel_ModelBase::setHeaderItem (const int theColumnId, const TreeModel_HeaderSection& theSection) +{ + if (theSection.IsEmpty()) + { + // remove section + myHeaderValues.remove (theColumnId); + myRootItems.remove (theColumnId); + } + + myHeaderValues[theColumnId] = theSection; + createRoot (theColumnId); +} + // ======================================================================= // function : getIndexValue // purpose : diff --git a/tools/TreeModel/TreeModel_ModelBase.hxx b/tools/TreeModel/TreeModel_ModelBase.hxx index b8a31e903e..f616846496 100644 --- a/tools/TreeModel/TreeModel_ModelBase.hxx +++ b/tools/TreeModel/TreeModel_ModelBase.hxx @@ -141,12 +141,7 @@ public: //! Returns whether the column is hidden by default //! \param theColumnId a column index //! \return header section values container - TreeModel_HeaderSection GetHeaderItem (const int theColumnId) const { return myHeaderValues[theColumnId]; } - - //! Sets header properties item. - //! \param theColumnId a column index - //! \param theSection a section value - Standard_EXPORT void SetHeaderItem (const int theColumnId, const TreeModel_HeaderSection& theSection); + TreeModel_HeaderSection* ChangeHeaderItem (const int theColumnId) { return &myHeaderValues[theColumnId]; } //! Returns count of columns in the model //! \param theParent an index of the parent item @@ -180,16 +175,33 @@ public: //! \return model items from the list Standard_EXPORT static QList SelectedItems (const QModelIndexList& theIndices); + //! Returns presentations of sub items + //! \param theIndices a container of selected indices + //! \thePresentations [out] container of presentation handles to be visualized + Standard_EXPORT static void SubItemsPresentations (const QModelIndexList& theIndices, + NCollection_List& thePresentations); + protected: //! Creates root item //! \param theColumnId index of a column virtual TreeModel_ItemBasePtr createRootItem (const int theColumnId) = 0; + //! Sets header properties item. + //! \param theColumnId a column index + //! \param theSection a section value + Standard_EXPORT void setHeaderItem (const int theColumnId, const TreeModel_HeaderSection& theSection); + //! Converts the item shared pointer to void* type //! \param theItem //! \return an item pointer Standard_EXPORT static void* getIndexValue (const TreeModel_ItemBasePtr& theItem); + //! Returns presentations of sub items + //! \param theIndices a container of selected indices + //! \thePresentations [out] container of presentation handles to be visualized + static void subItemsPresentations (const TreeModel_ItemBasePtr& theItem, + NCollection_List& thePresentations); + private: //! Creates root item //! \param theColumnId index of a column diff --git a/tools/TreeModel/TreeModel_Tools.cxx b/tools/TreeModel/TreeModel_Tools.cxx index e3d8b2afa5..00bc92f59f 100644 --- a/tools/TreeModel/TreeModel_Tools.cxx +++ b/tools/TreeModel/TreeModel_Tools.cxx @@ -89,6 +89,7 @@ void TreeModel_Tools::SaveState (QTreeView* theTreeView, QMap& QStringList aColumnWidths, aHiddenColumns; for (int aColumnId = 0; aColumnId < theTreeView->model()->columnCount(); aColumnId++) { + int aWidth = theTreeView->columnWidth (aColumnId); if (theTreeView->isColumnHidden (aColumnId)) { aHiddenColumns.append (QString::number (aColumnId)); @@ -121,18 +122,18 @@ bool TreeModel_Tools::RestoreState (QTreeView* theTreeView, const QString& theKe } else if (theKey == thePrefix + "columns_hidden") { - int aColumnSize = theTreeView->model()->columnCount(); - QStringList aValues = theValue.split (",", QString::SkipEmptyParts); - QList aColumnIds; - for (int aValueId = 0; aValueId < aValues.size(); aValueId++) - { - if (aValueId < aColumnSize) - aColumnIds.append (aValues.at (aValueId).toInt()); - } - for (int aColumnId = 0; aColumnId < aColumnSize; aColumnId++) - { - theTreeView->setColumnHidden (aColumnId, aColumnIds.contains(aColumnId) == true); - } + //int aColumnSize = theTreeView->model()->columnCount(); + //QStringList aValues = theValue.split (",", QString::SkipEmptyParts); + //QList aColumnIds; + //for (int aValueId = 0; aValueId < aValues.size(); aValueId++) + //{ + // if (aValueId < aColumnSize) + // aColumnIds.append (aValues.at (aValueId).toInt()); + //} + //for (int aColumnId = 0; aColumnId < aColumnSize; aColumnId++) + //{ + // theTreeView->setColumnHidden (aColumnId, aColumnIds.contains(aColumnId) == true); + //} } else return false; @@ -149,9 +150,9 @@ void TreeModel_Tools::SetDefaultHeaderSections(QTreeView* theTreeView) for (int aColumnId = 0, aNbColumns = aTreeModel->columnCount(); aColumnId < aNbColumns; aColumnId++) { - TreeModel_HeaderSection aSection = aTreeModel->GetHeaderItem (aColumnId); - theTreeView->setColumnWidth (aColumnId, aSection.GetWidth()); - theTreeView->setColumnHidden (aColumnId, aSection.IsHidden()); + TreeModel_HeaderSection* aSection = aTreeModel->ChangeHeaderItem (aColumnId); + theTreeView->setColumnWidth (aColumnId, aSection->GetWidth()); + theTreeView->setColumnHidden (aColumnId, aSection->IsHidden()); } } @@ -170,8 +171,10 @@ void TreeModel_Tools::UseVisibilityColumn (QTreeView* theTreeView, const bool th aHeader->moveSection (TreeModel_ColumnType_Name, TreeModel_ColumnType_Visibility); TreeModel_ModelBase* aModel = dynamic_cast (theTreeView->model()); - aModel->SetHeaderItem (TreeModel_ColumnType_Visibility, - TreeModel_HeaderSection ("Visibility", TreeModel_ModelBase::ColumnVisibilityWidth())); + TreeModel_HeaderSection* anItem = aModel->ChangeHeaderItem ((int)TreeModel_ColumnType_Visibility); + anItem->SetIsHidden (theActive); + anItem->SetWidth (TreeModel_ModelBase::ColumnVisibilityWidth()); + aModel->SetUseVisibilityColumn (theActive); } diff --git a/tools/VInspector/VInspector_ItemBase.cxx b/tools/VInspector/VInspector_ItemBase.cxx index 591ecb0661..3ac0a4e022 100644 --- a/tools/VInspector/VInspector_ItemBase.cxx +++ b/tools/VInspector/VInspector_ItemBase.cxx @@ -43,7 +43,7 @@ QVariant VInspector_ItemBase::initValue (const int theItemRole) const case 3: return Standard_Dump::GetPointerInfo (Object(), true).ToCString(); } - return QVariant(); + return TreeModel_ItemBase::initValue (theItemRole); } // ======================================================================= diff --git a/tools/VInspector/VInspector_ItemBase.hxx b/tools/VInspector/VInspector_ItemBase.hxx index 4e35513625..cfe70758d8 100644 --- a/tools/VInspector/VInspector_ItemBase.hxx +++ b/tools/VInspector/VInspector_ItemBase.hxx @@ -51,11 +51,6 @@ public: //! \return the value Standard_EXPORT virtual QVariant initValue (const int theItemRole) const Standard_OVERRIDE; - //! Returns presentation of the attribute to be visualized in the view - //! \thePresentations [out] container of presentation handles to be visualized - virtual void Presentations (NCollection_List& thePresentations) - { (void)thePresentations; } - //! Returns transform persistent of the item or NULL Handle(Graphic3d_TransformPers) TransformPersistence() const { return myTransformPersistence; } diff --git a/tools/VInspector/VInspector_ItemPresentableObject.hxx b/tools/VInspector/VInspector_ItemPresentableObject.hxx index 28ea239953..31df492fc6 100644 --- a/tools/VInspector/VInspector_ItemPresentableObject.hxx +++ b/tools/VInspector/VInspector_ItemPresentableObject.hxx @@ -61,7 +61,7 @@ public: //! Returns presentation of the attribute to be visualized in the view //! \thePresentations [out] container of presentation handles to be visualized - Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations) Standard_OVERRIDE; protected: diff --git a/tools/VInspector/VInspector_ViewModel.cxx b/tools/VInspector/VInspector_ViewModel.cxx index 2ca792b334..894d0a3ba3 100644 --- a/tools/VInspector/VInspector_ViewModel.cxx +++ b/tools/VInspector/VInspector_ViewModel.cxx @@ -43,8 +43,8 @@ void VInspector_ViewModel::InitColumns() { TreeModel_ModelBase::InitColumns(); - SetHeaderItem (3, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); - SetHeaderItem (4, TreeModel_HeaderSection ("SelectedOwners", -1)); + setHeaderItem (3, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); + setHeaderItem (4, TreeModel_HeaderSection ("SelectedOwners", -1)); } // ======================================================================= diff --git a/tools/VInspector/VInspector_ViewModelHistory.cxx b/tools/VInspector/VInspector_ViewModelHistory.cxx index 980dc1e865..0b50eca7d8 100644 --- a/tools/VInspector/VInspector_ViewModelHistory.cxx +++ b/tools/VInspector/VInspector_ViewModelHistory.cxx @@ -54,13 +54,13 @@ void VInspector_ViewModelHistory::InitColumns() { TreeModel_ModelBase::InitColumns(); - SetHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); - SetHeaderItem (1, TreeModel_HeaderSection ("Visibility", COLUMN_SIZE_WIDTH)); // visualization item - SetHeaderItem (2, TreeModel_HeaderSection ("Size", COLUMN_SIZE_WIDTH)); - SetHeaderItem (3, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); - SetHeaderItem (4, TreeModel_HeaderSection ("Shape type", COLUMN_SHAPE_TYPE_WIDTH)); - SetHeaderItem (5, TreeModel_HeaderSection ("AIS Name", COLUMN_AIS_NAME_WIDTH)); - SetHeaderItem (6, TreeModel_HeaderSection ("Selected/Highlighted", -1)); + setHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + setHeaderItem (1, TreeModel_HeaderSection ("Visibility", COLUMN_SIZE_WIDTH)); // visualization item + setHeaderItem (2, TreeModel_HeaderSection ("Size", COLUMN_SIZE_WIDTH)); + setHeaderItem (3, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); + setHeaderItem (4, TreeModel_HeaderSection ("Shape type", COLUMN_SHAPE_TYPE_WIDTH)); + setHeaderItem (5, TreeModel_HeaderSection ("AIS Name", COLUMN_AIS_NAME_WIDTH)); + setHeaderItem (6, TreeModel_HeaderSection ("Selected/Highlighted", -1)); for (int aColumnId = 0, aNbColumns = columnCount(); aColumnId < aNbColumns; aColumnId++) { diff --git a/tools/VInspector/VInspector_Window.cxx b/tools/VInspector/VInspector_Window.cxx index 17fc850e6d..163df690dd 100644 --- a/tools/VInspector/VInspector_Window.cxx +++ b/tools/VInspector/VInspector_Window.cxx @@ -17,7 +17,6 @@ #include #include -#include #include @@ -49,7 +48,6 @@ #include #include #include -#include #include #include @@ -114,9 +112,8 @@ VInspector_Window::VInspector_Window() aTreeModel->InitColumns(); myTreeView->setModel (aTreeModel); // hide Visibility column - TreeModel_HeaderSection anItem = aTreeModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility); - anItem.SetIsHidden (true); - aTreeModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem); + TreeModel_HeaderSection* anItem = aTreeModel->ChangeHeaderItem ((int)TreeModel_ColumnType_Visibility); + anItem->SetIsHidden (true); connect (myTreeView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT (onTreeViewContextMenuRequested(const QPoint&))); @@ -159,12 +156,11 @@ VInspector_Window::VInspector_Window() connect (aSelectionModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (onHistoryViewSelectionChanged (const QItemSelection&, const QItemSelection&))); - anItem = aHistoryModel->GetHeaderItem (0); + anItem = aHistoryModel->ChangeHeaderItem (0); // hide Visibility column TreeModel_Tools::UseVisibilityColumn (myHistoryView, false); - anItem = aHistoryModel->GetHeaderItem ((int)TreeModel_ColumnType_Visibility); - anItem.SetIsHidden (true); - aHistoryModel->SetHeaderItem ((int)TreeModel_ColumnType_Visibility, anItem); + anItem = aHistoryModel->ChangeHeaderItem ((int)TreeModel_ColumnType_Visibility); + anItem->SetIsHidden (true); QModelIndex aParentIndex = myHistoryView->model()->index (0, 0); myHistoryView->setExpanded (aParentIndex, true); @@ -636,12 +632,12 @@ void VInspector_Window::onExportToShapeView() TCollection_AsciiString aPluginName ("TKShapeView"); NCollection_List aParameters; - if (myParameters->FindParameters (aPluginName)) - aParameters = myParameters->Parameters (aPluginName); + //if (myParameters->FindParameters (aPluginName)) + // aParameters = myParameters->Parameters (aPluginName); NCollection_List anItemNames; - if (myParameters->FindSelectedNames (aPluginName)) - anItemNames = myParameters->GetSelectedNames (aPluginName); + //if (myParameters->FindSelectedNames (aPluginName)) + // anItemNames = myParameters->GetSelectedNames (aPluginName); QStringList anExportedPointers; if (aSelectedShapes.Extent() > 0) @@ -661,23 +657,23 @@ void VInspector_Window::onExportToShapeView() } } - // search for objects to be exported - QList anItems = TreeModel_ModelBase::SelectedItems (myTreeView->selectionModel()->selectedIndexes()); - for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) - { - TreeModel_ItemBasePtr anItem = *anItemIt; - VInspector_ItemBasePtr aVItem = itemDynamicCast(anItem); - if (!aVItem) - continue; + //// search for objects to be exported + //QList anItems = TreeModel_ModelBase::SelectedItems (myTreeView->selectionModel()->selectedIndexes()); + //for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + //{ + // TreeModel_ItemBasePtr anItem = *anItemIt; + // VInspector_ItemBasePtr aVItem = itemDynamicCast(anItem); + // if (!aVItem) + // continue; - const Handle(Standard_Transient)& anObject = aVItem->Object(); - if (anObject.IsNull()) - continue; + // const Handle(Standard_Transient)& anObject = aVItem->Object(); + // if (anObject.IsNull()) + // continue; - aParameters.Append (anObject); - anItemNames.Append (anObject->DynamicType()->Name()); - anExportedPointers.append (Standard_Dump::GetPointerInfo (anObject, true).ToCString()); - } + // aParameters.Append (anObject); + // anItemNames.Append (anObject->DynamicType()->Name()); + // anExportedPointers.append (Standard_Dump::GetPointerInfo (anObject, true).ToCString()); + //} if (anExportedPointers.isEmpty()) return; @@ -894,7 +890,7 @@ Handle(AIS_InteractiveContext) VInspector_Window::createView() Handle(AIS_InteractiveContext) aContext = View_Viewer::CreateStandardViewer(); myViewWindow = new View_Window (0, aContext, false /*for opening several BREP files*/, true); - myViewWindow->SetPredefinedSize (VINSPECTOR_DEFAULT_VIEW_WIDTH, VINSPECTOR_DEFAULT_VIEW_HEIGHT); + myViewWindow->ViewWidget()->SetPredefinedSize (VINSPECTOR_DEFAULT_VIEW_WIDTH, VINSPECTOR_DEFAULT_VIEW_HEIGHT); myViewWindow->move (VINSPECTOR_DEFAULT_VIEW_POSITION_X, VINSPECTOR_DEFAULT_VIEW_POSITION_Y); myViewWindow->show(); diff --git a/tools/View/View.qrc b/tools/View/View.qrc index d403f34bb9..89d2f9a795 100644 --- a/tools/View/View.qrc +++ b/tools/View/View.qrc @@ -1,13 +1,18 @@ + icons/cursor_rotate.png + icons/cursor_zoom.png icons/keep_view_off.png icons/keep_view_on.png icons/trihedron.png icons/view_clear.png - icons/view_cube.png icons/view_dm_shading.png icons/view_dm_wireframe.png icons/view_fitall.png + icons/view_fitarea.png + icons/view_pan.png + icons/view_rotate.png + icons/view_zoom.png diff --git a/tools/View/View_Displayer.cxx b/tools/View/View_Displayer.cxx index 82592275d7..72c1c28ec7 100644 --- a/tools/View/View_Displayer.cxx +++ b/tools/View/View_Displayer.cxx @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -231,28 +230,6 @@ void View_Displayer::DisplayDefaultTrihedron (const Standard_Boolean toDisplay, GetContext()->Erase (aTrihedron, theToUpdateViewer); } -// ======================================================================= -// function : DisplayViewCube -// purpose : -// ======================================================================= -void View_Displayer::DisplayViewCube (const Standard_Boolean toDisplay, const bool theToUpdateViewer) -{ - if (myViewCube.IsNull() && toDisplay) - { - myViewCube = new AIS_ViewCube(); - myViewCube->SetSize (35.0); - myViewCube->SetBoxColor (Quantity_NOC_GRAY50); - } - - if (myViewCube.IsNull()) - return; - - if (toDisplay) - GetContext()->Display (myViewCube, theToUpdateViewer); - else - GetContext()->Erase (myViewCube, theToUpdateViewer); -} - // ======================================================================= // function : SetVisible // purpose : diff --git a/tools/View/View_Displayer.hxx b/tools/View/View_Displayer.hxx index 3ba29968d8..da1f029a46 100644 --- a/tools/View/View_Displayer.hxx +++ b/tools/View/View_Displayer.hxx @@ -28,7 +28,6 @@ #include class AIS_Trihedron; -class AIS_ViewCube; class V3d_View; class View_DisplayPreview; @@ -122,11 +121,6 @@ public: //! \param isToUpdateView boolean state if viewer should be updated Standard_EXPORT void DisplayDefaultTrihedron (const Standard_Boolean toDisplay, const bool theToUpdateViewer); - //! Displays presentation of view cube, create it by the first call - //! \param toDisplay flag to display presentation if true, or erase it - //! \param isToUpdateView boolean state if viewer should be updated - Standard_EXPORT void DisplayViewCube (const Standard_Boolean toDisplay, const bool theToUpdateViewer); - //! Sets shape visible/invisible //! \theShape shape instance //! \theState visibility state @@ -192,8 +186,7 @@ private: View_DisplayPreview* myDisplayPreview; //!< class for preview display Handle(AIS_InteractiveContext) myContext; //!< context, where the displayer works - Handle(AIS_Trihedron) myDefaultTrihedron; //!< trihedron presentation for the current context - Handle(AIS_ViewCube) myViewCube; //!< view cube presentation for current context + Handle(AIS_Trihedron) myDefaultTrihedron; //!< NULL presentation until the first display NCollection_DataMap> myDisplayed; //!< visualized presentations NCollection_DataMap myColorAttributes; //!< color properties of presentations diff --git a/tools/View/View_ToolActionType.hxx b/tools/View/View_ToolActionType.hxx index b2b0d0d4cb..a518d2ba54 100644 --- a/tools/View/View_ToolActionType.hxx +++ b/tools/View/View_ToolActionType.hxx @@ -22,8 +22,7 @@ enum View_ToolActionType View_ToolActionType_KeepViewId, //!< Do not clear previously shown presentations View_ToolActionType_KeepViewOffId, //!< Do show only for new displayed presentation View_ToolActionType_ClearViewId, //!< Erase all displayed presentations - View_ToolActionType_Trihedron, //!< Display/Erase trihedron presentation - View_ToolActionType_ViewCube //!< Display/Erase view cube presentation + View_ToolActionType_Trihedron //!< Display/Erase trihedron presentation }; #endif diff --git a/tools/View/View_ToolBar.cxx b/tools/View/View_ToolBar.cxx index e23b402ee3..7887ebbed6 100644 --- a/tools/View/View_ToolBar.cxx +++ b/tools/View/View_ToolBar.cxx @@ -69,13 +69,6 @@ View_ToolBar::View_ToolBar (QWidget* theParent, const bool isUseKeepView) myActionsMap[View_ToolActionType_Trihedron]->setCheckable (true); myActionsMap[View_ToolActionType_Trihedron]->setChecked (false); - myActionsMap[View_ToolActionType_ViewCube] = new QToolButton (theParent); - myActionsMap[View_ToolActionType_ViewCube]->setIcon (QIcon (":/icons/view_cube.png")); - myActionsMap[View_ToolActionType_ViewCube]->setToolTip (tr ("View Cube display")); - myActionsMap[View_ToolActionType_ViewCube]->setCheckable (true); - myActionsMap[View_ToolActionType_ViewCube]->setChecked (false); - - if (isUseKeepView) { myActionsMap[View_ToolActionType_KeepViewId] = new QToolButton (theParent); diff --git a/tools/View/View_ViewActionType.hxx b/tools/View/View_ViewActionType.hxx index d970c3554d..1f3288fa5f 100644 --- a/tools/View/View_ViewActionType.hxx +++ b/tools/View/View_ViewActionType.hxx @@ -19,7 +19,11 @@ //! Actions of view widget enum View_ViewActionType { - View_ViewActionType_FitAllId, //!< fits the view to wrap the bounding box of displayed objects + View_ViewActionType_FitAllId, //!< fits the view to wrap the bounding box of displayed objects + View_ViewActionType_FitAreaId, //!< zoom the view to the given area + View_ViewActionType_ZoomId, //!< zoom in/out the view by some delta + View_ViewActionType_PanId, //!< move position of the view camera + View_ViewActionType_RotationId, //!< rotate the view View_ViewActionType_DisplayModeId //!< change display mode of visualized presentations (to wireframe or shading) }; diff --git a/tools/View/View_Widget.cxx b/tools/View/View_Widget.cxx index e0c88e05a7..878b19f708 100644 --- a/tools/View/View_Widget.cxx +++ b/tools/View/View_Widget.cxx @@ -19,7 +19,6 @@ #include -#include #include #include @@ -51,6 +50,13 @@ #include #endif +// the key for multi selection : +#define MULTISELECTIONKEY Qt::ShiftModifier +// the key for shortcut (use to activate dynamic onRotate, panning) +#define CASCADESHORTCUTKEY Qt::ControlModifier +// for elastic bean selection +#define ValZWMin 1 + // ======================================================================= // function : Constructor // purpose : @@ -58,20 +64,18 @@ View_Widget::View_Widget (QWidget* theParent, const Handle(AIS_InteractiveContext)& theContext, const bool isFitAllActive) -: QWidget (theParent), myFirst (true), myDefaultWidth (-1), - myDefaultHeight (-1), myViewIsEnabled (true), +: QWidget (theParent), myCurrentMode (View_CurrentAction3d_Nothing), myFirst (true), myDefaultWidth (-1), + myDefaultHeight (-1), myViewIsEnabled (true), myXmin (0), myYmin (0), myXmax (0), myYmax (0), myDragButtonDownX (0), + myDragButtonDownY (0), myDragMultiButtonDownX (0), myDragMultiButtonDownY (0), myIsRectVisible (false), myRectBand (0), myHasInitProj (Standard_False), myInitVx (0), myInitVy (0), myInitVz (0) { myViewer = new View_Viewer (View_Viewer::DefaultColor()); if (!theContext.IsNull()) - { myViewer->InitViewer (theContext); - } else { myViewer->InitViewer (myViewer->CreateStandardViewer()); } - myController = new AIS_ViewController(); setAttribute (Qt::WA_PaintOnScreen); setAttribute (Qt::WA_NoSystemBackground); @@ -83,6 +87,7 @@ View_Widget::View_Widget (QWidget* theParent, initViewActions(); ((View_ToolButton*)myFitAllAction)->SetButtonChecked (isFitAllActive); + initCursors(); } // ======================================================================= @@ -199,7 +204,8 @@ void View_Widget::SetEnabledView (const bool theIsEnabled) if (myViewer->GetView()) myViewer->GetView()->SetBackgroundColor (theIsEnabled ? View_Viewer::DefaultColor() : View_Viewer::DisabledColor()); - ViewAction (View_ViewActionType_DisplayModeId)->setEnabled (theIsEnabled); + for (int anActionId = View_ViewActionType_FitAreaId; anActionId <= View_ViewActionType_DisplayModeId; anActionId++) + ViewAction ((View_ViewActionType)anActionId)->setEnabled (theIsEnabled); } // ======================================================================= @@ -248,6 +254,53 @@ void View_Widget::onCheckedStateChanged (bool isOn) emit checkedStateChanged(View_ViewActionType_FitAllId, isOn); } +// ======================================================================= +// function : OnUpdateToggled +// purpose : +// ======================================================================= +void View_Widget::OnUpdateToggled (bool isOn) +{ + QAction* aSentByAction = (QAction*)sender(); + + if (aSentByAction == myViewActions[View_ViewActionType_DisplayModeId]) + { + aSentByAction->setIcon (isOn ? QIcon (":/icons/view_dm_wireframe.png") + : QIcon (":/icons/view_dm_shading.png")); + return; + } + + if (!isOn) + return; + + for (int anActionId = View_ViewActionType_FitAreaId; anActionId <= View_ViewActionType_RotationId; anActionId++) + { + QAction* anAction = myViewActions[(View_ViewActionType)anActionId]; + if ((anAction == myViewActions[View_ViewActionType_FitAreaId]) || + (anAction == myViewActions[View_ViewActionType_ZoomId]) || + (anAction == myViewActions[View_ViewActionType_PanId]) || + (anAction == myViewActions[View_ViewActionType_RotationId])) + { + if (anAction && (anAction != aSentByAction)) + { + anAction->setChecked (false); + } + else + { + if (aSentByAction == myViewActions[View_ViewActionType_FitAreaId]) + setActiveCursor (View_CursorMode_HandCursor); + else if (aSentByAction == myViewActions[View_ViewActionType_ZoomId]) + setActiveCursor (View_CursorMode_ZoomCursor); + else if (aSentByAction == myViewActions[View_ViewActionType_PanId]) + setActiveCursor (View_CursorMode_PanCursor); + else if (aSentByAction == myViewActions[View_ViewActionType_RotationId]) + setActiveCursor (View_CursorMode_RotationCursor); + else + setActiveCursor (View_CursorMode_DefaultCursor); + } + } + } +} + // ======================================================================= // function : initViewActions // purpose : @@ -262,8 +315,31 @@ void View_Widget::initViewActions() createAction (View_ViewActionType_FitAllId, ":/icons/view_fitall.png", tr ("Fit All"), SLOT (OnFitAll())); myFitAllAction->setDefaultAction (ViewAction (View_ViewActionType_FitAllId)); + createAction (View_ViewActionType_FitAreaId, ":/icons/view_fitarea.png", tr ("Fit Area"), SLOT (OnFitArea()), true); + createAction (View_ViewActionType_ZoomId, ":/icons/view_zoom.png", tr ("Zoom"), SLOT (OnZoom()), true); + createAction (View_ViewActionType_PanId, ":/icons/view_pan.png", tr ("Pan"), SLOT (OnPan()), true); + createAction (View_ViewActionType_RotationId, ":/icons/view_rotate.png", tr ("Rotation"), SLOT (OnRotate()), true); createAction (View_ViewActionType_DisplayModeId, ":/icons/view_dm_shading.png", tr ("Display Mode"), SIGNAL (displayModeClicked()), true); + + for (int anActionId = View_ViewActionType_FitAreaId; anActionId <= View_ViewActionType_RotationId; anActionId++) + connect (myViewActions[(View_ViewActionType)anActionId], SIGNAL (toggled(bool)), this, SLOT (OnUpdateToggled(bool))); +} + +// ======================================================================= +// function : initCursors +// purpose : +// ======================================================================= +void View_Widget::initCursors() +{ + if (!myCursors.empty()) + return; + + myCursors[View_CursorMode_DefaultCursor] = QCursor (Qt::ArrowCursor); + myCursors[View_CursorMode_HandCursor] = QCursor (Qt::PointingHandCursor); + myCursors[View_CursorMode_PanCursor] = QCursor (Qt::SizeAllCursor); + myCursors[View_CursorMode_ZoomCursor] = QCursor(QIcon (":/icons/cursor_zoom.png").pixmap (20, 20)); + myCursors[View_CursorMode_RotationCursor] = QCursor(QIcon (":/icons/cursor_rotate.png").pixmap (20, 20)); } // ======================================================================= @@ -272,13 +348,12 @@ void View_Widget::initViewActions() // ======================================================================= void View_Widget::mousePressEvent (QMouseEvent* theEvent) { - if (myController->PressMouseButton (Graphic3d_Vec2i (theEvent->x(), theEvent->y()), - keyMouse (theEvent->button()), - keyFlag (theEvent->modifiers()), - Standard_False)) - { - myController->FlushViewEvents (myViewer->GetContext(), myViewer->GetView(), Standard_True); - } + if (theEvent->button() == Qt::LeftButton) + processLeftButtonDown (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); + else if (theEvent->button() == Qt::MidButton) + processMiddleButtonDown (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); + else if (theEvent->button() == Qt::RightButton) + processRightButtonDown (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); } // ======================================================================= @@ -287,13 +362,12 @@ void View_Widget::mousePressEvent (QMouseEvent* theEvent) // ======================================================================= void View_Widget::mouseReleaseEvent (QMouseEvent* theEvent) { - if (myController->ReleaseMouseButton (Graphic3d_Vec2i (theEvent->x(), theEvent->y()), - keyMouse (theEvent->button()), - keyFlag (theEvent->modifiers()), - Standard_False)) - { - myController->FlushViewEvents (myViewer->GetContext(), myViewer->GetView(), Standard_True); - } + if (theEvent->button() == Qt::LeftButton) + processLeftButtonUp (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); + else if (theEvent->button() == Qt::MidButton) + processMiddleButtonUp (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); + else if (theEvent->button() == Qt::RightButton) + processRightButtonUp (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); } // ======================================================================= @@ -302,11 +376,411 @@ void View_Widget::mouseReleaseEvent (QMouseEvent* theEvent) // ======================================================================= void View_Widget::mouseMoveEvent (QMouseEvent* theEvent) { - myController->UpdateMousePosition (Graphic3d_Vec2i (theEvent->x(), theEvent->y()), - keyMouse (theEvent->button()), - keyFlag (theEvent->modifiers()), Standard_False); + processMouseMove (theEvent->buttons() | theEvent->modifiers(), theEvent->pos()); +} + +// ======================================================================= +// function : activateCursor +// purpose : +// ======================================================================= +void View_Widget::activateCursor (const View_CurrentAction3d theMode) +{ + switch (theMode) + { + case View_CurrentAction3d_DynamicPanning: + { + setActiveCursor (View_CursorMode_PanCursor); + break; + } + case View_CurrentAction3d_DynamicZooming: + { + setActiveCursor (View_CursorMode_ZoomCursor); + break; + } + case View_CurrentAction3d_DynamicRotation: + { + setActiveCursor (View_CursorMode_RotationCursor); + break; + } + case View_CurrentAction3d_WindowZooming: + { + setActiveCursor (View_CursorMode_HandCursor); + break; + } + case View_CurrentAction3d_Nothing: + default: + { + setActiveCursor (View_CursorMode_DefaultCursor); + break; + } + } +} + +// ======================================================================= +// function : processLeftButtonDown +// purpose : +// ======================================================================= +void View_Widget::processLeftButtonDown (const int theFlags, const QPoint thePoint) +{ + // save the current mouse coordinate in min + myXmin = thePoint.x(); + myYmin = thePoint.y(); + myXmax = thePoint.x(); + myYmax = thePoint.y(); + + if (theFlags & CASCADESHORTCUTKEY) + { + myCurrentMode = View_CurrentAction3d_DynamicZooming; + OnUpdateToggled(true); + } + else + { + switch (myCurrentMode) + { + case View_CurrentAction3d_Nothing: + { + if (theFlags & MULTISELECTIONKEY) + processDragMultiEvent (myXmax, myYmax, View_DragMode_ButtonDown); + else + processDragEvent (myXmax, myYmax, View_DragMode_ButtonDown); + break; + } + case View_CurrentAction3d_DynamicZooming: + case View_CurrentAction3d_WindowZooming: + case View_CurrentAction3d_DynamicPanning: + break; + case View_CurrentAction3d_DynamicRotation: + { + myViewer->GetView()->StartRotation (thePoint.x(), thePoint.y()); + break; + } + default: + { + throw Standard_ProgramError ("View_Widget::processLeftButtonDown : Incompatible Current Mode"); + break; + } + } + } + activateCursor (myCurrentMode); + emit leftButtonDown(thePoint.x(), thePoint.y()); +} + +// ======================================================================= +// function : processMiddleButtonDown +// purpose : +// ======================================================================= +void View_Widget::processMiddleButtonDown (const int theFlags, const QPoint /*thePoint*/) +{ + if (theFlags & CASCADESHORTCUTKEY) { + myCurrentMode = View_CurrentAction3d_DynamicPanning; + OnUpdateToggled(true); + } + activateCursor (myCurrentMode); +} + +// ======================================================================= +// function : processRightButtonDown +// purpose : +// ======================================================================= +void View_Widget::processRightButtonDown (const int theFlags, const QPoint thePoint) +{ + if (theFlags & CASCADESHORTCUTKEY) + { + myCurrentMode = View_CurrentAction3d_DynamicRotation; + myViewer->GetView()->StartRotation (thePoint.x(), thePoint.y()); + OnUpdateToggled(true); + } + else + { + popup (thePoint.x(), thePoint.y()); + } + activateCursor (myCurrentMode); +} + +// ======================================================================= +// function : processLeftButtonUp +// purpose : +// ======================================================================= +void View_Widget::processLeftButtonUp (const int theFlags, const QPoint thePoint) +{ + switch (myCurrentMode) + { + case View_CurrentAction3d_Nothing: + { + if (thePoint.x() == myXmin && thePoint.y() == myYmin) + { + // no offset between down and up --> selectEvent + myXmax = thePoint.x(); + myYmax = thePoint.y(); + if (theFlags & MULTISELECTIONKEY) + processInputMultiEvent (thePoint.x(), thePoint.y()); + else + processInputEvent (thePoint.x(), thePoint.y()); + } + else + { + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_False); + myXmax = thePoint.x(); + myYmax = thePoint.y(); + if (theFlags & MULTISELECTIONKEY) + processDragMultiEvent (thePoint.x(), thePoint.y(), View_DragMode_ButtonUp); + else + processDragEvent (thePoint.x(), thePoint.y(), View_DragMode_ButtonUp); + } + break; + } + case View_CurrentAction3d_DynamicZooming: + break; + case View_CurrentAction3d_WindowZooming: + { + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_False); + myXmax = thePoint.x(); + myYmax = thePoint.y(); + if ((abs(myXmin - myXmax) > ValZWMin) || + (abs(myYmin - myYmax) > ValZWMin)) + myViewer->GetView()->WindowFitAll (myXmin, myYmin, myXmax, myYmax); + break; + } + case View_CurrentAction3d_DynamicPanning: + break; + case View_CurrentAction3d_DynamicRotation: + break; + default: + { + throw Standard_ProgramError("View_Widget::processLeftButtonUp : Incompatible Current Mode"); + break; + } + } + myDragButtonDownX = 0; + myDragButtonDownY = 0; + myDragMultiButtonDownX = 0; + myDragMultiButtonDownY = 0; + + emit selectionChanged(); + emit leftButtonUp(thePoint.x(), thePoint.y()); +} + +// ======================================================================= +// function : processMiddleButtonUp +// purpose : +// ======================================================================= +void View_Widget::processMiddleButtonUp (const int /*theFlags*/, const QPoint /*thePoint*/) +{ + myCurrentMode = View_CurrentAction3d_Nothing; + activateCursor (myCurrentMode); +} + +// ======================================================================= +// function : processRightButtonUp +// purpose : +// ======================================================================= +void View_Widget::processRightButtonUp (const int /*theFlags*/, const QPoint thePoint) +{ + if (myCurrentMode == View_CurrentAction3d_Nothing) + { + popup (thePoint.x(), thePoint.y()); + } + else + myCurrentMode = View_CurrentAction3d_Nothing; + activateCursor (myCurrentMode); +} + +// ======================================================================= +// function : processMouseMove +// purpose : +// ======================================================================= +void View_Widget::processMouseMove (const int theFlags, const QPoint thePoint) +{ + if (theFlags & Qt::LeftButton || theFlags & Qt::RightButton || theFlags & Qt::MidButton) + { + switch (myCurrentMode) + { + case View_CurrentAction3d_Nothing: + { + myXmax = thePoint.x(); + myYmax = thePoint.y(); + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_False); + if (theFlags & MULTISELECTIONKEY) + processDragMultiEvent (myXmax, myYmax, View_DragMode_ButtonMove); + else + processDragEvent (myXmax, myYmax, View_DragMode_ButtonMove); + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_True); + break; + } + case View_CurrentAction3d_DynamicZooming: + { + myViewer->GetView()->Zoom (myXmax, myYmax, thePoint.x(), thePoint.y()); + myXmax = thePoint.x(); + myYmax = thePoint.y(); + break; + } + case View_CurrentAction3d_WindowZooming: + { + myXmax = thePoint.x(); + myYmax = thePoint.y(); + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_False); + drawRectangle (myXmin, myYmin, myXmax, myYmax, Standard_True); + break; + } + case View_CurrentAction3d_DynamicPanning: + { + myViewer->GetView()->Pan (thePoint.x() - myXmax, myYmax - thePoint.y()); + myXmax = thePoint.x(); + myYmax = thePoint.y(); + break; + } + case View_CurrentAction3d_DynamicRotation: + { + myViewer->GetView()->Rotation (thePoint.x(), thePoint.y()); + myViewer->GetView()->Redraw(); + break; + } + default: + { + throw Standard_ProgramError("View_Widget::processMouseMove : Incompatible Current Mode"); + break; + } + } + } + else + { + myXmax = thePoint.x(); + myYmax = thePoint.y(); + if (theFlags & MULTISELECTIONKEY) + processMoveMultiEvent (thePoint.x(), thePoint.y()); + else + processMoveEvent (thePoint.x(), thePoint.y()); + } + emit moveTo (thePoint.x(), thePoint.y()); +} + +// ======================================================================= +// function : processDragEvent +// purpose : +// ======================================================================= +void View_Widget::processDragEvent (const Standard_Integer theX, const Standard_Integer theY, const View_DragMode& theState) +{ + //myDragButtonDownX = 0; + //myDragButtonDownY = 0; - myController->FlushViewEvents (myViewer->GetContext(), myViewer->GetView(), Standard_True); + switch (theState) + { + case View_DragMode_ButtonDown: + { + myDragButtonDownX = theX; + myDragButtonDownY = theY; + break; + } + case View_DragMode_ButtonMove: + break; + case View_DragMode_ButtonUp: + { + myViewer->GetContext()->Select (myDragButtonDownX, myDragButtonDownY, theX, theY, myViewer->GetView(), Standard_True); + emit selectionChanged(); + break; + } + default: + break; + } +} + +// ======================================================================= +// function : processInputEvent +// purpose : +// ======================================================================= +void View_Widget::processInputEvent (const Standard_Integer/* theX*/, const Standard_Integer/* theY*/) +{ + myViewer->GetContext()->Select (Standard_True); + emit selectionChanged(); +} + +// ======================================================================= +// function : processMoveEvent +// purpose : +// ======================================================================= +void View_Widget::processMoveEvent (const Standard_Integer theX, const Standard_Integer theY) +{ + if (myViewer->GetView()) + myViewer->GetContext()->MoveTo (theX, theY, myViewer->GetView(), Standard_True); +} + +// ======================================================================= +// function : processDragMultiEvent +// purpose : +// ======================================================================= +void View_Widget::processDragMultiEvent (const Standard_Integer theX, const Standard_Integer theY, + const View_DragMode& theState) +{ + switch (theState) + { + case View_DragMode_ButtonDown: + { + myDragMultiButtonDownX = theX; + myDragMultiButtonDownY = theY; + break; + } + case View_DragMode_ButtonMove: + { + myViewer->GetContext()->ShiftSelect (myDragMultiButtonDownX, myDragMultiButtonDownY, theX, theY, + myViewer->GetView(), Standard_True); + emit selectionChanged(); + break; + } + case View_DragMode_ButtonUp: + default: + break; + } +} + +// ======================================================================= +// function : processInputMultiEvent +// purpose : +// ======================================================================= +void View_Widget::processInputMultiEvent (const Standard_Integer /*theX*/, const Standard_Integer /*theY*/) +{ + myViewer->GetContext()->ShiftSelect (Standard_True); + emit selectionChanged(); +} + +// ======================================================================= +// function : drawRectangle +// purpose : +// ======================================================================= +void View_Widget::drawRectangle (const Standard_Integer theMinX, const Standard_Integer MinY, + const Standard_Integer MaxX, const Standard_Integer MaxY, + const Standard_Boolean theToDraw) +{ + Standard_Integer StoredMinX, StoredMaxX, StoredMinY, StoredMaxY; + + StoredMinX = (theMinX < MaxX) ? theMinX : MaxX; + StoredMinY = (MinY < MaxY) ? MinY : MaxY; + StoredMaxX = (theMinX > MaxX) ? theMinX : MaxX; + StoredMaxY = (MinY > MaxY) ? MinY : MaxY; + + QRect aRect; + aRect.setRect(StoredMinX, StoredMinY, abs (StoredMaxX-StoredMinX), abs (StoredMaxY-StoredMinY)); + + if (!myRectBand) + { + myRectBand = new QRubberBand (QRubberBand::Rectangle, this); + myRectBand->setStyle (QStyleFactory::create ("windows")); + myRectBand->setGeometry (aRect); + myRectBand->show(); + } + + if (myIsRectVisible && !theToDraw) // move or up : erase at the old position + { + myRectBand->hide(); + delete myRectBand; + myRectBand = 0; + myIsRectVisible = false; + } + + if (theToDraw) // move : draw + { + myIsRectVisible = true; + myRectBand->setGeometry (aRect); + } } // ======================================================================= @@ -327,34 +801,11 @@ void View_Widget::createAction (const View_ViewActionType theActionId, const QSt } // ======================================================================= -// function : keyFlag +// function : setActiveCursor // purpose : // ======================================================================= -Aspect_VKeyFlags View_Widget::keyFlag (const int theModifierId) +void View_Widget::setActiveCursor (const View_CursorMode& theMode) { - switch (theModifierId) - { - case Qt::NoModifier: return Aspect_VKeyFlags_NONE; - case Qt::ShiftModifier: return Aspect_VKeyFlags_SHIFT; - case Qt::ControlModifier: return Aspect_VKeyFlags_CTRL; - default: break; - } - return Aspect_VKeyFlags_NONE; -} - -// ======================================================================= -// function : keyMouse -// purpose : -// ======================================================================= -Aspect_VKeyMouse View_Widget::keyMouse (const int theButtonId) -{ - switch (theButtonId) - { - case Qt::NoButton: return Aspect_VKeyMouse_NONE; - case Qt::LeftButton: return Aspect_VKeyMouse_LeftButton; - case Qt::RightButton: return Aspect_VKeyMouse_RightButton; - case Qt::MidButton: return Aspect_VKeyMouse_MiddleButton; - default: break; - } - return Aspect_VKeyMouse_NONE; + QCursor aCursor = myCursors[theMode]; + setCursor (myCursors[theMode]); } diff --git a/tools/View/View_Widget.hxx b/tools/View/View_Widget.hxx index b882f32619..3fd7fdb069 100644 --- a/tools/View/View_Widget.hxx +++ b/tools/View/View_Widget.hxx @@ -17,8 +17,6 @@ #define View_View_H #include -#include -#include #include #include #include @@ -33,6 +31,8 @@ class View_Viewer; +class QRubberBand; + //! \class View_Widget //! \brief It is a Qt control that visualizes content of OCCT 3D view //! It creates control and actions of manipulating of this view, @@ -41,8 +41,38 @@ class View_Viewer; class View_Widget : public QWidget { Q_OBJECT +protected: + + //! Enumeration defines manipulating actions of the widget + enum View_CurrentAction3d + { + View_CurrentAction3d_Nothing, //!< Empty action + View_CurrentAction3d_DynamicZooming, //!< Zoom action + View_CurrentAction3d_WindowZooming, //!< Zoom action using rectangle + View_CurrentAction3d_DynamicPanning, //!< Panning action + View_CurrentAction3d_DynamicRotation //!< Rotation action + }; + + //! Enumeration defines cursor kind + enum View_CursorMode + { + View_CursorMode_DefaultCursor, //!< default Qt cursor + View_CursorMode_HandCursor, //!< hand cursor + View_CursorMode_PanCursor, //!< panning cursor + View_CursorMode_ZoomCursor, //!< zoom cursor + View_CursorMode_RotationCursor //!< onRotate cursor + }; + + //! Enumeration defines drag mode + enum View_DragMode + { + View_DragMode_ButtonDown, //!< theState == -1 button down + View_DragMode_ButtonMove, //!< theState == 0 move + View_DragMode_ButtonUp //< theState == 1 button up + }; public: + //! Constructor Standard_EXPORT View_Widget (QWidget* theParent, const Handle(AIS_InteractiveContext)& theContext, @@ -124,6 +154,21 @@ signals: //! Sends a signal about selection change if the left mouse button is pressed and current action does not process it void selectionChanged(); + //! Sends a signal about moving to the point in the view + //! \param theX X mouse position in pixels + //! \param theY Y mouse position in pixels + void moveTo (const int theX, const int theY); + + //! Sends a signal about up the left mouse button down + //! \param theX X mouse position in pixels + //! \param theY Y mouse position in pixels + void leftButtonDown (const int theX, const int theY); + + //! Sends a signal about up the left mouse button up + //! \param theX X mouse position in pixels + //! \param theY Y mouse position in pixels + void leftButtonUp (const int theX, const int theY); + //! Sends a signal about display mode change void displayModeClicked(); @@ -137,11 +182,29 @@ public slots: //! Fits all the V3d view and redraw view void OnFitAll() { myViewer->GetView()->FitAll(); } + //! Stores state about fitting all to use it by the mouse move + void OnFitArea() { myCurrentMode = View_CurrentAction3d_WindowZooming; } + + //! Stores state about zoom to use it by the mouse move + void OnZoom() { myCurrentMode = View_CurrentAction3d_DynamicZooming; } + + //! Stores state about pan to use it by the mouse move + void OnPan() { myCurrentMode = View_CurrentAction3d_DynamicPanning; } + + //! Stores state about onRotate to use it by the mouse move + void OnRotate() { myCurrentMode = View_CurrentAction3d_DynamicRotation; } + //! Updates states of widget actions //! //! - if the state is checked, uncheck all other actions Standard_EXPORT void onCheckedStateChanged (bool isOn); + //! Updates states of tool actions: + //! - if the action is display mode, it changes an icon for action(wireframe or shading) + //! - if the state is checked, uncheck all other actions + //! \param isOn boolean value about check + Standard_EXPORT void OnUpdateToggled (bool isOn); + protected: //! Avoids Qt standard execution of this method, redraw V3d view @@ -169,11 +232,99 @@ protected: //! Creates view actions and fills an internal map void initViewActions(); + //! Creates cursors and fills an internal map + void initCursors(); + + //! Sets widget cursor by the action type + //! \param theMode an active action mode + void activateCursor (const View_CurrentAction3d theMode); + + //! Activates cursor of the active operation, perform drag, onRotate depending on mode, + //! stores the point position in xmin/xmax and ymin/ymax + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processLeftButtonDown (const int theFlags, const QPoint thePoint); + + //! Activates cursor of the active operation and performs dynamic pan if it is active + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processMiddleButtonDown (const int theFlags, const QPoint thePoint); + + //! Activates cursor of the active operation, build popup menu + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processRightButtonDown (const int theFlags, const QPoint thePoint); + + //! Performs the active operation or performs Input/Drag event processing, emits selection changed signal + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processLeftButtonUp (const int theFlags, const QPoint thePoint); + + //! Changes the active operation to None + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processMiddleButtonUp (const int theFlags, const QPoint thePoint); + + //! Calls popup menu build and changes the active operation to None + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processRightButtonUp (const int theFlags, const QPoint thePoint); + + //! Performs active operation or draws rectangle of zoom + //! \param theFlags an event buttons and modifiers + //! \param thePoint a clicked point + void processMouseMove (const int theFlags, const QPoint thePoint); + + //! Performs selection: store clicked point by botton down, call Select by button up + //! Emits signal about selection changed + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + //! \param theState a mouse button state: down, move or up + void processDragEvent (const Standard_Integer theX, const Standard_Integer theY, const View_DragMode& theState); + + //! Performs selection in context without parameter, it means the selection of picked object + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + void processInputEvent (const Standard_Integer theX, const Standard_Integer theY); + + //! Calls MoveTo of the context for the parameter coordinates + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + void processMoveEvent (const Standard_Integer theX, const Standard_Integer theY); + + //! Empty: template to process mouse move with multi selection key pressed + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + void processMoveMultiEvent (const Standard_Integer theX, const Standard_Integer theY) + { (void)theX; (void)theY; } + + //! Performs selection: store clicked point by botton down, call ShiftSelect by button move + //! Emits signal about selection changed + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + //! \param theState a mouse button state: down, move or up + void processDragMultiEvent (const Standard_Integer theX, const Standard_Integer theY, const View_DragMode& theState); + + //! Performs shift selection in context without parameter, it means the selection of picked object + //! \param theX a horizontal position of mouse event + //! \param theX a vertical position of mouse event + void processInputMultiEvent (const Standard_Integer theX, const Standard_Integer theY); + //! Empty: template to create popup menu //! \param theX a horizontal position of mouse event //! \param theX a vertical position of mouse event void popup (const Standard_Integer theX, const Standard_Integer theY) { (void)theX; (void)theY; } + //! Draws Qt rectangle for the given area (e.g. for panning operation) + //! \param theMinX a minimal X coordinate + //! \param theMinY a minimal Y coordinate + //! \param theMinZ a minimal Z coordinate + //! \param theMaxX a maximum X coordinate + //! \param theMaxY a maximum Y coordinate + //! \param theMaxZ a maximum Z coordinate + //! \param theToDraw state whether the rectangle should be visualized or hidden + void drawRectangle (const Standard_Integer theMinX, const Standard_Integer theMinY, const Standard_Integer theMaxX, + const Standard_Integer theMaxY, const Standard_Boolean theToDraw); private: //! Creates action and stores it in a map of actions //! \param theActionId an identifier of action in internal map @@ -185,32 +336,38 @@ private: const char* theSlot, const bool isCheckable = false, const QString& theToolBar = QString(), const QString& theStatusBar = QString()); -private: - //! Converts Qt modifier key to Aspect key flag - //! \param theModifierId the event modifier - static Aspect_VKeyFlags keyFlag (const int theModifierId); - - //! Converts Qt button key to Aspect key mouse - //! \param theButtonId the event button - static Aspect_VKeyMouse keyMouse (const int theButtonId); + //! Sets active action cursor for application + //! \param theMode a cursor mode + void setActiveCursor (const View_CursorMode& theMode); private: View_Viewer* myViewer; //!< connector to context, V3d viewer and V3d View - AIS_ViewController* myController; //!< controller to process view actions - QToolButton* myFitAllAction; //!< widget for fit all, processed double click to perform action automatically QMap myViewActions; //!< tool bar view actions + QMap myCursors; //!< possible cursors for view actions + View_CurrentAction3d myCurrentMode; //!< an active action mode for viewer Standard_Boolean myFirst; //!< flag to Init view by the first resize/paint call Standard_Integer myDefaultWidth; //!< default width for the first sizeHint Standard_Integer myDefaultHeight; //!< default height for the first sizeHint Standard_Boolean myViewIsEnabled; //!< flag if the view and tool bar view actions are enabled/disabled + Standard_Integer myXmin; //!< cached X minimal position by mouse press event + Standard_Integer myYmin; //!< cached Y minimal position by mouse press event + Standard_Integer myXmax; //!< cached X maximum position by mouse press event + Standard_Integer myYmax; //!< cached Y maximum position by mouse press event + Standard_Integer myDragButtonDownX; //!< cached X button down by drag event + Standard_Integer myDragButtonDownY; //!< cached Y button down by drag event + Standard_Integer myDragMultiButtonDownX; //!< cached X button down by multi drag event + Standard_Integer myDragMultiButtonDownY; //!< cached Y button down by multi drag event + Standard_Boolean myIsRectVisible; //!< true if rectangle is visible now + QRubberBand* myRectBand; //!< selection rectangle rubber band Standard_Boolean myHasInitProj; //!< is initial camera position defined Standard_Real myInitVx; //!< initial camera position on X Standard_Real myInitVy; //!< initial camera position on Y Standard_Real myInitVz; //!< initial camera position on Z + }; #endif diff --git a/tools/View/View_Window.cxx b/tools/View/View_Window.cxx index beb4cda431..f47cbeb9c2 100644 --- a/tools/View/View_Window.cxx +++ b/tools/View/View_Window.cxx @@ -69,7 +69,8 @@ View_Window::View_Window (QWidget* theParent, myActionsToolBar->setOrientation (Qt::Vertical); myActionsToolBar->addWidget (myView-> GetWidget (View_ViewActionType_FitAllId)); - myActionsToolBar->addAction (myView->ViewAction (View_ViewActionType_DisplayModeId)); + for (int anActionId = View_ViewActionType_FitAreaId; anActionId <= View_ViewActionType_DisplayModeId; anActionId++) + myActionsToolBar->addAction (myView->ViewAction ((View_ViewActionType)anActionId)); aViewLayout->addWidget (myActionsToolBar, 1, 0); aViewLayout->addWidget (myView, 1, 1); @@ -95,33 +96,6 @@ void View_Window::SetContext (View_ContextType /*theType*/, const Handle(AIS_Int ViewToolBar()->SetContext (View_ContextType_External, theContext); } -// ======================================================================= -// function : SetPredefinedSize -// purpose : -// ======================================================================= -void View_Window::SetPredefinedSize (int theDefaultWidth, int theDefaultHeight) -{ - myView->SetPredefinedSize (theDefaultWidth, theDefaultHeight); -} - -// ======================================================================= -// function : SetInitProj -// purpose : -// ======================================================================= -void View_Window::SetInitProj (const Standard_Real theVx, const Standard_Real theVy, const Standard_Real theVz) -{ - myView->SetInitProj (theVx, theVy, theVz); -} - -// ======================================================================= -// function : View -// purpose : -// ======================================================================= -Handle(V3d_View) View_Window::View() const -{ - return myView->GetViewer()->GetView(); -} - // ======================================================================= // function : SaveState // purpose : @@ -131,7 +105,7 @@ void View_Window::SaveState (View_Window* theView, QMap& theIt { QStringList aCameraDirection; Standard_Real aVX, aVY, aVZ; - Handle(V3d_View) aView = theView->View(); + Handle(V3d_View) aView = theView->ViewWidget()->GetViewer()->GetView(); if (aView.IsNull()) return; @@ -161,7 +135,7 @@ bool View_Window::RestoreState (View_Window* theView, const QString& theKey, con Standard_Real aVY = aValues.at (1).toDouble(); Standard_Real aVZ = aValues.at (2).toDouble(); - theView->SetInitProj (aVX, aVY, aVZ); + theView->ViewWidget()->SetInitProj (aVX, aVY, aVZ); } return true; } @@ -222,12 +196,6 @@ void View_Window::onToolBarActionClicked (const int theActionId) myDisplayer->DisplayDefaultTrihedron (myViewToolBar->IsActionChecked (theActionId), Standard_True); break; } - case View_ToolActionType_ViewCube: - { - myDisplayer->DisplayViewCube (myViewToolBar->IsActionChecked (theActionId), Standard_True); - break; - } - case View_ToolActionType_KeepViewId: { myDisplayer->KeepPresentations (myViewToolBar->IsActionChecked (theActionId)); diff --git a/tools/View/View_Window.hxx b/tools/View/View_Window.hxx index 8d85646fbc..b270f816d3 100644 --- a/tools/View/View_Window.hxx +++ b/tools/View/View_Window.hxx @@ -64,18 +64,6 @@ public: //! \param theContext an AIS context Standard_EXPORT void SetContext (View_ContextType theType, const Handle(AIS_InteractiveContext)& theContext); - //! Sets default size that is used in sizeHint when the widget is firstly show - Standard_EXPORT void SetPredefinedSize (int theDefaultWidth, int theDefaultHeight); - - //! Sets initial camera position - //! \param theVx direction on Ox - //! \param theVy direction on Oy - //! \param theVz direction on Oz - Standard_EXPORT void SetInitProj (const Standard_Real theVx, const Standard_Real theVy, const Standard_Real theVz); - - //! Returns an active view - Standard_EXPORT Handle(V3d_View) View() const; - //! Saves state of view window in a container in form: key, value. It saves: //! - visibility of columns, //! - columns width diff --git a/tools/View/icons/cursor_rotate.png b/tools/View/icons/cursor_rotate.png new file mode 100644 index 0000000000..a3cb0c1ecc Binary files /dev/null and b/tools/View/icons/cursor_rotate.png differ diff --git a/tools/View/icons/cursor_zoom.png b/tools/View/icons/cursor_zoom.png new file mode 100644 index 0000000000..0020fea39f Binary files /dev/null and b/tools/View/icons/cursor_zoom.png differ diff --git a/tools/View/icons/view_cube.png b/tools/View/icons/view_cube.png deleted file mode 100644 index d373c4b238..0000000000 Binary files a/tools/View/icons/view_cube.png and /dev/null differ diff --git a/tools/View/icons/view_fitarea.png b/tools/View/icons/view_fitarea.png new file mode 100644 index 0000000000..f20f5c0554 Binary files /dev/null and b/tools/View/icons/view_fitarea.png differ diff --git a/tools/View/icons/view_pan.png b/tools/View/icons/view_pan.png new file mode 100644 index 0000000000..68343b8ddb Binary files /dev/null and b/tools/View/icons/view_pan.png differ diff --git a/tools/View/icons/view_rotate.png b/tools/View/icons/view_rotate.png new file mode 100644 index 0000000000..7e5d013b9f Binary files /dev/null and b/tools/View/icons/view_rotate.png differ diff --git a/tools/View/icons/view_zoom.png b/tools/View/icons/view_zoom.png new file mode 100644 index 0000000000..1b50a37bc8 Binary files /dev/null and b/tools/View/icons/view_zoom.png differ diff --git a/tools/ViewControl/FILES b/tools/ViewControl/FILES index 9fda7a71be..3560ed5779 100644 --- a/tools/ViewControl/FILES +++ b/tools/ViewControl/FILES @@ -3,6 +3,8 @@ ViewControl_MessageDialog.cxx ViewControl_MessageDialog.hxx ViewControl_PropertyView.cxx ViewControl_PropertyView.hxx +ViewControl_PropertiesDialog.cxx +ViewControl_PropertiesDialog.hxx ViewControl_Table.cxx ViewControl_Table.hxx ViewControl_TableModel.cxx diff --git a/tools/ViewControl/ViewControl_PropertiesDialog.cxx b/tools/ViewControl/ViewControl_PropertiesDialog.cxx new file mode 100644 index 0000000000..c72627aa6e --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertiesDialog.cxx @@ -0,0 +1,65 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +#include +#include +#include +#include +#include + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +ViewControl_PropertiesDialog::ViewControl_PropertiesDialog (QWidget* theParent) +: QDialog (theParent) +{ + setWindowTitle ("Properties"); + + QGridLayout* aLayout = new QGridLayout (this); + myTable = new ViewControl_Table (this); + ViewControl_TableModel* aModel = new ViewControl_TableModel (myTable->TableView()); + myTable->SetModel (aModel); + + aLayout->addWidget(myTable->TableView(), 0, 0, 1, 3); + + myOkButton = new QPushButton ("Ok", this); + myCancelButton = new QPushButton ("Cancel", this); + connect (myOkButton, SIGNAL (clicked()), this, SLOT (accept())); + connect (myCancelButton, SIGNAL (clicked()), this, SLOT (reject())); + aLayout->addWidget (myOkButton, 1, 1); + aLayout->addWidget (myCancelButton, 1, 2); + + aLayout->setColumnStretch (0, 1); + + myCancelButton->setDefault (true); + + setMinimumSize (200, 600); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void ViewControl_PropertiesDialog::Init (const Handle(TreeModel_ItemProperties)& theProperties) +{ + ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (theProperties); + + myTable->Init (aTableValues); +} diff --git a/tools/ViewControl/ViewControl_PropertiesDialog.hxx b/tools/ViewControl/ViewControl_PropertiesDialog.hxx new file mode 100644 index 0000000000..609bcb9226 --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertiesDialog.hxx @@ -0,0 +1,54 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ViewControl_PropertiesDialog_H +#define ViewControl_PropertiesDialog_H + +#include +#include + +#include + +#include +#include +#include + +class TreeModel_ItemProperties; + +class QWidget; +class QPushButton; + +//! \class ViewControl_PropertiesDialog +//! Dialog providing table of stream values +class ViewControl_PropertiesDialog : public QDialog +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT ViewControl_PropertiesDialog (QWidget* theParent); + + //! Destructor + virtual ~ViewControl_PropertiesDialog() {} + + Standard_EXPORT void Init (const Handle(TreeModel_ItemProperties)& theProperties); + +private: + ViewControl_Table* myTable; //!< table view + + QPushButton* myOkButton; //!< accept button + QPushButton* myCancelButton; //!< reject button +}; + + +#endif