From 64c52c0521e437e1923c3898f37bff5dc60ffaf9 Mon Sep 17 00:00:00 2001 From: nds Date: Fri, 4 Oct 2019 18:30:10 +0300 Subject: [PATCH] 0029451: Information Message Alert to debug an algorithm or object functionality (cherry picked from commit 4c6cbbf845945848cc2cb730d58ac07734ae5440) --- adm/TOOLS | 2 +- src/Message/FILES | 20 +- src/Message/Message.cxx | 339 ++++++++ src/Message/Message.hxx | 132 ++- src/Message/Message_AlertExtended.cxx | 81 ++ src/Message/Message_AlertExtended.hxx | 133 +++ src/Message/Message_Alerts.hxx | 102 +++ src/Message/Message_Attribute.cxx | 30 + src/Message/Message_Attribute.hxx | 67 ++ src/Message/Message_AttributeObject.cxx | 32 + src/Message/Message_AttributeObject.hxx | 46 + src/Message/Message_AttributeStream.cxx | 47 + src/Message/Message_AttributeStream.hxx | 50 ++ src/Message/Message_CompositeAlerts.cxx | 69 ++ src/Message/Message_CompositeAlerts.hxx | 67 ++ src/Message/Message_PerfMeter.cxx | 192 ++++ src/Message/Message_PerfMeter.hxx | 97 +++ src/Message/Message_PerfMeterMode.hxx | 34 + src/Message/Message_Report.cxx | 252 ++++++ src/Message/Message_Report.hxx | 76 +- src/Message/Message_ReportCallBack.cxx | 22 + src/Message/Message_ReportCallBack.hxx | 44 + src/NCollection/NCollection_Mat4.hxx | 14 + src/OSD/OSD_MemInfo.cxx | 139 +++ src/OSD/OSD_MemInfo.hxx | 3 + src/OpenGl/OpenGl_Context.cxx | 13 + src/OpenGl/OpenGl_Context.hxx | 3 + src/OpenGl/OpenGl_MatrixState.hxx | 12 + src/TopoDS/FILES | 2 + src/TopoDS/TopoDS_AlertAttribute.cxx | 37 + src/TopoDS/TopoDS_AlertAttribute.hxx | 51 ++ src/XmlDrivers/FILES | 2 + .../XmlDrivers_MessageReportStorage.cxx | 347 ++++++++ .../XmlDrivers_MessageReportStorage.hxx | 68 ++ tools/MessageModel/FILES | 18 + tools/MessageModel/MessageModel.qrc | 6 + .../MessageModel/MessageModel_ActionType.hxx | 30 + tools/MessageModel/MessageModel_Actions.cxx | 367 ++++++++ tools/MessageModel/MessageModel_Actions.hxx | 104 +++ tools/MessageModel/MessageModel_ItemAlert.cxx | 332 +++++++ tools/MessageModel/MessageModel_ItemAlert.hxx | 132 +++ tools/MessageModel/MessageModel_ItemBase.cxx | 47 + tools/MessageModel/MessageModel_ItemBase.hxx | 56 ++ .../MessageModel/MessageModel_ItemReport.cxx | 200 +++++ .../MessageModel/MessageModel_ItemReport.hxx | 114 +++ tools/MessageModel/MessageModel_ItemRoot.cxx | 96 ++ tools/MessageModel/MessageModel_ItemRoot.hxx | 123 +++ .../MessageModel_ReportCallBack.cxx | 18 + .../MessageModel_ReportCallBack.hxx | 48 + tools/MessageModel/MessageModel_Tools.cxx | 195 +++++ tools/MessageModel/MessageModel_Tools.hxx | 74 ++ tools/MessageModel/MessageModel_TreeModel.cxx | 153 ++++ tools/MessageModel/MessageModel_TreeModel.hxx | 93 ++ tools/MessageModel/icons/item_shape.png | Bin 0 -> 614 bytes tools/MessageModel/icons/item_shape.svg | 122 +++ .../MessageModel/icons/item_vectorOfReal.png | Bin 0 -> 347 bytes .../MessageModel/icons/item_vectorOfReal.svg | 103 +++ .../icons/item_vectorOfRealVec3.png | Bin 0 -> 421 bytes .../icons/item_vectorOfRealVec3.svg | 124 +++ .../icons/item_vectorOfValues.png | Bin 0 -> 347 bytes .../icons/item_vectorOfValues.svg | 103 +++ tools/MessageView/FILES | 6 + .../MessageView/MessageView_Communicator.cxx | 26 + .../MessageView/MessageView_Communicator.hxx | 68 ++ .../MessageView_VisibilityState.cxx | 140 +++ .../MessageView_VisibilityState.hxx | 87 ++ tools/MessageView/MessageView_Window.cxx | 818 ++++++++++++++++++ tools/MessageView/MessageView_Window.hxx | 186 ++++ tools/TInspectorEXE/TInspectorEXE.cxx | 8 +- tools/TKMessageModel/CMakeLists.txt | 5 + tools/TKMessageModel/EXTERNLIB | 10 + tools/TKMessageModel/FILES | 2 + tools/TKMessageModel/PACKAGES | 1 + tools/TKMessageView/CMakeLists.txt | 5 + tools/TKMessageView/EXTERNLIB | 13 + tools/TKMessageView/FILES | 2 + tools/TKMessageView/PACKAGES | 1 + tools/ToolsDraw/ToolsDraw.cxx | 4 +- tools/TreeModel/TreeModel_ItemBase.cxx | 12 +- tools/TreeModel/TreeModel_ItemStream.cxx | 12 +- tools/VInspector/VInspector_Window.cxx | 45 +- 81 files changed, 6691 insertions(+), 43 deletions(-) create mode 100644 src/Message/Message_AlertExtended.cxx create mode 100644 src/Message/Message_AlertExtended.hxx create mode 100644 src/Message/Message_Alerts.hxx create mode 100644 src/Message/Message_Attribute.cxx create mode 100644 src/Message/Message_Attribute.hxx create mode 100644 src/Message/Message_AttributeObject.cxx create mode 100644 src/Message/Message_AttributeObject.hxx create mode 100644 src/Message/Message_AttributeStream.cxx create mode 100644 src/Message/Message_AttributeStream.hxx create mode 100644 src/Message/Message_CompositeAlerts.cxx create mode 100644 src/Message/Message_CompositeAlerts.hxx create mode 100644 src/Message/Message_PerfMeter.cxx create mode 100644 src/Message/Message_PerfMeter.hxx create mode 100644 src/Message/Message_PerfMeterMode.hxx create mode 100644 src/Message/Message_ReportCallBack.cxx create mode 100644 src/Message/Message_ReportCallBack.hxx create mode 100644 src/TopoDS/TopoDS_AlertAttribute.cxx create mode 100644 src/TopoDS/TopoDS_AlertAttribute.hxx create mode 100644 src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx create mode 100644 src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx create mode 100644 tools/MessageModel/FILES create mode 100644 tools/MessageModel/MessageModel.qrc create mode 100644 tools/MessageModel/MessageModel_ActionType.hxx create mode 100644 tools/MessageModel/MessageModel_Actions.cxx create mode 100644 tools/MessageModel/MessageModel_Actions.hxx create mode 100644 tools/MessageModel/MessageModel_ItemAlert.cxx create mode 100644 tools/MessageModel/MessageModel_ItemAlert.hxx create mode 100644 tools/MessageModel/MessageModel_ItemBase.cxx create mode 100644 tools/MessageModel/MessageModel_ItemBase.hxx create mode 100644 tools/MessageModel/MessageModel_ItemReport.cxx create mode 100644 tools/MessageModel/MessageModel_ItemReport.hxx create mode 100644 tools/MessageModel/MessageModel_ItemRoot.cxx create mode 100644 tools/MessageModel/MessageModel_ItemRoot.hxx create mode 100644 tools/MessageModel/MessageModel_ReportCallBack.cxx create mode 100644 tools/MessageModel/MessageModel_ReportCallBack.hxx create mode 100644 tools/MessageModel/MessageModel_Tools.cxx create mode 100644 tools/MessageModel/MessageModel_Tools.hxx create mode 100644 tools/MessageModel/MessageModel_TreeModel.cxx create mode 100644 tools/MessageModel/MessageModel_TreeModel.hxx create mode 100644 tools/MessageModel/icons/item_shape.png create mode 100644 tools/MessageModel/icons/item_shape.svg create mode 100644 tools/MessageModel/icons/item_vectorOfReal.png create mode 100644 tools/MessageModel/icons/item_vectorOfReal.svg create mode 100644 tools/MessageModel/icons/item_vectorOfRealVec3.png create mode 100644 tools/MessageModel/icons/item_vectorOfRealVec3.svg create mode 100644 tools/MessageModel/icons/item_vectorOfValues.png create mode 100644 tools/MessageModel/icons/item_vectorOfValues.svg create mode 100644 tools/MessageView/FILES create mode 100644 tools/MessageView/MessageView_Communicator.cxx create mode 100644 tools/MessageView/MessageView_Communicator.hxx create mode 100644 tools/MessageView/MessageView_VisibilityState.cxx create mode 100644 tools/MessageView/MessageView_VisibilityState.hxx create mode 100644 tools/MessageView/MessageView_Window.cxx create mode 100644 tools/MessageView/MessageView_Window.hxx create mode 100644 tools/TKMessageModel/CMakeLists.txt create mode 100644 tools/TKMessageModel/EXTERNLIB create mode 100644 tools/TKMessageModel/FILES create mode 100644 tools/TKMessageModel/PACKAGES create mode 100644 tools/TKMessageView/CMakeLists.txt create mode 100644 tools/TKMessageView/EXTERNLIB create mode 100644 tools/TKMessageView/FILES create mode 100644 tools/TKMessageView/PACKAGES diff --git a/adm/TOOLS b/adm/TOOLS index b106a7c10b..57ddcfcc64 100644 --- a/adm/TOOLS +++ b/adm/TOOLS @@ -1,4 +1,4 @@ -TModelingData TKShapeView +TModelingData TKShapeView TKMessageModel TKMessageView TVisualization TKView TKVInspector TApplicationFramework TKTreeModel TKTInspectorAPI TKDFBrowser TTool TKTInspector TKToolsDraw TInspectorEXE \ No newline at end of file diff --git a/src/Message/FILES b/src/Message/FILES index e502c6903c..9a4bf4a982 100755 --- a/src/Message/FILES +++ b/src/Message/FILES @@ -1,8 +1,21 @@ Message.cxx Message.hxx +Message_Alert.cxx +Message_Alert.hxx +Message_AlertExtended.cxx +Message_AlertExtended.hxx +Message_Alerts.hxx Message_Algorithm.cxx Message_Algorithm.hxx Message_Algorithm.lxx +Message_Attribute.cxx +Message_Attribute.hxx +Message_AttributeObject.cxx +Message_AttributeObject.hxx +Message_AttributeStream.cxx +Message_AttributeStream.hxx +Message_CompositeAlerts.cxx +Message_CompositeAlerts.hxx Message_ExecStatus.hxx Message_Gravity.hxx Message_HArrayOfMsg.hxx @@ -15,6 +28,9 @@ Message_Msg.hxx Message_Msg.lxx Message_MsgFile.cxx Message_MsgFile.hxx +Message_PerfMeter.cxx +Message_PerfMeter.hxx +Message_PerfMeterMode.hxx Message_Printer.cxx Message_Printer.hxx Message_PrinterOStream.cxx @@ -32,8 +48,8 @@ Message_SequenceOfPrinters.hxx Message_SequenceOfProgressScale.hxx Message_Status.hxx Message_StatusType.hxx -Message_Alert.cxx -Message_Alert.hxx Message_ListOfAlert.hxx Message_Report.cxx Message_Report.hxx +Message_ReportCallBack.cxx +Message_ReportCallBack.hxx diff --git a/src/Message/Message.cxx b/src/Message/Message.cxx index b540ae5fb2..3aea6317a4 100644 --- a/src/Message/Message.cxx +++ b/src/Message/Message.cxx @@ -49,3 +49,342 @@ TCollection_AsciiString Message::FillTime (const Standard_Integer hour, Sprintf (t, "%.2fs", second); return TCollection_AsciiString (t); } + +namespace +{ + static Standard_CString Message_Table_PrintGravityEnum[5] = + { + "TRACE", "INFO", "WARNING", "ALARM", "FAIL" + }; + + static Standard_CString Message_Table_PrintPerfMeterModeEnum[10] = + { + "NONE", "USER_TIME_CPU", "SYSTEM_TIME_CPU", "MEM_PRIVATE", "MEM_VIRTUAL", + "MEM_WORKING_SET", "MEM_WORKING_SET_PEAK", "MEM_SWAP_USAGE", "MEM_SWAP_USAGE_PEAK", "MEM_HEAP_USAGE" + }; +} + +//======================================================================= +//function : GravityToString +//purpose : +//======================================================================= + +Standard_CString Message::GravityToString (const Message_Gravity theGravity) +{ + return Message_Table_PrintGravityEnum[theGravity]; +} + +//======================================================================= +//function : GravityFromString +//purpose : +//======================================================================= + +Standard_Boolean Message::GravityFromString (const Standard_CString theGravityString, + Message_Gravity& theGravity) +{ + TCollection_AsciiString aName (theGravityString); + aName.UpperCase(); + for (Standard_Integer aGravityIter = 0; aGravityIter <= Message_Fail; ++aGravityIter) + { + Standard_CString aGravityName = Message_Table_PrintGravityEnum[aGravityIter]; + if (aName == aGravityName) + { + theGravity = Message_Gravity (aGravityIter); + return Standard_True; + } + } + return Standard_False; +} + +//======================================================================= +//function : PerfMeterModeToString +//purpose : +//======================================================================= + +Standard_CString Message::PerfMeterModeToString (const Message_PerfMeterMode theValue) +{ + return Message_Table_PrintPerfMeterModeEnum[theValue]; +} + +//======================================================================= +//function : PerfMeterModeFromString +//purpose : +//======================================================================= + +Standard_Boolean Message::PerfMeterModeFromString (const Standard_CString theString, + Message_PerfMeterMode& theValue) +{ + TCollection_AsciiString aName (theString); + aName.UpperCase(); + for (Standard_Integer aModeIter = 0; aModeIter <= Message_PerfMeterMode_MemHeapUsage; ++aModeIter) + { + Standard_CString aModeName = Message_Table_PrintPerfMeterModeEnum[aModeIter]; + if (aName == aModeName) + { + theValue = Message_PerfMeterMode (aModeIter); + return Standard_True; + } + } + return Standard_False; +} + +// ======================================================================= +// function : GetPointerInfo +// purpose : +// ======================================================================= +TCollection_AsciiString Message::TransientToString (const Handle(Standard_Transient)& thePointer, const bool isShortInfo) +{ + if (thePointer.IsNull()) + return TCollection_AsciiString(); + + return PointerToString(thePointer.operator->(), isShortInfo); +} + +// ======================================================================= +// function : GetPointerInfo +// purpose : +// ======================================================================= +TCollection_AsciiString Message::PointerToString (const void* thePointer, const bool isShortInfo) +{ + std::ostringstream aPtrStr; + aPtrStr << thePointer; + 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(); +} + +// ======================================================================= +// function : StrVectorToString +// purpose : +// ======================================================================= +TCollection_AsciiString Message::StrVectorToString + (const NCollection_Vector& theValues) +{ + TCollection_AsciiString aValue; + for (NCollection_Vector::Iterator aValuesIt (theValues); aValuesIt.More(); aValuesIt.Next()) + { + aValue += aValuesIt.Value(); + if (aValuesIt.More()) + aValue += VectorSeparator(); + } + return aValue; +} + +// ======================================================================= +// function : StrVectorFromString +// purpose : +// ======================================================================= +Standard_Boolean Message::StrVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues) +{ + TCollection_AsciiString aCurrentString = theValue, aValueString; + + while (!aCurrentString.IsEmpty()) + { + Standard_Integer aPosition = aCurrentString.Search (", "); + aValueString = aCurrentString; + if (aPosition > 0) + aCurrentString = aValueString.Split (aPosition - 1); + theValues.Append (aValueString.RealValue()); + if (aPosition > 0) + aCurrentString = aCurrentString.Split (2); + } + return Standard_True; +} + +// ======================================================================= +// function : RealVectorToString +// purpose : +// ======================================================================= +TCollection_AsciiString Message::RealVectorToString + (const NCollection_Vector& theValues) +{ + TCollection_AsciiString aValue = ("("); + + for (NCollection_Vector::Iterator aValuesIt (theValues); aValuesIt.More(); aValuesIt.Next()) + { + aValue += aValuesIt.Value(); + if (aValuesIt.More()) + aValue += VectorSeparator(); + } + aValue += ")"; + + return aValue; +} + +// ======================================================================= +// function : RealVectorFromString +// purpose : +// ======================================================================= +Standard_Boolean Message::RealVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues) +{ + TCollection_AsciiString aCurrentString = theValue, aValueString; + + Standard_Integer aPosition = aCurrentString.Search ("("); + if (aPosition != 1) + return Standard_False; + aCurrentString = aCurrentString.Split (aPosition); + + aPosition = aCurrentString.Search (")"); + if (aPosition != 1) + return Standard_False; + aValueString = aCurrentString.Split (aPosition); + + + while (!aCurrentString.IsEmpty()) + { + // x value + aPosition = aCurrentString.Search (", "); + aValueString = aCurrentString; + if (aPosition > 0) + aCurrentString = aValueString.Split (aPosition - 1); + theValues.Append (aValueString.RealValue()); + if (aPosition > 0) + aCurrentString = aCurrentString.Split (2); + } + return Standard_True; +} + +// ======================================================================= +// function : CoordVectorToString +// purpose : +// ======================================================================= +TCollection_AsciiString Message::CoordVectorToString + (const NCollection_Vector& theValues) +{ + TCollection_AsciiString aValue = ("("); + aValue += RealVectorToString (theValues); + aValue += ")"; + + return aValue; +} + +// ======================================================================= +// function : CoordVectorFromString +// purpose : +// ======================================================================= +Standard_Boolean Message::CoordVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues) +{ + TCollection_AsciiString aCurrentString = theValue, aValueString; + + Standard_Integer aPosition = aCurrentString.Search ("("); + if (aPosition != 1) + return Standard_False; + aCurrentString = aCurrentString.Split (aPosition); + + aPosition = aCurrentString.Search (")"); + if (aPosition != 1) + return Standard_False; + aValueString = aCurrentString.Split (aPosition); + + return RealVectorFromString (aCurrentString, theValues); +} + +// ======================================================================= +// function : ColorVectorToString +// purpose : +// ======================================================================= +TCollection_AsciiString Message::ColorVectorToString + (const NCollection_Vector& theValues) +{ + TCollection_AsciiString aValue = ("["); + aValue += RealVectorToString (theValues); + aValue += "]"; + + return aValue; +} + +// ======================================================================= +// function : ColorVectorFromString +// purpose : +// ======================================================================= +Standard_Boolean Message::ColorVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues) +{ + TCollection_AsciiString aCurrentString = theValue, aValueString; + + Standard_Integer aPosition = aCurrentString.Search ("["); + if (aPosition != 1) + return Standard_False; + aCurrentString = aCurrentString.Split (aPosition); + + aPosition = aCurrentString.Search ("]"); + if (aPosition != 1) + return Standard_False; + aValueString = aCurrentString.Split (aPosition); + + return RealVectorFromString (aCurrentString, theValues); +} + +// ======================================================================= +// function : ConvertStream +// purpose : +// ======================================================================= +void Message::ConvertStream (const Standard_SStream& theStream, + Standard_Integer& theColumnCount, + NCollection_Vector& theValues) +{ + TCollection_AsciiString aStream (theStream.str().c_str()); + Standard_Character aSeparator = Message::DumpSeparator(); + Standard_Integer aColumnCount = 0; + + TCollection_AsciiString aCurrentString = aStream; + Standard_Integer aPosition = aCurrentString.Search (aSeparator); + if (aPosition >= 1) + { + TCollection_AsciiString aTailString = aCurrentString.Split (aPosition); + Standard_Boolean aClassNameFound = Standard_False; + while (!aCurrentString.IsEmpty()) + { + TCollection_AsciiString aValueString = aCurrentString; + aPosition = aValueString.Search (aSeparator); + if (aPosition < 0 ) + break; + aCurrentString = aValueString.Split (aPosition - 1); + + if (!aColumnCount) + { + if (!aClassNameFound) + aClassNameFound = Standard_True; + else + { + if (!aValueString.IsIntegerValue()) + break; // not correct Dump, in correct the first value is number of property columns + aColumnCount = aValueString.IntegerValue(); + } + } + else + theValues.Append (aValueString); + + if (aTailString.IsEmpty()) + break; + aCurrentString = aTailString; + aPosition = aCurrentString.Search (aSeparator); + if (aPosition < 0 ) + { + aCurrentString = aTailString; + aTailString = TCollection_AsciiString(); + } + else + aTailString = aCurrentString.Split (aPosition); + } + } + theColumnCount = aColumnCount; +} diff --git a/src/Message/Message.hxx b/src/Message/Message.hxx index 4be71135b3..6c440bad81 100644 --- a/src/Message/Message.hxx +++ b/src/Message/Message.hxx @@ -17,14 +17,19 @@ #ifndef _Message_HeaderFile #define _Message_HeaderFile +#include +#include +#include + #include #include #include #include #include +#include + class Message_Messenger; -class TCollection_AsciiString; class Message_Msg; class Message_MsgFile; class Message_Messenger; @@ -59,8 +64,129 @@ public: //! 3. (0, 0, 4.5 ) returns "4.50s" Standard_EXPORT static TCollection_AsciiString FillTime (const Standard_Integer Hour, const Standard_Integer Minute, const Standard_Real Second); - - + //! Returns the string name for a given gravity. + //! @param Gravity gravity type + //! @return string identifier from the list Message_Trace, Message_Info, Message_Warning, Message_Alarm and Message_Fail + Standard_EXPORT static Standard_CString GravityToString (const Message_Gravity theGravity); + + //! Returns the gravity type from the given string identifier (using case-insensitive comparison). + //! @param theGravityString string identifier + //! @return gravity or Message_Trace if string identifier is invalid + static Message_Gravity GravityFromString (const Standard_CString theGravityString) + { + Message_Gravity aGravity = Message_Trace; + GravityFromString (theGravityString, aGravity); + return aGravity; + } + + //! Determines the gravity from the given string identifier (using case-insensitive comparison). + //! @param theGravityString string identifier + //! @param theGravity detected shape type + //! @return TRUE if string identifier is known + Standard_EXPORT static Standard_Boolean GravityFromString (const Standard_CString theGravityString, + Message_Gravity& theGravity); + + //! Returns the string name for a perf meter mode. + //! @param theValue mode + //! @return string identifier + Standard_EXPORT static Standard_CString PerfMeterModeToString (const Message_PerfMeterMode theValue); + + //! Returns the enum value from the given string identifier (using case-insensitive comparison). + //! @param theString string identifier + //! @return enum or Message_PerfMeterMode_None if string identifier is invalid + static Message_PerfMeterMode PerfMeterModeFromString (const Standard_CString theString) + { + Message_PerfMeterMode aValue = Message_PerfMeterMode_None; + PerfMeterModeFromString (theString, aValue); + return aValue; + } + + //! Returns the enum value from the given string identifier (using case-insensitive comparison). + //! @param theString string identifier + //! @return enum or Message_PerfMeterMode_None if string identifier is invalid + //! @return TRUE if string identifier is known + Standard_EXPORT static Standard_Boolean PerfMeterModeFromString (const Standard_CString theString, + Message_PerfMeterMode& theValue); + + + //! Returns separator symbol of Dump information + static Standard_Character DumpSeparator() { return '\\'; } + + //! Returns separator symbol of values vector union + static TCollection_AsciiString VectorSeparator() { return " ,"; } + + //! Convert handle 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 TransientToString (const Handle(Standard_Transient)& thePointer, + const bool isShortInfo = true); + + //! 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 PointerToString (const void* thePointer, + const bool isShortInfo = true); + //! Convert vector of real values to string, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static TCollection_AsciiString StrVectorToString + (const NCollection_Vector& theValues); + + //! Convert string to vector of real values, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static Standard_Boolean StrVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues); + + //! Convert vector of real values to string, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static TCollection_AsciiString RealVectorToString + (const NCollection_Vector& theValues); + + //! Convert string to vector of real values, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static Standard_Boolean RealVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues); + + //! Convert vector of real values to string, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static TCollection_AsciiString CoordVectorToString + (const NCollection_Vector& theValues); + + //! Convert string to vector of real values, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static Standard_Boolean CoordVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues); + + //! Convert vector of real values to string, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static TCollection_AsciiString ColorVectorToString + (const NCollection_Vector& theValues); + + //! Convert string to vector of real values, separator is vector separator + //! \param thePointer a container of real values + //! \return the string value + Standard_EXPORT static Standard_Boolean ColorVectorFromString + (const TCollection_AsciiString& theValue, + NCollection_Vector& theValues); + + //! Converts stream to vector of values and column count + //! \param theStream stream value + //! \param theColumnCount [out] number of columns + //! \param theValues [out] container of split values + static Standard_EXPORT void ConvertStream (const Standard_SStream& theStream, + Standard_Integer& theColumnCount, + NCollection_Vector& theValues); protected: diff --git a/src/Message/Message_AlertExtended.cxx b/src/Message/Message_AlertExtended.cxx new file mode 100644 index 0000000000..44555fccf2 --- /dev/null +++ b/src/Message/Message_AlertExtended.cxx @@ -0,0 +1,81 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_AlertExtended,Message_Alert) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_AlertExtended::GetMessageKey () const +{ + if (myAttribute.IsNull()) + return Message_Alert::GetMessageKey(); + + return myAttribute->GetMessageKey(); +} + +//======================================================================= +//function : GetCompositeAlerts +//purpose : +//======================================================================= + +Handle (Message_CompositeAlerts) Message_AlertExtended::GetCompositeAlerts (const Standard_Boolean isCreate) +{ + if (myCompositAlerts.IsNull() && isCreate) + myCompositAlerts = new Message_CompositeAlerts(); + + return myCompositAlerts; +} + +//======================================================================= +//function : IsMetricValid +//purpose : +//======================================================================= + +Standard_Boolean Message_AlertExtended::IsMetricValid() const +{ + return fabs (myMetricStart - GetUndefinedMetric()) > Precision::Confusion() && + fabs (myMetricStop - GetUndefinedMetric()) > Precision::Confusion(); +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= + +Handle(Message_Alert) Message_AlertExtended::AddAlert (const Handle(Message_Report)& theReport, + const Handle(Message_Attribute)& theAttribute, + Message_PerfMeter* thePerfMeter, + const Handle(Message_Alert)& theParentAlert) +{ + if (!theReport->IsActive (Message_Info)) + return Handle(Message_Alert)(); + + Handle(Message_AlertExtended) anAlert = new Message_AlertExtended(); + anAlert->SetAttribute (theAttribute); + theReport->AddAlert (Message_Info, anAlert, thePerfMeter, theParentAlert); + + return anAlert; +} diff --git a/src/Message/Message_AlertExtended.hxx b/src/Message/Message_AlertExtended.hxx new file mode 100644 index 0000000000..bac7047cd9 --- /dev/null +++ b/src/Message/Message_AlertExtended.hxx @@ -0,0 +1,133 @@ +// Created on: 2018-06-10 +// 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 _Message_AlertExtended_HeaderFile +#define _Message_AlertExtended_HeaderFile + +#include +#include + +class Message_Attribute; +class Message_PerfMeter; +class Message_Report; + +DEFINE_STANDARD_HANDLE(Message_AlertExtended, Message_Alert) + +class Message_CompositeAlerts; + +//! Inherited class of Message_Alert with some additional information. +//! +//! It has Message_Attributes to provide the alert name, description and +//! other custom information +//! +//! It is possible to set performance meter into alert to store time/memory metric information +//! spent between the next alert adding. Also time of child alerts are collected +//! +//! It has a container of composite alerts, if the alert might provide +//! sub-alerts collecting. +//! + +class Message_AlertExtended : public Message_Alert +{ +public: + //! Empty constructor + Standard_EXPORT Message_AlertExtended() + : Message_Alert(), myMetricStart (GetUndefinedMetric()), myMetricStop (GetUndefinedMetric()) {} + + //! Return a C string to be used as a key for generating text user + //! messages describing this alert. + //! The messages are generated with help of Message_Msg class, in + //! Message_Report::Dump(). + //! Base implementation returns dynamic type name of the instance. + virtual Standard_EXPORT Standard_CString GetMessageKey () const; + + //! Sets container of the alert attributes + //! \param theAttributes an attribute values + void SetAttribute (const Handle(Message_Attribute)& theAttribute) { myAttribute = theAttribute; } + + //! Returns container of the alert attributes + //! \param theAttributes an attribute values + const Handle(Message_Attribute)& Attribute () const { return myAttribute; } + + //! Returns class provided hierarchy of alerts if created or create if the parameter is true + //! \param isCreate if composite alert has not been created for this alert, it should be created + //! \return instance or NULL + Standard_EXPORT Handle (Message_CompositeAlerts) GetCompositeAlerts (const Standard_Boolean isCreate = Standard_False); + + //! Returns performance meter + //! \return instance or NULL + Message_PerfMeter* GetPerfMeter() { return myPerfMeter; } + + //! Returns true if metric is computed + //! @return value + Standard_EXPORT Standard_Boolean IsMetricValid() const; + + //! Returns the alert cumulative metric. It includes time/mem of sub alerts + //! @return value + Standard_Real MetricStart() const { return myMetricStart; } + + //! Returns the alert cumulative metric. It includes time/mem of sub alerts + //! @return value + Standard_Real MetricStop() const { return myMetricStop; } + + //! Sets cumulative time/mem of alert + //! \param theCumulativeMetric time/mem of the alert + void SetMetricValues (const Standard_Real theStartValue, const Standard_Real theStopValue) + { myMetricStart = theStartValue; myMetricStop = theStopValue; } + + //! Return true if this type of alert can be merged with other + //! of the same type to avoid duplication. + //! Basis implementation returns true. + virtual Standard_EXPORT Standard_Boolean SupportsMerge () const { return Standard_False; } + + //! Returns default value of the time/mem when it is not defined + //! \return integer value + static Standard_Real GetUndefinedMetric() { return -1.0; } + + //! Creates new instance of the alert and put it into report with Message_Info gravity. + //! It does nothing if such kind of gravity is not active in the report + //! @param theReport the message report where new alert is placed + //! @param theAttribute container of additional values of the alert + //! @param thePerfMeter performance meter calculates the alert spent time and participate in searching the last alert if needed + //! @param theParentAlert parent for the new alert, or alert is placed under the report + //! @return created alert or NULL if Message_Info is not active in report + static Standard_EXPORT Handle(Message_Alert) AddAlert (const Handle(Message_Report)& theReport, + const Handle(Message_Attribute)& theAttribute, + Message_PerfMeter* thePerfMeter, + const Handle(Message_Alert)& theParentAlert = Handle(Message_Alert)()); + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AlertExtended, Message_Alert) + +protected: + //! Sets performance meter + //! \param theMeter instance pointer or NULL + void SetPerfMeter (Message_PerfMeter* theMeter) { myPerfMeter = theMeter; } + +protected: + + Handle(Message_CompositeAlerts) myCompositAlerts; //!< class provided hierarchical structure of alerts + //!< It should be created by an attempt of a child alert creation + + Handle(Message_Attribute) myAttribute; //!< container of the alert attributes + + Message_PerfMeter* myPerfMeter; //!< performance meter + Standard_Real myMetricStart; //!< value on start metric computation + Standard_Real myMetricStop; //!< value on stop metric computation + + friend Message_PerfMeter; +}; + +#endif // _Message_Alert_HeaderFile diff --git a/src/Message/Message_Alerts.hxx b/src/Message/Message_Alerts.hxx new file mode 100644 index 0000000000..9f73a1f56c --- /dev/null +++ b/src/Message/Message_Alerts.hxx @@ -0,0 +1,102 @@ +// Created on: 2018-06-10 +// 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 _Message_Alerts_HeaderFile +#define _Message_Alerts_HeaderFile + +#include +#include +#include +#include +#include +#include + +#include +#include + +static Handle(Message_Alert) OCCT_Message_Alert; + +#define MESSAGE_INFO(Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertExtended::AddAlert (Message_Report::CurrentReport(), \ + new Message_Attribute (Name, Description), PerfMeter, ParentAlert); \ + } \ + } + +#define MESSAGE_INFO_OBJECT(Object, StreamValues, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertExtended::AddAlert (Message_Report::CurrentReport(), \ + new Message_AttributeObject (Object, StreamValues, Name, Description), PerfMeter, ParentAlert ); \ + } \ + } + +#define MESSAGE_INFO_STREAM(StreamValues, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertExtended::AddAlert (Message_Report::CurrentReport(), \ + new Message_AttributeStream (StreamValues, Name, Description), PerfMeter, ParentAlert ); \ + } \ + } + +//#define DUMP_VALUE(OS, Value) \ +// { \ +// OS << Value << Message::DumpSeparator(); \ +// } +// +//#define DUMP_VALUES_COLUMNS(OS, ObjectName, ColumnCount) \ +// { \ +// OS << ObjectName << Message::DumpSeparator() << ColumnCount << Message::DumpSeparator(); \ +// } +// +//#define DUMP_VALUES(OS, Value1, Value2) \ +// { \ +// OS << Value1 << Message::DumpSeparator() << Value2 << Message::DumpSeparator(); \ +// } +// +//#define DUMP_VEC_COLOR(Values, Value) \ +// { \ +// Value = Message::ColorVectorToString (aValues); \ +// } +// +//#define DUMP_VEC_COLOR_SPLIT(Value, Values) \ +// { \ +// Message::ColorVectorFromString (Value, Values); \ +// } +// +//#define DUMP_VEC_COORD(Values, Value) \ +// { \ +// Value = Message::CoordVectorToString (aValues); \ +// } +// +//#define DUMP_VEC_COORD_SPLIT(Value, Values) \ +// { \ +// Message::CoordVectorFromString (Value, Values); \ +// } +// +// +//#define DUMP_VALUES_SPLIT(OS, ColumnCount, Values) \ +// { \ +// Message::ConvertStream (OS, aColumnCount, aValues); \ +// } + +#endif // _Message_Alerts_HeaderFile diff --git a/src/Message/Message_Attribute.cxx b/src/Message/Message_Attribute.cxx new file mode 100644 index 0000000000..b76c1cb8ed --- /dev/null +++ b/src/Message/Message_Attribute.cxx @@ -0,0 +1,30 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_Attribute::GetMessageKey () const +{ + return !myName.IsEmpty() ? myName.ToCString() : ""; +} diff --git a/src/Message/Message_Attribute.hxx b/src/Message/Message_Attribute.hxx new file mode 100644 index 0000000000..f27b332266 --- /dev/null +++ b/src/Message/Message_Attribute.hxx @@ -0,0 +1,67 @@ +// Created on: 2018-06-10 +// 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 _Message_Attribute_HeaderFile +#define _Message_Attribute_HeaderFile + +#include +#include + +DEFINE_STANDARD_HANDLE(Message_Attribute, Standard_Transient) + +//! Additional information of extended alert attribute +//! To provide other custom attribute container, it might be redefined. +class Message_Attribute : public Standard_Transient +{ +public: + //! Empty constructor + Standard_EXPORT Message_Attribute (const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()) + : myName (theName), myDescription (theDescription) {} + + //! Return a C string to be used as a key for generating text user + //! messages describing this alert. + //! The messages are generated with help of Message_Msg class, in + //! Message_Report::Dump(). + //! Base implementation returns dynamic type name of the instance. + virtual Standard_EXPORT Standard_CString GetMessageKey () const; + + //! Returns custom name of alert if it is set + //! @return alert name + const TCollection_AsciiString& GetName() const { return myName; } + + //! Sets the custom name of alert + //! @param theName a name for the alert + void SetName (const TCollection_AsciiString& theName) { myName = theName; } + + //! Sets desription of alert + //! @param theName a name for the alert + void SetDescription (const TCollection_AsciiString& theDescription) { myDescription = theDescription; } + + //! Returns description of alert if it is set + //! @return alert description + virtual const TCollection_AsciiString& GetDescription() const { return myDescription; } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient) + +private: + + TCollection_AsciiString myName; //!< alert name, if defined is used in GetMessageKey + TCollection_AsciiString myDescription; //!< alert description if defined + +}; + +#endif // _Message_Attribute_HeaderFile diff --git a/src/Message/Message_AttributeObject.cxx b/src/Message/Message_AttributeObject.cxx new file mode 100644 index 0000000000..b31ad97cd0 --- /dev/null +++ b/src/Message/Message_AttributeObject.cxx @@ -0,0 +1,32 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeObject, Message_AttributeStream) + +//======================================================================= +//function : Message_AttributeObject +//purpose : +//======================================================================= + +Message_AttributeObject::Message_AttributeObject (const Handle(Standard_Transient)& theObject, + const Standard_SStream& theStream, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_AttributeStream (theStream, theName, theDescription) +{ + myObject = theObject; +} diff --git a/src/Message/Message_AttributeObject.hxx b/src/Message/Message_AttributeObject.hxx new file mode 100644 index 0000000000..29e45e98ca --- /dev/null +++ b/src/Message/Message_AttributeObject.hxx @@ -0,0 +1,46 @@ +// Created on: 2018-06-10 +// 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 _Message_AttributeObject_HeaderFile +#define _Message_AttributeObject_HeaderFile + +#include +#include + +//! Alert object storing Transient object in its field +class Message_AttributeObject : public Message_AttributeStream +{ +public: + //! Constructor with string argument + Standard_EXPORT Message_AttributeObject (const Handle(Standard_Transient)& theObject, + const Standard_SStream& theStream, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()); + + //! Sets the object + //! @param theObject an instance + void SetObject (const Handle(Standard_Transient)& theObject) { myObject = theObject; } + + //! Returns object + Handle(Standard_Transient) GetObject() const { return myObject; } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeObject, Message_AttributeStream) + +private: + Handle(Standard_Transient) myObject; +}; + +#endif // _Message_AttributeObject_HeaderFile diff --git a/src/Message/Message_AttributeStream.cxx b/src/Message/Message_AttributeStream.cxx new file mode 100644 index 0000000000..0e4ed5f0c0 --- /dev/null +++ b/src/Message/Message_AttributeStream.cxx @@ -0,0 +1,47 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute) + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= +Message_AttributeStream::Message_AttributeStream (const Standard_SStream& theStream, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute(theName, theDescription) +{ + SetStream (theStream); +} + +//======================================================================= +//function : SetStream +//purpose : +//======================================================================= + +void Message_AttributeStream::SetStream (const Standard_SStream& theStream) +{ + TCollection_AsciiString aStreamStr (theStream.str().c_str()); + myStream << aStreamStr; +} + diff --git a/src/Message/Message_AttributeStream.hxx b/src/Message/Message_AttributeStream.hxx new file mode 100644 index 0000000000..c0a3218726 --- /dev/null +++ b/src/Message/Message_AttributeStream.hxx @@ -0,0 +1,50 @@ +// Created on: 2018-06-10 +// 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 _Message_AttributeStream_HeaderFile +#define _Message_AttributeStream_HeaderFile + +#include +#include + +#include + +class Message_PerfMeter; +class Message_Report; + +//! Alert object storing container of Standard_Real values in its field +class Message_AttributeStream : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeStream (const Standard_SStream& theStream, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()); + + //! Sets stream value + Standard_EXPORT void SetStream (const Standard_SStream& theStream); + + //! Returns stream value + const Standard_SStream& GetStream() const { return myStream; } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute) + +private: + Standard_SStream myStream; //!< container of values +}; + +#endif // _Message_AttributeStream_HeaderFile diff --git a/src/Message/Message_CompositeAlerts.cxx b/src/Message/Message_CompositeAlerts.cxx new file mode 100644 index 0000000000..bf390d424a --- /dev/null +++ b/src/Message/Message_CompositeAlerts.cxx @@ -0,0 +1,69 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_CompositeAlerts, Standard_Transient) + +//======================================================================= +//function : Merge +//purpose : +//======================================================================= + +Standard_Boolean Message_CompositeAlerts::Merge (const Handle(Message_Alert)& theTarget) +{ + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (theTarget); + if (!anExtAlert.IsNull() && !anExtAlert->GetCompositeAlerts().IsNull()) + { + Handle(Message_CompositeAlerts) anExtCompositeAlert = anExtAlert->GetCompositeAlerts(); + // hierarchical alerts can not be merged + for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + { + if (!GetAlerts ((Message_Gravity)iGravity).IsEmpty() || + !anExtCompositeAlert->GetAlerts ((Message_Gravity)iGravity).IsEmpty()) + return Standard_False; + } + } + // by default, merge trivially + return Standard_True; +} + +//======================================================================= +//function : GetAlerts +//purpose : +//======================================================================= + +Message_ListOfAlert& Message_CompositeAlerts::GetAlerts (const Message_Gravity theGravity) +{ + return myChildAlerts[theGravity]; +} + +//======================================================================= +//function : HasAlerts +//purpose : +//======================================================================= + +Standard_Boolean Message_CompositeAlerts::HasAlert (const Handle(Message_Alert)& theAlert) +{ + for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + { + Message_ListOfAlert& anAlerts = GetAlerts ((Message_Gravity)iGravity); + if (anAlerts.Contains (theAlert)) + return Standard_True; + } + return Standard_False; +} diff --git a/src/Message/Message_CompositeAlerts.hxx b/src/Message/Message_CompositeAlerts.hxx new file mode 100644 index 0000000000..f069d45836 --- /dev/null +++ b/src/Message/Message_CompositeAlerts.hxx @@ -0,0 +1,67 @@ +// Created on: 2018-06-10 +// 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 _Message_CompositeAlerts_HeaderFile +#define _Message_CompositeAlerts_HeaderFile + +#include +#include +#include +#include + +class Message_CompositeAlerts; +DEFINE_STANDARD_HANDLE(Message_CompositeAlerts, Standard_Transient) + +//! Base class of the hierarchy of classes describing various situations +//! occurring during execution of some algorithm or procedure. +//! +//! Alert should provide unique text identifier that can be used to distinguish +//! particular type of alerts, e.g. to get text message string describing it. +//! See method GetMessageKey(); by default, dynamic type name is used. +//! +//! Alert can contain some data. To avoid duplication of data, new alert +//! can be merged with another one of the same type. Method SupportsMerge() +//! should return true if merge is supported; method Merge() should do the +//! merge if possible and return true in that case and false otherwise. +//! +class Message_CompositeAlerts : public Standard_Transient +{ +public: + //! Empty constructor + Standard_EXPORT Message_CompositeAlerts () {} + + //! If possible, merge data contained in this alert to theTarget. + //! @return True if merged. + //! Base implementation always returns true. + virtual Standard_EXPORT Standard_Boolean Merge (const Handle(Message_Alert)& theTarget); + + //! Returns list of collected alerts with specified gravity + Standard_EXPORT Message_ListOfAlert& GetAlerts (const Message_Gravity theGravity); + + //! Returns true if the alert belong the list of the child alerts. + //! \param theAlert an alert to be checked as a child alert + //! \return true if the alert is found in a container of children + Standard_EXPORT Standard_Boolean HasAlert (const Handle(Message_Alert)& theAlert); + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_CompositeAlerts,Standard_Transient) + +protected: + // store messages in a lists sorted by gravity; + // here we rely on knowledge that Message_Fail is the last element of the enum + Message_ListOfAlert myChildAlerts[Message_Fail + 1]; +}; + +#endif // _Message_CompositeAlerts_HeaderFile diff --git a/src/Message/Message_PerfMeter.cxx b/src/Message/Message_PerfMeter.cxx new file mode 100644 index 0000000000..d602574afa --- /dev/null +++ b/src/Message/Message_PerfMeter.cxx @@ -0,0 +1,192 @@ +// Created on: 2018-06-10 +// 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 : Destructor +//purpose : +//======================================================================= + +Message_PerfMeter::~Message_PerfMeter() +{ + releaseAlert (0); +} + +//======================================================================= +//function : GetAlert +//purpose : +//======================================================================= + +Handle(Message_AlertExtended) Message_PerfMeter::GetAlert (const Standard_Integer theLevelId) const +{ + if (!myActiveAlerts.IsBound (theLevelId)) + return Handle(Message_AlertExtended)(); + + return myActiveAlerts.Find (theLevelId).myAlert; +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= + +void Message_PerfMeter::AddAlert (const Handle(Message_Alert)& theAlert, + const Message_PerfMeterMode theMode) +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anExtendedAlert.IsNull()) + return; + + if (myActiveAlerts.IsEmpty()) + { + setAlert (0, theAlert, theMode); + return; + } + + Standard_Integer aSize = myActiveAlerts.Size(); + // looking for the parent of the parameter alert to release the previous alert + for (Standard_Integer aLevelId = 0; aLevelId < aSize; aLevelId++) + { + Handle(Message_AlertExtended) anAlert = GetAlert (aLevelId); + Handle(Message_CompositeAlerts) aCompositeAlert = anAlert->GetCompositeAlerts(); + Standard_ASSERT_RETURN (! aCompositeAlert.IsNull(), "Any alert of the performance meter has composite and children",); + if (!aCompositeAlert->HasAlert (theAlert)) + continue; + // parent alert is found + if (myActiveAlerts.IsBound (aLevelId + 1)) + releaseAlert (aLevelId + 1); + + setAlert (aLevelId + 1, theAlert, theMode); + return; + } + Standard_Boolean isDone = Standard_True; + Standard_ASSERT_RETURN (!isDone, "Alert should be processed above",); +} + +//======================================================================= +//function : setAlert +//purpose : +//======================================================================= + +Standard_Boolean Message_PerfMeter::setAlert (const Standard_Integer theLevelId, + const Handle(Message_Alert)& theAlert, + const Message_PerfMeterMode theMode) +{ + if (!GetAlert (theLevelId).IsNull()) + return Standard_False; + + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlertExtended.IsNull()) + return Standard_False; + + myActiveAlerts.Bind (theLevelId, AlertInfo (anAlertExtended, getCurrentInfo (theMode))); + anAlertExtended->SetPerfMeter (this); + myMode = theMode; + return Standard_True; +} + +//======================================================================= +//function : releaseAlert +//purpose : +//======================================================================= + +Standard_Boolean Message_PerfMeter::releaseAlert (const Standard_Integer theLevelId) +{ + // release alerts from the tail till the given alert + for (Standard_Integer aLevelId = myActiveAlerts.Extent() - 1; aLevelId >= theLevelId; aLevelId--) + { + if (!myActiveAlerts.IsBound (aLevelId)) + continue; + stopAlert (aLevelId); + } + + return Standard_True; +} + +//======================================================================= +//function : stopAlert +//purpose : +//======================================================================= + +Standard_Boolean Message_PerfMeter::stopAlert (const Standard_Integer theLevelId) +{ + if (!myActiveAlerts.IsBound (theLevelId)) + return Standard_False; + + AlertInfo anAlertInfo = myActiveAlerts.Find (theLevelId); + Handle(Message_AlertExtended) anExtendedAlert = anAlertInfo.myAlert; + + anExtendedAlert->SetMetricValues (anAlertInfo.myStartValue, getCurrentInfo(myMode)); + anExtendedAlert->SetPerfMeter (0); + myActiveAlerts.UnBind (theLevelId); + + return Standard_True; +} + +//======================================================================= +//function : getLevel +//purpose : +//======================================================================= + +Standard_Integer Message_PerfMeter::getLevel (const Handle(Message_Alert)& theAlert) +{ + for (NCollection_DataMap::Iterator anIterator (myActiveAlerts); + anIterator.More(); anIterator.Next()) + { + if (anIterator.Value().myAlert == theAlert) + return anIterator.Key(); + } + return -1; +} + +//======================================================================= +//function : getCurrentInfo +//purpose : +//======================================================================= + +Standard_Real Message_PerfMeter::getCurrentInfo (const Message_PerfMeterMode theMode) +{ + if (theMode == Message_PerfMeterMode_UserTimeCPU || + theMode == Message_PerfMeterMode_SystemTimeInfo) + { + Standard_Real aUserSeconds, aSystemSeconds; + OSD_Chronometer::GetThreadCPU (aUserSeconds, aSystemSeconds); + return theMode == Message_PerfMeterMode_UserTimeCPU ? aUserSeconds : aSystemSeconds; + } + + OSD_MemInfo::Counter aType; + switch (theMode) + { + case Message_PerfMeterMode_MemPrivate: aType = OSD_MemInfo::MemPrivate; break; + case Message_PerfMeterMode_MemVirtual: aType = OSD_MemInfo::MemVirtual; break; + case Message_PerfMeterMode_MemWorkingSet: aType = OSD_MemInfo::MemWorkingSet; break; + case Message_PerfMeterMode_MemWorkingSetPeak: aType = OSD_MemInfo::MemWorkingSetPeak; break; + case Message_PerfMeterMode_MemSwapUsage: aType = OSD_MemInfo::MemSwapUsage; break; + case Message_PerfMeterMode_MemSwapUsagePeak: aType = OSD_MemInfo::MemSwapUsagePeak; break; + case Message_PerfMeterMode_MemHeapUsage: aType = OSD_MemInfo::MemHeapUsage; break; + default: return Message_AlertExtended::GetUndefinedMetric(); break; + } + + OSD_MemInfo aMemInfo (Standard_False); + aMemInfo.Update (aType); + return (Standard_Real)aMemInfo.ValuePreciseMiB (aType); +} diff --git a/src/Message/Message_PerfMeter.hxx b/src/Message/Message_PerfMeter.hxx new file mode 100644 index 0000000000..d9f85bd522 --- /dev/null +++ b/src/Message/Message_PerfMeter.hxx @@ -0,0 +1,97 @@ +// Created on: 2018-06-10 +// 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 _Message_PerfMeter_HeaderFile +#define _Message_PerfMeter_HeaderFile + +#include +#include +#include + +#include +#include + +//! This class is performance meter for message alerts. The usage is create the simple instance of it (not a pointer) +//! in a method. Finalizing of the method will call destructor of the meter and store time into alert. +class Message_PerfMeter +{ + +public: + //! Constructs and starts (if autoStart is true) the named meter + //! One string key is used for all alert meters. The perf meter is not started automatically, it will be done in + //! AddAlert method + Message_PerfMeter() : myGravity (Message_Info), myMode (Message_PerfMeterMode_None) {} + + //! Assures stopping upon destruction + Standard_EXPORT ~Message_PerfMeter(); + + //! Returns message alert on the level, by default the upper alert is returned + //! \param theLevelId a level of child position inside the upper alert of performance meter + //! \return alert instance or NULL + Handle(Message_AlertExtended) GetAlert (const Standard_Integer theLevelId = 0) const; + + //! Processes the parameter alert. There are some variants: + //! - current alert is NULL, the alert becomes the current one and perf meter is started + //! - last alert of the current alert is stopped (perf meter becomes NULL, time is calculated), + //! the parameter alert is started (perf meter becomes the current one) + Standard_EXPORT void AddAlert (const Handle(Message_Alert)& theAlert, + const Message_PerfMeterMode theMode); + +protected: + + //! Sets message alert on the level + //! \param theLevelId a level of child position inside the upper alert of performance meter + //! \param theAlert an alert to be stored + //! \return true if succeeded, false if there is stored alert on the given level + Standard_Boolean setAlert (const Standard_Integer theLevelId, + const Handle(Message_Alert)& theAlert, + const Message_PerfMeterMode theMode); + + //! Stop alert, store time into the alert and last child alert + //! \param theLevelId a level of child position inside the upper alert of performance meter + Standard_Boolean releaseAlert (const Standard_Integer theLevelId); + + //! Sets NULL perf meter and parameter time into the alert + //! \param theLevelId a level of child position inside the upper alert of performance meter + Standard_Boolean stopAlert (const Standard_Integer theLevelId); + + //! Returns level of given alert if it participates in the performance meter + //! \param theAlert modified alert + //! \return level value or -1 + Standard_Integer getLevel (const Handle(Message_Alert)& theAlert); + + //! Returns cumulative info of the performance meter + //! \param theMeterId a performance meter index + //! \return time value + static Standard_Real getCurrentInfo (const Message_PerfMeterMode theMode); + +protected: + //! Struct to store start time for the alert + struct AlertInfo + { + AlertInfo (const Handle(Message_AlertExtended)& theAlert, Standard_Real theStartValue) + : myAlert (theAlert), myStartValue (theStartValue) {} + + Handle(Message_AlertExtended) myAlert; //!< an alert + Standard_Real myStartValue; //!< start alert information + }; + + NCollection_DataMap myActiveAlerts; //!< container of current alerts + Message_Gravity myGravity; //!< perf meter alert gravity + Message_PerfMeterMode myMode; //!< mode to define which information to collect +}; + + +#endif // _Message_PerfMeter_HeaderFile diff --git a/src/Message/Message_PerfMeterMode.hxx b/src/Message/Message_PerfMeterMode.hxx new file mode 100644 index 0000000000..d03d5d43f9 --- /dev/null +++ b/src/Message/Message_PerfMeterMode.hxx @@ -0,0 +1,34 @@ +// Created on: 2019-08-13 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2019 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 _Message_PerfMeterMode_HeaderFile +#define _Message_PerfMeterMode_HeaderFile + +//! Specifies kind of report information to collect +enum Message_PerfMeterMode +{ + Message_PerfMeterMode_None, //!< no computation + Message_PerfMeterMode_UserTimeCPU, //!< the current CPU user time in seconds + Message_PerfMeterMode_SystemTimeInfo, //!< the current CPU system time in seconds + Message_PerfMeterMode_MemPrivate, //!< OSD_MemInfo::MemPrivate + Message_PerfMeterMode_MemVirtual, //!< OSD_MemInfo::MemVirtual + Message_PerfMeterMode_MemWorkingSet, //!< OSD_MemInfo::MemWorkingSet + Message_PerfMeterMode_MemWorkingSetPeak, //!< OSD_MemInfo::MemWorkingSetPeak + Message_PerfMeterMode_MemSwapUsage, //!< OSD_MemInfo::MemSwapUsage + Message_PerfMeterMode_MemSwapUsagePeak, //!< OSD_MemInfo::MemSwapUsagePeak + Message_PerfMeterMode_MemHeapUsage //!< OSD_MemInfo::MemHeapUsage +}; + +#endif // _Message_PerfMeterKind_HeaderFile diff --git a/src/Message/Message_Report.cxx b/src/Message/Message_Report.cxx index 07324599d2..344c7fbf04 100644 --- a/src/Message/Message_Report.cxx +++ b/src/Message/Message_Report.cxx @@ -14,19 +14,42 @@ // commercial license or contractual agreement. #include + +#include +#include #include #include +#include +#include + #include +#include IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) +static Handle(Message_Report) MyReport; + //======================================================================= //function : Message_Report //purpose : //======================================================================= Message_Report::Message_Report () +: myPerfMeterMode (Message_PerfMeterMode_None), myLimit (-1) +{ + SetActive (Standard_True); +} + +//======================================================================= +//function : CurrentReport +//purpose : +//======================================================================= +Handle(Message_Report) Message_Report::CurrentReport(const Standard_Boolean theToCreate) { + if (MyReport.IsNull() && theToCreate) + MyReport = new Message_Report(); + + return MyReport; } //======================================================================= @@ -36,6 +59,9 @@ Message_Report::Message_Report () void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert) { + if (!IsActive (theGravity)) + return; + Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert",); Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), "Adding alert with gravity not in valid range",); @@ -58,6 +84,63 @@ void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_ // if not merged, just add to the list aList.Append (theAlert); + + if (!myCallBack.IsNull()) + myCallBack->Update (theAlert); +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= + +void Message_Report::AddAlert (const Message_Gravity theGravity, const Handle(Message_Alert)& theAlert, + Message_PerfMeter* thePerfMeter, const Handle(Message_Alert)& theParentAlert) +{ + if (!IsActive (theGravity)) + return; + + Standard_ASSERT_RETURN (!theAlert.IsNull(), "Attempt to add null alert",); + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Adding alert with gravity not in valid range",); + + Standard_Mutex::Sentry aSentry (myMutex); + + // iterate by already recorded alerts and try to merge new one with one of those + Handle(Message_Alert) aParentAlert = theParentAlert; + if (aParentAlert.IsNull() && thePerfMeter) + aParentAlert = thePerfMeter->GetAlert(); + if (aParentAlert.IsNull()) + aParentAlert = getLastAlertInPerfMeter(theGravity); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(aParentAlert); + Handle(Message_CompositeAlerts) aCompositeAlert = !anExtendedAlert.IsNull() ? anExtendedAlert->GetCompositeAlerts (Standard_True) + : Handle(Message_CompositeAlerts)(); + Message_ListOfAlert& aList = !aCompositeAlert.IsNull() ? aCompositeAlert->GetAlerts (theGravity) : myAlerts[theGravity]; + + if (theAlert->SupportsMerge() && !aList.IsEmpty()) + { + // merge is performed only for alerts of exactly same type and same name + const Handle(Standard_Type)& aType = theAlert->DynamicType(); + for (Message_ListOfAlert::Iterator anIt(aList); anIt.More(); anIt.Next()) + { + // if merged successfully, just return + if (aType == anIt.Value()->DynamicType() && theAlert->Merge (anIt.Value())) + return; + } + } + + // if not merged, just add to the list + aList.Append (theAlert); + // remove alerts under the report only + if (theParentAlert.IsNull() && aParentAlert.IsNull() && myLimit > 0 && aList.Extent() > myLimit) + aList.RemoveFirst(); + + if (thePerfMeter) + thePerfMeter->AddAlert (theAlert, PerfMeterMode()); + + if (!myCallBack.IsNull()) + myCallBack->Update(theAlert); } //======================================================================= @@ -73,6 +156,156 @@ const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity return myAlerts[theGravity]; } +//======================================================================= +//function : CumulativeMetric +//purpose : +//======================================================================= + +Standard_Real Message_Report::CumulativeMetric (const Message_Gravity theGravity) const +{ + switch (myPerfMeterMode) + { + case Message_PerfMeterMode_None: return 0.0; + case Message_PerfMeterMode_UserTimeCPU: + case Message_PerfMeterMode_SystemTimeInfo: + { + Standard_Real aStartTime = Message_AlertExtended::GetUndefinedMetric(); + Standard_Boolean isFound = Standard_False; + for (Message_ListOfAlert::Iterator anAlertsIt (GetAlerts (theGravity)); anAlertsIt.More(); anAlertsIt.Next()) + { + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlertsIt.Value()); + if (anExtendedAlert.IsNull() && anExtendedAlert->IsMetricValid()) + { + aStartTime = anExtendedAlert->MetricStart(); + isFound = Standard_True; + break; + } + } + if (!isFound) + return 0.0; + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(getLastAlert (theGravity)); + if (anExtendedAlert.IsNull() || !anExtendedAlert->IsMetricValid()) + return 0.0; + + return anExtendedAlert->MetricStop() - aStartTime; + } + case Message_PerfMeterMode_MemPrivate: + case Message_PerfMeterMode_MemVirtual: + case Message_PerfMeterMode_MemWorkingSet: + { + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(getLastAlert (theGravity)); + if (!anExtendedAlert.IsNull()) + return anExtendedAlert->MetricStop(); + } + } + return 0.0; +} + +//======================================================================= +//function : getLastAlert +//purpose : +//======================================================================= + +Handle(Message_Alert) Message_Report::getLastAlert (const Message_Gravity theGravity) const +{ + if (!IsActive (theGravity)) + return Handle(Message_Alert)(); + + const Message_ListOfAlert& anAlerts = GetAlerts (theGravity); + if (anAlerts.IsEmpty()) + return Handle(Message_Alert)(); + + Handle(Message_Alert) aLastAlert = anAlerts.Last(); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (aLastAlert); + if (anExtendedAlert.IsNull()) + return aLastAlert; + Handle(Message_CompositeAlerts) aCompositeAlert = anExtendedAlert->GetCompositeAlerts (Standard_True); + if (aCompositeAlert.IsNull()) + return aLastAlert; + + while (!aCompositeAlert.IsNull() && !aCompositeAlert->GetAlerts (theGravity).IsEmpty()) + { + Handle(Message_Alert) anAlert = aCompositeAlert->GetAlerts (theGravity).Last(); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anAlert); + if (anExtendedAlert.IsNull()) + { + aLastAlert = anAlert; + break; + } + + aLastAlert = anExtendedAlert; + aCompositeAlert = anExtendedAlert->GetCompositeAlerts(); + } + + // if alert has perf meter, use as the last alert, an alert of the perf meter + anExtendedAlert = Handle(Message_AlertExtended)::DownCast (aLastAlert); + if (anExtendedAlert.IsNull()) + return aLastAlert; + + return aLastAlert; +} + +//======================================================================= +//function : getLastAlertInPerfMeter +//purpose : +//======================================================================= + +Handle(Message_Alert) Message_Report::getLastAlertInPerfMeter (const Message_Gravity theGravity) const +{ + if (!IsActive (theGravity)) + return Handle(Message_Alert)(); + + const Message_ListOfAlert& anAlerts = GetAlerts (theGravity); + if (anAlerts.IsEmpty()) + return Handle(Message_Alert)(); + + Handle(Message_Alert) aLastAlert = anAlerts.Last(); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (aLastAlert); + if (anExtendedAlert.IsNull()) + return aLastAlert; + Handle(Message_CompositeAlerts) aCompositeAlert = anExtendedAlert->GetCompositeAlerts (Standard_True); + if (aCompositeAlert.IsNull()) + return aLastAlert; + + Standard_Boolean aHasPerfMeter = anExtendedAlert->GetPerfMeter() != NULL; + if (!aHasPerfMeter) // the alert has finished and is not the last alert anymore + return Handle(Message_Alert)(); + + while (!aCompositeAlert.IsNull() && !aCompositeAlert->GetAlerts (theGravity).IsEmpty()) + { + Handle(Message_Alert) anAlert = aCompositeAlert->GetAlerts (theGravity).Last(); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anAlert); + if (anExtendedAlert.IsNull()) + { + if (!aHasPerfMeter) // if there is a perf meter, use alert of it + aLastAlert = anAlert; + break; + } + + if (!aHasPerfMeter) + aHasPerfMeter = anExtendedAlert->GetPerfMeter() != NULL; + else if (!anExtendedAlert->GetPerfMeter()) + break; // last alert is the previous alert where perf meter is not NULL + + aLastAlert = anExtendedAlert; + aCompositeAlert = anExtendedAlert->GetCompositeAlerts(); + } + + // if alert has perf meter, use as the last alert, an alert of the perf meter + anExtendedAlert = Handle(Message_AlertExtended)::DownCast (aLastAlert); + if (anExtendedAlert.IsNull()) + return aLastAlert; + //if (anExtendedAlert->GetPerfMeter()) + // aLastAlert = anExtendedAlert->GetPerfMeter()->GetAlert(); + + return aLastAlert; +} + //======================================================================= //function : HasAlert //purpose : @@ -248,3 +481,22 @@ void Message_Report::Merge (const Handle(Message_Report)& theOther, Message_Grav AddAlert (theGravity, anIt.Value()); } } + +//======================================================================= +//function : SetActive +//purpose : +//======================================================================= + +void Message_Report::SetActive (const Standard_Boolean theActive, const Standard_Integer theGravity) +{ + if (theGravity < 0) + { + for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + SetActive (theActive, iGravity); + return; + } + + Standard_ASSERT_RETURN (theGravity >= 0 && size_t (theGravity) < sizeof (myAlerts) / sizeof (myAlerts[0]), + "Set active report with gravity not in valid range", ); + myIsActive[theGravity] = theActive; +} diff --git a/src/Message/Message_Report.hxx b/src/Message/Message_Report.hxx index 8440ba8149..b8c1df512b 100644 --- a/src/Message/Message_Report.hxx +++ b/src/Message/Message_Report.hxx @@ -18,12 +18,15 @@ #include #include +#include #include class Message_Messenger; - +class Message_PerfMeter; class Message_Report; -DEFINE_STANDARD_HANDLE(Message_Report, MMgt_TShared) +class Message_ReportCallBack; + +DEFINE_STANDARD_HANDLE(Message_Report, Standard_Transient) //! Container for alert messages, sorted according to their gravity. //! @@ -54,10 +57,24 @@ public: //! Empty constructor Standard_EXPORT Message_Report (); + //! returns the only one instance of Report + //! When theToCreate is true - automatically creates message report when not exist. + //! that has been created. + Standard_EXPORT static Handle(Message_Report) CurrentReport (const Standard_Boolean theToCreate = Standard_False); + //! Add alert with specified gravity. //! This method is thread-safe, i.e. alerts can be added from parallel threads safely. Standard_EXPORT void AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert); + //! Add alert with specified gravity. The alert is a sub-alert of report or another alert + //! The parent alert is the parameter alert or the last alert if found else report. + //! \param theGravity a message gravity + //! \param theAlert a new alert to be added + //! \param thePerfMeter performance meter calculates the alert spent time and participate in searching the last alert if needed + //! \param theParentAlert if not NULL specifies parent alert where the alert should be placed, if the parent is an extednded alert + Standard_EXPORT void AddAlert (const Message_Gravity theGravity, const Handle(Message_Alert)& theAlert, + Message_PerfMeter* thePerfMeter, const Handle(Message_Alert)& theParentAlert = Handle(Message_Alert)()); + //! Returns list of collected alerts with specified gravity Standard_EXPORT const Message_ListOfAlert& GetAlerts (Message_Gravity theGravity) const; @@ -94,15 +111,70 @@ public: //! Merges alerts with specified gravity from theOther report into this Standard_EXPORT void Merge (const Handle(Message_Report)& theOther, Message_Gravity theGravity); + //! Returns a state whether the report is active + //! \return the state + Standard_Boolean IsActive (const Message_Gravity theGravity) const { return myIsActive[theGravity]; } + + //! Starts a timer to compute time between messages. If a timer has already been started, it will be stopped + //! \param theActive new state of report active + //! \param theGravity gravity type, if '-1', apply value for all gravity kinds + Standard_EXPORT void SetActive (const Standard_Boolean theActive, const Standard_Integer theGravity = -1); + + //! Sets a perf meter mode + //! \param theMode new mode + Standard_EXPORT void SetPerfMeterMode (const Message_PerfMeterMode theMode) + { myPerfMeterMode = theMode; } + + //! Returns mode of perf meter + //! \return the state + Standard_EXPORT Message_PerfMeterMode PerfMeterMode() const + { return myPerfMeterMode; } + + //! Returns maximum number of collecting alerts. If the limit is achieved, + //! adding of a new alert after removing the first cached alert. + //! \return the limit value + Standard_EXPORT Standard_Integer GetLimit() const { return myLimit; } + + //! Sets maximum number of collecting alerts. + //! \return theLimit limit value + Standard_EXPORT void SetLimit(const Standard_Integer theLimit) { myLimit = theLimit; } + + //! Returns the report cumulative metric. It includes time/mem of sub alerts depending on PerfMeter mode + //! @return value + Standard_EXPORT Standard_Real CumulativeMetric (const Message_Gravity theGravity) const; + + //! Sets a listener for the report events + void SetCallBack(const Handle(Message_ReportCallBack)& theCallBack) { myCallBack = theCallBack; } + + //! Returns listener of the reports events + const Handle(Message_ReportCallBack)& GetCallBack() const { return myCallBack; } + // OCCT RTTI DEFINE_STANDARD_RTTIEXT(Message_Report,Standard_Transient) +protected: + //! Returns last alert in list of report alerts or last alert in hierarchical tree of alerts provided by + //! the last alert + //! \parm theGravity a message gravity + Standard_EXPORT Handle(Message_Alert) getLastAlert (const Message_Gravity theGravity) const; + + //! Returns last alert in list of report alerts or last alert in hierarchical tree of alerts provided by + //! the last alert + //! \parm theGravity a message gravity + Standard_EXPORT Handle(Message_Alert) getLastAlertInPerfMeter (const Message_Gravity theGravity) const; + protected: Standard_Mutex myMutex; // store messages in a lists sorted by gravity; // here we rely on knowledge that Message_Fail is the last element of the enum Message_ListOfAlert myAlerts[Message_Fail + 1]; + + Standard_Boolean myIsActive[Message_Fail + 1]; + Message_PerfMeterMode myPerfMeterMode; //! If true, each alert will store the mode information + Standard_Integer myLimit; //! Maximum number of collected alerts + + Handle(Message_ReportCallBack) myCallBack; //! signal about performed modifications }; #endif // _Message_Report_HeaderFile diff --git a/src/Message/Message_ReportCallBack.cxx b/src/Message/Message_ReportCallBack.cxx new file mode 100644 index 0000000000..5f0ce64327 --- /dev/null +++ b/src/Message/Message_ReportCallBack.cxx @@ -0,0 +1,22 @@ +// Created on: 2017-12-01 +// 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 "Message_ReportCallBack.hxx" + +IMPLEMENT_STANDARD_RTTIEXT(Message_ReportCallBack, Standard_Transient) + +Message_ReportCallBack::Message_ReportCallBack () +{ +} diff --git a/src/Message/Message_ReportCallBack.hxx b/src/Message/Message_ReportCallBack.hxx new file mode 100644 index 0000000000..884b64dcaf --- /dev/null +++ b/src/Message/Message_ReportCallBack.hxx @@ -0,0 +1,44 @@ +// Created on: 2017-12-01 +// 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 _Message_ReportCallBack_HeaderFile +#define _Message_ReportCallBack_HeaderFile + +#include +#include +#include + +class Message_Alert; +class Message_ReportCallBack; +DEFINE_STANDARD_HANDLE(Message_ReportCallBack, Standard_Transient) + +//! Interface to have possibility of processing message report events. +class Message_ReportCallBack : public Standard_Transient +{ +public: + + //! Empty constructor + Standard_EXPORT Message_ReportCallBack (); + ~Message_ReportCallBack () {} + + //! Interface to be implemented in the child to process the message report event + //! \param theAlert created or modified message alert + virtual void Update(const Handle(Message_Alert)& theAlert) = 0; + + //! OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_ReportCallBack, Standard_Transient) +}; + +#endif // _Message_ReportCallBack_HeaderFile diff --git a/src/NCollection/NCollection_Mat4.hxx b/src/NCollection/NCollection_Mat4.hxx index c0ea4fefdd..fe60eff1b6 100755 --- a/src/NCollection/NCollection_Mat4.hxx +++ b/src/NCollection/NCollection_Mat4.hxx @@ -17,6 +17,8 @@ #define _NCollection_Mat4_HeaderFile #include +#include +#include //! Generic matrix of 4 x 4 elements. //! To be used in conjunction with NCollection_Vec4 entities. @@ -461,6 +463,18 @@ public: return *reinterpret_cast*> (theData); } + //! Dumps the content of me into the stream + Standard_EXPORT void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const + { + OCCT_DUMP_CLASS_BEGIN (theOStream, NCollection_Mat4); + + OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "CornerMin", 16, + myMat[0], myMat[1], myMat[2], myMat[3], + myMat[4], myMat[5], myMat[6], myMat[7], + myMat[8], myMat[9], myMat[10], myMat[11], + myMat[12], myMat[13], myMat[14], myMat[15]) + } + private: Element_t myMat[16]; diff --git a/src/OSD/OSD_MemInfo.cxx b/src/OSD/OSD_MemInfo.cxx index 277804e203..6651c8f2b1 100644 --- a/src/OSD/OSD_MemInfo.cxx +++ b/src/OSD/OSD_MemInfo.cxx @@ -186,6 +186,145 @@ void OSD_MemInfo::Update() #endif } +// ======================================================================= +// function : Update +// purpose : +// ======================================================================= +void OSD_MemInfo::Update (const OSD_MemInfo::Counter theCounter) +{ +#ifndef OCCT_UWP +#if defined(_WIN32) + + if (theCounter == MemVirtual) + { + #if (_WIN32_WINNT >= 0x0500) + MEMORYSTATUSEX aStatEx; + aStatEx.dwLength = sizeof(aStatEx); + GlobalMemoryStatusEx (&aStatEx); + myCounters[MemVirtual] = Standard_Size(aStatEx.ullTotalVirtual - aStatEx.ullAvailVirtual); + #else + MEMORYSTATUS aStat; + aStat.dwLength = sizeof(aStat); + GlobalMemoryStatus (&aStat); + myCounters[MemVirtual] = Standard_Size(aStat.dwTotalVirtual - aStat.dwAvailVirtual); + #endif + + return; + } + + if (theCounter == MemPrivate || + theCounter == MemWorkingSet || + theCounter == MemWorkingSetPeak || + theCounter == MemSwapUsage || + theCounter == MemSwapUsagePeak) + { + // use Psapi library + HANDLE aProcess = GetCurrentProcess(); + #if (_WIN32_WINNT >= 0x0501) + PROCESS_MEMORY_COUNTERS_EX aProcMemCnts; + #else + PROCESS_MEMORY_COUNTERS aProcMemCnts; + #endif + if (GetProcessMemoryInfo (aProcess, (PROCESS_MEMORY_COUNTERS* )&aProcMemCnts, sizeof(aProcMemCnts))) + { + #if (_WIN32_WINNT >= 0x0501) + myCounters[MemPrivate] = aProcMemCnts.PrivateUsage; + #endif + myCounters[MemWorkingSet] = aProcMemCnts.WorkingSetSize; + myCounters[MemWorkingSetPeak] = aProcMemCnts.PeakWorkingSetSize; + myCounters[MemSwapUsage] = aProcMemCnts.PagefileUsage; + myCounters[MemSwapUsagePeak] = aProcMemCnts.PeakPagefileUsage; + } + return; + } + + if (theCounter == MemHeapUsage) + { + _HEAPINFO hinfo; + int heapstatus; + hinfo._pentry = NULL; + + myCounters[MemHeapUsage] = 0; + while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) + { + if(hinfo._useflag == _USEDENTRY) + myCounters[MemHeapUsage] += hinfo._size; + } + return; + } + +#elif (defined(__linux__) || defined(__linux)) +/* + // use procfs on Linux + char aBuff[4096]; + snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid()); + std::ifstream aFile; + aFile.open (aBuff); + if (!aFile.is_open()) + { + return; + } + + while (!aFile.eof()) + { + memset (aBuff, 0, sizeof(aBuff)); + aFile.getline (aBuff, 4096); + if (aBuff[0] == '\0') + { + continue; + } + + if (strncmp (aBuff, "VmSize:", strlen ("VmSize:")) == 0) + { + myCounters[MemVirtual] = atol (aBuff + strlen ("VmSize:")) * 1024; + } + //else if (strncmp (aBuff, "VmPeak:", strlen ("VmPeak:")) == 0) + // myVirtualPeak = atol (aBuff + strlen ("VmPeak:")) * 1024; + else if (strncmp (aBuff, "VmRSS:", strlen ("VmRSS:")) == 0) + { + myCounters[MemWorkingSet] = atol (aBuff + strlen ("VmRSS:")) * 1024; // RSS - resident set size + } + else if (strncmp (aBuff, "VmHWM:", strlen ("VmHWM:")) == 0) + { + myCounters[MemWorkingSetPeak] = atol (aBuff + strlen ("VmHWM:")) * 1024; // HWM - high water mark + } + else if (strncmp (aBuff, "VmData:", strlen ("VmData:")) == 0) + { + if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate]; + myCounters[MemPrivate] += atol (aBuff + strlen ("VmData:")) * 1024; + } + else if (strncmp (aBuff, "VmStk:", strlen ("VmStk:")) == 0) + { + if (myCounters[MemPrivate] == Standard_Size(-1)) ++myCounters[MemPrivate]; + myCounters[MemPrivate] += atol (aBuff + strlen ("VmStk:")) * 1024; + } + } + aFile.close(); + + struct mallinfo aMI = mallinfo(); + myCounters[MemHeapUsage] = aMI.uordblks; + +#elif (defined(__APPLE__)) + struct task_basic_info aTaskInfo; + mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT; + if (task_info (mach_task_self(), TASK_BASIC_INFO, + (task_info_t )&aTaskInfo, &aTaskInfoCount) == KERN_SUCCESS) + { + // On Mac OS X, these values in bytes, not pages! + myCounters[MemVirtual] = aTaskInfo.virtual_size; + myCounters[MemWorkingSet] = aTaskInfo.resident_size; + + //Getting malloc statistics + malloc_statistics_t aStats; + malloc_zone_statistics (NULL, &aStats); + + myCounters[MemHeapUsage] = aStats.size_in_use; + } +*/ +#endif +#endif +} + // ======================================================================= // function : ToString // purpose : diff --git a/src/OSD/OSD_MemInfo.hxx b/src/OSD/OSD_MemInfo.hxx index f06d5d05a1..71c0c9a1ea 100644 --- a/src/OSD/OSD_MemInfo.hxx +++ b/src/OSD/OSD_MemInfo.hxx @@ -74,6 +74,9 @@ public: //! Update counters Standard_EXPORT void Update(); + //! Update counter of specified counter + Standard_EXPORT void Update (const OSD_MemInfo::Counter theCounter); + //! Return the string representation for all available counter. Standard_EXPORT TCollection_AsciiString ToString() const; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index ef69f45426..e23f3d83c8 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -4038,3 +4038,16 @@ bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable) myAlphaToCoverage = toEnable; return anOldValue; } + +// ======================================================================= +// function : DumpJson +// purpose : +// ======================================================================= +void OpenGl_Context::DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth) const +{ + OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_Context); + + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ModelWorldState); + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &WorldViewState); + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &ProjectionState); +} diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 1b70d37f37..b6e2df52ce 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -851,6 +851,9 @@ public: //! @name methods to alter or retrieve current state //! Return Graphics Driver's vendor. const TCollection_AsciiString& Vendor() const { return myVendor; } + //! Dumps the content of me into the stream + Standard_EXPORT void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const; + private: //! Wrapper to system function to retrieve GL function pointer by name. diff --git a/src/OpenGl/OpenGl_MatrixState.hxx b/src/OpenGl/OpenGl_MatrixState.hxx index 00f16d0d09..1104cfda6b 100644 --- a/src/OpenGl/OpenGl_MatrixState.hxx +++ b/src/OpenGl/OpenGl_MatrixState.hxx @@ -18,6 +18,7 @@ #include #include +#include //! Software implementation for OpenGL matrix stack. template @@ -84,6 +85,17 @@ public: myCurrent = typename OpenGl::MatrixType::Mat4(); } + //! Dumps the content of me into the stream + Standard_EXPORT void DumpJson (Standard_OStream& theOStream, const Standard_Integer theDepth = -1) const + { + OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_MatrixState); + + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myStack.Size()) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myStackHead) + + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myCurrent); + } + private: NCollection_Vector::Mat4> myStack; //!< Collection used to maintenance matrix stack diff --git a/src/TopoDS/FILES b/src/TopoDS/FILES index 8e17f304b6..27345a189f 100644 --- a/src/TopoDS/FILES +++ b/src/TopoDS/FILES @@ -1,5 +1,7 @@ TopoDS.hxx TopoDS.lxx +TopoDS_AlertAttribute.hxx +TopoDS_AlertAttribute.cxx TopoDS_Builder.cxx TopoDS_Builder.hxx TopoDS_Builder.lxx diff --git a/src/TopoDS/TopoDS_AlertAttribute.cxx b/src/TopoDS/TopoDS_AlertAttribute.cxx new file mode 100644 index 0000000000..aac6e489af --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.cxx @@ -0,0 +1,37 @@ +// Created on: 2018-06-10 +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute) + +//======================================================================= +//function : TopoDS_AlertAttribute +//purpose : +//======================================================================= + + +TopoDS_AlertAttribute::TopoDS_AlertAttribute (const TopoDS_Shape& theShape, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_AttributeStream (Standard_SStream(), theName, theDescription), myShape (theShape) +{ + Standard_SStream aStream; + theShape.DumpJson (aStream); + + SetStream (aStream); +} diff --git a/src/TopoDS/TopoDS_AlertAttribute.hxx b/src/TopoDS/TopoDS_AlertAttribute.hxx new file mode 100644 index 0000000000..ea347944e7 --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.hxx @@ -0,0 +1,51 @@ +// Created on: 2018-06-10 +// 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 _TopoDS_AlertAttribute_HeaderFile +#define _TopoDS_AlertAttribute_HeaderFile + +#include +#include + +//! Alert attributre object storing TopoDS shape in its field +class TopoDS_AlertAttribute : public Message_AttributeStream +{ +public: + //! Constructor with shape argument + Standard_EXPORT TopoDS_AlertAttribute (const TopoDS_Shape& theShape, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()); + + //! Returns contained shape + const TopoDS_Shape& GetShape() const { return myShape; } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_AttributeStream) + +private: + TopoDS_Shape myShape; +}; + +#define MESSAGE_INFO_SHAPE(Shape, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertExtended::AddAlert (Message_Report::CurrentReport(), \ + new TopoDS_AlertAttribute (Shape, Name, Description), PerfMeter, ParentAlert); \ + } \ + } + +#endif // _TopoDS_AlertAttribute_HeaderFile diff --git a/src/XmlDrivers/FILES b/src/XmlDrivers/FILES index 058b8acc20..d4a93d94ff 100644 --- a/src/XmlDrivers/FILES +++ b/src/XmlDrivers/FILES @@ -4,3 +4,5 @@ XmlDrivers_DocumentRetrievalDriver.cxx XmlDrivers_DocumentRetrievalDriver.hxx XmlDrivers_DocumentStorageDriver.cxx XmlDrivers_DocumentStorageDriver.hxx +XmlDrivers_MessageReportStorage.cxx +XmlDrivers_MessageReportStorage.hxx diff --git a/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx new file mode 100644 index 0000000000..b6a5696f63 --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx @@ -0,0 +1,347 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2001-2014 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 + +// ======================================================================= +// function : GetApplication +// purpose : +// ======================================================================= + +const Handle(TDocStd_Application)& GetApplication() +{ + static Handle(TDocStd_Application) anApp; + if (anApp.IsNull()) + { + anApp = new TDocStd_Application; + XmlDrivers::DefineFormat (anApp); + } + return anApp; +} + +// ======================================================================= +// function : ExportReport +// purpose : +// ======================================================================= + +void XmlDrivers_MessageReportStorage::ExportReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theFileName) +{ + if (theReport.IsNull()) + return; + + Handle(TDocStd_Document) aDocument; + GetApplication()->NewDocument (TCollection_ExtendedString ("XmlOcaf"), aDocument); + + TDF_Label aMainLabel = aDocument->Main(); + + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + Message_Gravity aGravity = (Message_Gravity)aGravityId; + + if (theReport->GetAlerts (aGravity).Size() == 0) + continue; + // Gravity Label + TDF_Label aGravityLabel = aMainLabel.NewChild(); + // set gravity kind string + TCollection_ExtendedString aName (Message::GravityToString ((Message_Gravity)aGravity)); + if (!aName.IsEmpty()) + TDataStd_Name::Set (aGravityLabel, aName); + + /// reserved label to store gravity information + //TDF_Label aFirstAlertLabel = aGravityLabel.NewChild(); + + // Alert Labels: labels are started from the second index + const Message_ListOfAlert& anAlerts = theReport->GetAlerts (aGravity); + for (Message_ListOfAlert::Iterator anAlertsIt (anAlerts); anAlertsIt.More(); anAlertsIt.Next()) + { + exportAlert (anAlertsIt.Value(), aGravityLabel); + } + } + GetApplication()->SaveAs (aDocument, theFileName); +} + +// ======================================================================= +// function : ImportReport +// purpose : +// ======================================================================= + +Handle(Message_Report) XmlDrivers_MessageReportStorage::ImportReport (const TCollection_AsciiString& theFileName) +{ + Handle(TDocStd_Application) anApplication = GetApplication(); + Standard_Integer aDocumentId = anApplication->IsInSession (theFileName); + if (aDocumentId > 0) + { + Handle(TDocStd_Document) aDocument; + anApplication->GetDocument (aDocumentId, aDocument); + anApplication->Close (aDocument); + } + + Handle(TDocStd_Document) aDocument; + GetApplication()->Open (theFileName, aDocument); + if (aDocument.IsNull()) + return Handle(Message_Report)(); + + TDF_Label aMainLabel = aDocument->Main(); + if (aMainLabel.IsNull()) + return Handle(Message_Report)(); + + TDF_Label aLabel; + Handle(Message_Report) aReport = new Message_Report(); + for (TDF_ChildIterator aLabelsIt(aMainLabel); aLabelsIt.More(); aLabelsIt.Next()) + { + TDF_Label aGravityLabel = aLabelsIt.Value(); + if (aGravityLabel.IsNull()) + continue; + Handle(TDF_Attribute) anAttribute; + if (!aGravityLabel.FindAttribute (TDataStd_Name::GetID(), anAttribute)) + continue; + Handle(TDataStd_Name) aNameAttribute = Handle(TDataStd_Name)::DownCast (anAttribute); + if (aNameAttribute.IsNull()) + continue; + + // get gravity type + const TCollection_ExtendedString& aGravityName = aNameAttribute->Get(); + Message_Gravity aGravity = Message::GravityFromString (TCollection_AsciiString (aGravityName).ToCString()); + + /// reserved label to store gravity information + //TDF_Label aFirstAlertLabel = aGravityLabel.FindChild (1, Standard_False); + + // find alerts information, add corresponded alerts to the report + for (TDF_ChildIterator anAlertLabelsIt (aGravityLabel); anAlertLabelsIt.More(); anAlertLabelsIt.Next()) + { + TDF_Label anAlertLabel = anAlertLabelsIt.Value(); + if (anAlertLabel.IsNull()) + continue; + + importAlert (anAlertLabel, aGravity, aReport, Handle(Message_Alert)()); + } + } + return aReport; +} + +// ======================================================================= +// function : exportAlert +// purpose : +// ======================================================================= + +void XmlDrivers_MessageReportStorage::exportAlert (const Handle(Message_Alert)& theAlert, const TDF_Label& theParentLabel) +{ + TDF_Label anAlertLabel = theParentLabel.NewChild(); + TDataStd_Name::Set (anAlertLabel, theAlert->DynamicType()->Name()); + + /// reserved label to store parameters of the current label + TDF_Label anAlertParmetersLabel = anAlertLabel.NewChild(); + exportAlertParameters (theAlert, anAlertParmetersLabel); + + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + // Gravity Label + TDF_Label aGravityLabel = anAlertLabel.NewChild(); + // set gravity kind string + TDataStd_Name::Set (aGravityLabel, Message::GravityToString ((Message_Gravity)aGravityId)); + + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlertExtended.IsNull()) + continue; + Handle(Message_CompositeAlerts) aComposite = anAlertExtended->GetCompositeAlerts(); + if (aComposite.IsNull()) + continue; + + const Message_ListOfAlert& anAlerts = aComposite->GetAlerts ((Message_Gravity)aGravityId); + for (Message_ListOfAlert::Iterator anAlertsIt (anAlerts); anAlertsIt.More(); anAlertsIt.Next()) + exportAlert (anAlertsIt.Value(), aGravityLabel); + } +} + +// ======================================================================= +// function : importAlert +// purpose : +// ======================================================================= + +void XmlDrivers_MessageReportStorage::importAlert (const TDF_Label& theAlertLabel, + const Message_Gravity theGravity, + Handle(Message_Report)& theReport, + const Handle(Message_Alert)& theParentAlert) +{ + TDF_Label aParametersLabel = theAlertLabel.FindChild (1, Standard_False); + Handle(Message_Alert) anAlert = importAlertParameters (aParametersLabel); + if (anAlert.IsNull()) + return; + + TDF_Label aLabel; + TDF_ChildIterator aSubAlertsLabelsIt (theAlertLabel); + aSubAlertsLabelsIt.Next(); // do not processing the first (parameters) label + for (; aSubAlertsLabelsIt.More(); aSubAlertsLabelsIt.Next()) + { + TDF_Label aGravityLabel = aSubAlertsLabelsIt.Value(); + if (aGravityLabel.IsNull()) + continue; + Handle(TDF_Attribute) anAttribute; + if (!aGravityLabel.FindAttribute (TDataStd_Name::GetID(), anAttribute)) + continue; + Handle(TDataStd_Name) aNameAttribute = Handle(TDataStd_Name)::DownCast (anAttribute); + if (aNameAttribute.IsNull()) + continue; + + // get gravity type + Message_Gravity aGravity = Message::GravityFromString (TCollection_AsciiString (aNameAttribute->Get()).ToCString()); + // find alerts information, add corresponded alerts to the report + for (TDF_ChildIterator anAlertLabelsIt (aGravityLabel); anAlertLabelsIt.More(); anAlertLabelsIt.Next()) + { + TDF_Label anAlertLabel = anAlertLabelsIt.Value(); + if (anAlertLabel.IsNull()) + continue; + + importAlert (anAlertLabel, aGravity, theReport, anAlert); + } + } + theReport->AddAlert (theGravity, anAlert, 0, theParentAlert); +} + +// ======================================================================= +// function : exportAlertParameters +// purpose : +// ======================================================================= +void XmlDrivers_MessageReportStorage::exportAlertParameters (const Handle(Message_Alert)& theAlert, const TDF_Label& theAlertLabel) +{ + //Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + //if (anAlertExtended.IsNull()) // name attribute is empty + // return; + + //// store attribute time + //Handle(Message_Attribute) anAttribute = anAlertExtended->Attribute(); + + //TDataStd_Name::Set (theAlertLabel, anAttribute->DynamicType()->Name()); + ////TDataStd_Real::Set (theAlertLabel, anAlertExtended->CumulativeMetric()); + + //TDataStd_AsciiString::Set (theAlertLabel, anAttribute->GetName()); + //TCollection_AsciiString aDescription = anAttribute->GetDescription(); + //if (!aDescription.IsEmpty()) + // TDataStd_Comment::Set (theAlertLabel, anAttribute->GetDescription()); + + //Standard_CString aDynamicTypeName = anAttribute->DynamicType()->Name(); + //if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeStream)->Name()) + //{ + // Handle(Message_AttributeStream) aValuesArrayAlert = Handle(Message_AttributeStream)::DownCast (anAttribute); + // // store values + // NCollection_IndexedDataMap aValues; + // TCollection_AsciiString aKey; + // TCollection::Split (aValuesArrayAlert->GetStream(), aValues, aKey); + // if (aValues.IsEmpty()) + // return; + // int anArraySize = 2 * aValues.Size(); + // Handle(TDataStd_ExtStringArray) aListAttribute = TDataStd_ExtStringArray::Set (theAlertLabel, 0, anArraySize - 1); + // for (int aValueId = 0; aValueId < anArraySize; aValueId++) + // { + // TCollection_AsciiString aKey = aValues.FindKey (aValueId); + // aListAttribute->SetValue (aValueId * 2, aKey); + // aListAttribute->SetValue (aValueId * 2 + 1, aValues.FindFromKey (aKey)); + // } + //} +} + +// ======================================================================= +// function : importAlertParameters +// purpose : +// ======================================================================= +Handle(Message_Alert) XmlDrivers_MessageReportStorage::importAlertParameters (const TDF_Label& aParametersLabel) +{ + //Handle(TDF_Attribute) anAttribute; + //if (!aParametersLabel.FindAttribute (TDataStd_Name::GetID(), anAttribute)) + // return Handle(Message_Alert)(); + + //Handle(TDataStd_Name) aDynamicTypeAttribute = Handle(TDataStd_Name)::DownCast (anAttribute); + //if (aDynamicTypeAttribute.IsNull()) + // return Handle(Message_Alert)(); + //const TCollection_ExtendedString& aDynamicTypeName = aDynamicTypeAttribute->Get(); + + //TCollection_ExtendedString aDescription; + //if (aParametersLabel.FindAttribute (TDataStd_Comment::GetID(), anAttribute)) + //{ + // Handle(TDataStd_Comment) aDescriptionAttribute = Handle(TDataStd_Comment)::DownCast (anAttribute); + // if (!aDescriptionAttribute.IsNull()) + // aDescription = aDescriptionAttribute->Get(); + //} + + //Handle(Message_AlertExtended) anAlert = new Message_AlertExtended(); + //Handle(Message_Attribute) aMessageAttribute; + //if (aDynamicTypeName == STANDARD_TYPE (Message_Attribute)->Name()) + // aMessageAttribute = new Message_Attribute(); + //else if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeStream)->Name()) + //{ + // // values + // NCollection_Vector anArrayValues; + // if (!aParametersLabel.FindAttribute (TDataStd_ExtStringArray::GetID(), anAttribute)) + // return Handle(Message_Alert)(); + + // Handle(TDataStd_ExtStringArray) aValuesAttribute = Handle(TDataStd_ExtStringArray)::DownCast (anAttribute); + // if (aValuesAttribute.IsNull()) + // return Handle(Message_Alert)(); + + // Standard_SStream aStream; + // for (int aValueId = aValuesAttribute->Lower(); aValueId <= aValuesAttribute->Upper(); aValueId++) + // { + // TCollection_AsciiString aKey = aValuesAttribute->Value (aValueId++); + // if (aValueId > aValuesAttribute->Upper()) + // break; + // DUMP_VALUES (aStream, aKey, aValuesAttribute->Value (aValueId)); + // } + // Handle(Message_AttributeStream) anAlert = new Message_AttributeStream (aStream); + // aMessageAttribute = anAlert; + //} + + //if (!aMessageAttribute.IsNull()) + //{ + // // name + // if (!aParametersLabel.FindAttribute (TDataStd_AsciiString::GetID(), anAttribute)) + // return Handle(Message_Alert)(); + // Handle(TDataStd_AsciiString) aNameAttribute = Handle(TDataStd_AsciiString)::DownCast (anAttribute); + // if (aNameAttribute.IsNull()) + // return Handle(Message_Alert)(); + + // aMessageAttribute->SetName (aNameAttribute->Get()); + // aMessageAttribute->SetDescription (aDescription); + + // anAlert->SetAttribute (aMessageAttribute); + //} + + //// time + //Standard_Real aTime = -1; + //Handle(TDataStd_Real) aTimeAttribute; + //if (aParametersLabel.FindAttribute (TDataStd_Real::GetID(), aTimeAttribute)) + // aTime = aTimeAttribute->Get(); + + ////anAlert->SetCumulativeMetric (aTime); + //return anAlert; + return NULL; +} diff --git a/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx b/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx new file mode 100644 index 0000000000..cd97441c1e --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx @@ -0,0 +1,68 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2001-2014 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 _XmlDrivers_MessageReportStorage +#define _XmlDrivers_MessageReportStorage + +#include + +#include +#include +#include + +//! Base class to store/restore Message_Report content in XML document +class XmlDrivers_MessageReportStorage +{ +public: + //! Create document for the report + //! \param theReport the source report + //! \param theFileName a file name + Standard_EXPORT static void ExportReport (const Handle(Message_Report)& theReport, const TCollection_AsciiString& theFileName); + + //! Restores document file content into report instance + //! \param theFileName a file name + //! \return new report or NULL + Standard_EXPORT static Handle(Message_Report) ImportReport (const TCollection_AsciiString& theFileName); + +private: + //! Create labels/attributes for the alert and place it under the parent label. + //! It is recursive as alerts may contains other alerts + //! \param theAlert a source alert + //! \parm theParentLabel a label where alert label is placed + static void exportAlert (const Handle(Message_Alert)& theAlert, const TDF_Label& theParentLabel); + + //! Creates a new alert by the label parameters + //! \param theAlertLabel a source document label + //! \param theGravity an alert gravity + //! \param theReport a container of alerts + //! \param theParentAlert a parent alert, if null, the parent is report + static void importAlert (const TDF_Label& theAlertLabel, + const Message_Gravity theGravity, + Handle(Message_Report)& theReport, + const Handle(Message_Alert)& theParentAlert); + + //! Convert alert to a custom type and store parameters in child labels and attributes + //! \param theAlert a source alert + //! \parm theAlertLabel an alert label + static void exportAlertParameters (const Handle(Message_Alert)& theAlert, + const TDF_Label& theAlertLabel); + + //! Creates alert by label type filled by the label content + //! \param theParametersLabel a label + //! \return new alert or NULL + static Handle(Message_Alert) importAlertParameters (const TDF_Label& aParametersLabel); +}; + +#endif // _XmlDrivers_MessageReportStorage diff --git a/tools/MessageModel/FILES b/tools/MessageModel/FILES new file mode 100644 index 0000000000..953018ceee --- /dev/null +++ b/tools/MessageModel/FILES @@ -0,0 +1,18 @@ +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_ReportCallBack.cxx +MessageModel_ReportCallBack.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..6862cafe7d --- /dev/null +++ b/tools/MessageModel/MessageModel.qrc @@ -0,0 +1,6 @@ + + + icons/item_shape.png + icons/item_vectorOfValues.png + + diff --git a/tools/MessageModel/MessageModel_ActionType.hxx b/tools/MessageModel/MessageModel_ActionType.hxx new file mode 100644 index 0000000000..8cd073c1c8 --- /dev/null +++ b/tools/MessageModel/MessageModel_ActionType.hxx @@ -0,0 +1,30 @@ +// 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 +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Actions.cxx b/tools/MessageModel/MessageModel_Actions.cxx new file mode 100644 index 0000000000..03115c1a2f --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.cxx @@ -0,0 +1,367 @@ +// 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 + +#define DEBUG_ALERTS + +#ifdef DEBUG_ALERTS +#include +#include +#endif + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_Actions::MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel) +: QObject (theParent), myTreeModel (theTreeModel), mySelectionModel (theModel) +{ + myActions.insert (MessageModel_ActionType_Deactivate, + ViewControl_Tools::CreateAction ("Deactivate", SLOT (OnDeactivateReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_Activate, + ViewControl_Tools::CreateAction ("Activate", SLOT (OnActivateReport()), 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)); +#ifdef DEBUG_ALERTS + 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)); +#endif +} + +// ======================================================================= +// 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]); +#ifdef DEBUG_ALERTS + theMenu->addAction (myActions[MessageModel_ActionType_TestMetric]); + theMenu->addAction (myActions[MessageModel_ActionType_TestProperties]); +#endif + } + else if (anAlertItem) + { + theMenu->addAction (myActions[MessageModel_ActionType_ExportToShapeView]); + } + + theMenu->addSeparator(); +} + +// ======================================================================= +// function : onImportReport +// 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 : OnDeactivateReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnDeactivateReport() +{ + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + aReport->SetActive (Standard_False); + ((MessageModel_TreeModel*)mySelectionModel->model())->EmitDataChanged (aReportIndex, aReportIndex); +} + +// ======================================================================= +// function : OnActivateReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnActivateReport() +{ + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + aReport->SetActive (Standard_True); + ((MessageModel_TreeModel*)mySelectionModel->model())->EmitDataChanged (aReportIndex, aReportIndex); +} + +// ======================================================================= +// function : OnClearReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnClearReport() +{ + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + aReport->Clear(); + ((MessageModel_TreeModel*)mySelectionModel->model())->EmitDataChanged (aReportIndex, aReportIndex); +} + +// ======================================================================= +// 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()))); +} + +// ======================================================================= +// function : OnTestMetric +// purpose : +// ======================================================================= +#include +#include +void MessageModel_Actions::OnTestMetric() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + Message_PerfMeter aPerfMeter; + MESSAGE_INFO ("MessageModel_Actions::OnTestAlerts()", "", &aPerfMeter, NULL); + unsigned int start_time = clock(); + //Standard_Real aSystemSeconds, aCurrentSeconds; + //OSD_Chronometer::GetThreadCPU (aCurrentSeconds, aSystemSeconds); + + Standard_Integer aCounter = 5000;//0; + Standard_Real aValue = 0., aValue2 = 0.1; + + double* aMemValue; + for (int aTopIt = 0; aTopIt < 4; aTopIt++) + { + 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; + } + } + MESSAGE_INFO ("Calculate", "", &aPerfMeter, NULL); + } + + //((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 MessageModel_Actions::OnTestPropertyPanel() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + Message_PerfMeter aPerfMeter; + MESSAGE_INFO ("MessageModel_Actions::OnTestAlerts()", "", &aPerfMeter, NULL); + + // gp_XYZ + { + gp_XYZ aCoords (1.3, 2.3, 3.4); + Standard_SStream aStream; + aCoords.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_XYZ", "", &aPerfMeter, NULL); + } + // Bnd_Box + { + Bnd_Box aBox (gp_Pnt (20., 15., 10.), gp_Pnt (25., 20., 15.)); + Standard_SStream aStream; + aBox.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Bnd_Box", "", &aPerfMeter, NULL); + } + // 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.); + Standard_SStream aStream; + anOBB.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Bnd_OBB", "", &aPerfMeter, NULL); + } + myTreeModel->UpdateTreeModel(); +#endif +} diff --git a/tools/MessageModel/MessageModel_Actions.hxx b/tools/MessageModel/MessageModel_Actions.hxx new file mode 100644 index 0000000000..c030c97fdf --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.hxx @@ -0,0 +1,104 @@ +// 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 not active + void OnDeactivateReport(); + + //! Set selected report active + void OnActivateReport(); + + //! Clears container of alerts of selected report + void OnClearReport(); + + //! Exports the first selected shape into ShapeViewer plugin. + void OnExportToShapeView(); + + //! 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(); + +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..c4882a928b --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.cxx @@ -0,0 +1,332 @@ +// 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 + + +// ======================================================================= +// 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(); + + Standard_Boolean isTimeReport = aReport->PerfMeterMode() == Message_PerfMeterMode_UserTimeCPU || + aReport->PerfMeterMode() == Message_PerfMeterMode_SystemTimeInfo; + + if (aReport->PerfMeterMode() == Message_PerfMeterMode_UserTimeCPU || + aReport->PerfMeterMode() == Message_PerfMeterMode_SystemTimeInfo) + + if (theRole == Qt::ForegroundRole) + { + if (!aReport->GetAlerts (Message_Fail).IsEmpty()) + return QColor(Qt::darkRed); + + for (int aGravityId = (int)Message_Trace; aGravityId <= (int)Message_Fail; aGravityId++) + { + if (!aReport->IsActive ((Message_Gravity)aGravityId)) + 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->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + return QIcon (":/icons/item_shape.png"); + else if (!Handle(Message_AttributeStream)::DownCast (anAttribute).IsNull()) + return QIcon (":/icons/item_vectorOfValues.png"); + else + return QVariant(); + } + + if (theRole != Qt::DisplayRole && theRole != Qt::ToolTipRole) + return QVariant(); + + if (anAlert.IsNull()) + return QVariant(); + + switch (Column()) + { + case 0: + return theRole == Qt::DisplayRole ? anAlert->GetMessageKey() : anAlert->DynamicType()->Name(); + //case 1: return QVariant(); // visibility state + //case 2: return rowCount() > 0 ? QVariant (rowCount()) : QVariant(); + //case 3: return anAlert->ElapsedTime() < 0 ? QVariant() : anAlert->ElapsedTime(); + case 4: + { + if (!anExtendedAlert->IsMetricValid()) + return QVariant(); + + if (isTimeReport) + return anExtendedAlert->MetricStop() - anExtendedAlert->MetricStart(); + else + return anExtendedAlert->MetricStart(); + } + case 5: + { + if (!anExtendedAlert->IsMetricValid()) + return QVariant(); + + if (isTimeReport) + { + TreeModel_ItemBasePtr aParentItem = Parent(); + MessageModel_ItemReportPtr aReportItem = itemDynamicCast (aParentItem); + while (!aReportItem) + { + aParentItem = aParentItem->Parent(); + aReportItem = itemDynamicCast (aParentItem); + } + double aDivideTo = aReport->CumulativeMetric (Message_Info); + double anAlertTime = anExtendedAlert->MetricStop() - anExtendedAlert->MetricStart(); + + return aDivideTo == 0 ? QVariant() : 100. * anAlertTime / aDivideTo; + } + else + { + TreeModel_ItemBasePtr aParentItem = Parent(); + //MessageModel_ItemAlertPtr aParentAlertItem = itemDynamicCast (aParentItem); + //if (aParentAlertItem) + //{ + //double aDeltaToParent = CumulativeMetric (anAlert) - CumulativeMetric (aParentAlertItem->GetAlert()); + + //return fabs (aDeltaToParent) > Precision::Confusion() ? QVariant (aDeltaToParent) : QVariant(); + //} + double anAlertMem = anExtendedAlert->MetricStop() - anExtendedAlert->MetricStart(); + return anAlertMem; + } + } + case 6: return MessageModel_Tools::GetPointerAlertInfo (anAlert).ToCString(); + case 7: return MessageModel_Tools::GetShapeTypeAlertInfo (anAlert).ToCString(); + case 8: return MessageModel_Tools::GetStandardTypeAlertInfo (anAlert).ToCString(); + case 9: + { + if (!anExtendedAlert.IsNull() && !anExtendedAlert->Attribute().IsNull()) + { + TCollection_AsciiString aDescription = anExtendedAlert->Attribute()->GetDescription(); + return theRole == Qt::DisplayRole ? TreeModel_Tools::CutString (aDescription.ToCString()) + : aDescription.ToCString(); + } + } + default: break; + } + 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->GetCompositeAlerts(); + 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->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 : GetStream +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::GetStream (Standard_OStream& OS) const +{ + //return; + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (getAlert()); + 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()); + OS << anAttributeStream->GetStream().str(); + } + } + } +} + +// ======================================================================= +// 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))) + // myPresentations.Append (Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject()); + //if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + // myPresentations.Append (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()))) + // myPresentations.Append (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(); + myPresentations.Clear(); +} + +// ======================================================================= +// 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..41950e8c30 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.hxx @@ -0,0 +1,132 @@ +// 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 void GetStream (Standard_OStream& OS) 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 + void GetPresentations (NCollection_List& thePresentations) + { thePresentations.Append (myPresentations); } + + + ////! 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; + + //! 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; + NCollection_List myPresentations; +}; + +#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..9730033557 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.cxx @@ -0,0 +1,200 @@ +// 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 + +// ======================================================================= +// 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->GetAlerts (Message_Fail).IsEmpty()) + return QColor(Qt::darkRed); + + for (int aGravityId = (int)Message_Trace; aGravityId <= (int)Message_Fail; aGravityId++) + { + if (!aReport->IsActive ((Message_Gravity)aGravityId)) + return QColor(Qt::darkGray); + } + return QVariant(); + } + if (theRole == Qt::ToolTipRole && !myDescription.IsEmpty() && Column() == 8) + return myDescription.ToCString(); + + if (theRole != Qt::DisplayRole) + return QVariant(); + + switch (Column()) + { + case 0: return aReport->DynamicType()->Name(); + //case 1: return QVariant(); // visibility state + //case 2: return rowCount() > 0 ? QVariant (rowCount()) : QVariant(); + case 4: return aReport->CumulativeMetric (Message_Info); + case 5: + { + if (aReport->PerfMeterMode() == Message_PerfMeterMode_UserTimeCPU || + aReport->PerfMeterMode() == Message_PerfMeterMode_SystemTimeInfo) + return "100"; + else + return QVariant(); + } + case 9: + { + if (myDescription.IsEmpty()) + return QVariant(); + + OSD_Path aPath(myDescription); + return QString ("%1%2").arg (aPath.Name().ToCString()).arg (aPath.Extension().ToCString()); + } + default: break; + } + 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; +} diff --git a/tools/MessageModel/MessageModel_ItemReport.hxx b/tools/MessageModel/MessageModel_ItemReport.hxx new file mode 100644 index 0000000000..258a58abce --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.hxx @@ -0,0 +1,114 @@ +// 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); + +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..b7465675c3 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.hxx @@ -0,0 +1,123 @@ +// 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; + +//! \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 +{ +private: + //! \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 + }; +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); + + //! 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_ReportCallBack.cxx b/tools/MessageModel/MessageModel_ReportCallBack.cxx new file mode 100644 index 0000000000..695722f0a4 --- /dev/null +++ b/tools/MessageModel/MessageModel_ReportCallBack.cxx @@ -0,0 +1,18 @@ +// Created on: 2018-06-20 +// 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 "MessageModel_ReportCallBack.hxx" + +IMPLEMENT_STANDARD_RTTIEXT(MessageModel_ReportCallBack, Message_ReportCallBack) diff --git a/tools/MessageModel/MessageModel_ReportCallBack.hxx b/tools/MessageModel/MessageModel_ReportCallBack.hxx new file mode 100644 index 0000000000..be5d7c98f3 --- /dev/null +++ b/tools/MessageModel/MessageModel_ReportCallBack.hxx @@ -0,0 +1,48 @@ +// Created on: 2018-06-20 +// 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_ReportCallBack_HeaderFile +#define _MessageModel_ReportCallBack_HeaderFile + +#include + +#include "inspector/TInspectorAPI_Communicator.hxx" + +class TInspectorAPI_Communicator; +DEFINE_STANDARD_HANDLE(MessageModel_ReportCallBack, Message_ReportCallBack) + +//! Class to update tree view model by message report events. +class MessageModel_ReportCallBack : public Message_ReportCallBack +{ +public: + + //! Constructor + MessageModel_ReportCallBack (TInspectorAPI_Communicator* theWindow) : Message_ReportCallBack(), myCommunicator (theWindow) {} + + //! Destructor + ~MessageModel_ReportCallBack() {} + + // Interface to be implemented in the child to process the message report event + // \theAlert updated alert + virtual void Update(const Handle(Message_Alert)& theAlert) { (void)theAlert; /*myCommunicator->UpdateContent();*/ } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(MessageModel_ReportCallBack, Message_ReportCallBack) + +private: + TInspectorAPI_Communicator* myCommunicator; //< communicator +}; + +#endif // _MessageModel_ReportCallBack_HeaderFile diff --git a/tools/MessageModel/MessageModel_Tools.cxx b/tools/MessageModel/MessageModel_Tools.cxx new file mode 100644 index 0000000000..189ecb573d --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.cxx @@ -0,0 +1,195 @@ +// 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 + +// ======================================================================= +// 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(); +} + +// ======================================================================= +// function : GetPointerAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetPointerAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anExtAlert.IsNull()) + return TCollection_AsciiString(); + + Handle(Message_Attribute) anAttribute = anExtAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + return GetPointerInfo (Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape().TShape()); + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + return GetPointerInfo (Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject()); + return TCollection_AsciiString(); +} + +// ======================================================================= +// function : GetShapeTypeAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetShapeTypeAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anExtAlert.IsNull()) + return TCollection_AsciiString(); + + Handle(Message_Attribute) anAttribute = anExtAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + TopoDS_Shape aShape; + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + aShape = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape(); + + if (aShape.IsNull()) + return TCollection_AsciiString(); + + TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); + Standard_SStream aSStream; + TopAbs::Print ((TopAbs_ShapeEnum)aShapeType, aSStream); + return aSStream.str().c_str(); +} + +// ======================================================================= +// function : GetStandardTypeAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetStandardTypeAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anExtAlert.IsNull()) + return TCollection_AsciiString(); + + Handle(Message_Attribute) anAttribute = anExtAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + Handle(Standard_Transient) aPointer; + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + aPointer = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape().TShape(); + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + aPointer = Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject(); + + if (aPointer.IsNull()) + return TCollection_AsciiString(); + + return aPointer->DynamicType()->Name(); +} + +// ======================================================================= +// function : GetPropertyTableValues +// purpose : +// ======================================================================= +void MessageModel_Tools::GetPropertyTableValues (const TreeModel_ItemBasePtr& theItem, + QList& theTableValues) +{ + //Handle(TreeModel_ItemProperties) anItemProperties = theItem->GetProperties(); + //if (!anItemProperties.IsNull()) + //{ + // ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); + // aTableValues->SetProperties (anItemProperties); + // theTableValues.append (aTableValues); + // return; + //} + + //MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(theItem); + //if (!anAlertItem) + // return; + + //const Handle(Message_Alert)& anAlert = anAlertItem->GetAlert(); + //Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + //if (anExtendedAlert.IsNull()) + // return; + + //Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + //if (anAttribute.IsNull()) + // return; + + ////if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeStream))) + ////{ + // //int aSectionSize = 200; + // //ViewControl_TableModelValues* aTableValues = new MessageModel_TableModelValues (anAttribute, aSectionSize); + // //theTableValues.append (aTableValues); + ////} + ////else + ////{ + //if (!anAttribute->GetDescription().IsEmpty()) + //{ + // ViewControl_TableModelValuesDefault* aTableValues = new ViewControl_TableModelValuesDefault(); + // QList aHeaderValues; + // QVector aValues; + // aHeaderValues << TreeModel_HeaderSection ("Description", -2); + // aValues << anAttribute->GetDescription().ToCString(); + // aTableValues->SetHeaderValues (aHeaderValues, Qt::Horizontal); + + // QString aValueStr = anAttribute->GetDescription().ToCString(); + // QStringList aValueStrList = aValueStr.split ("\n"); + // int aNbRows = aValueStrList.size(); + + // QFontMetrics aFontMetrics (qApp->font()); + // int aHeight = aFontMetrics.boundingRect(aValueStr).height(); + // aHeight = (aHeight + TreeModel_Tools::HeaderSectionMargin()) * aNbRows; + // aTableValues->SetValues (aValues); + // aTableValues->SetDefaultSectionSize(Qt::Vertical, aHeight); + + // theTableValues.append (aTableValues); + //} + ////} +} diff --git a/tools/MessageModel/MessageModel_Tools.hxx b/tools/MessageModel/MessageModel_Tools.hxx new file mode 100644 index 0000000000..15ff578375 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.hxx @@ -0,0 +1,74 @@ +// 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); + + //! Returns pointer alert information depening on type of alert (Transient_Object or TopoDS_TShape) + //! \param theAlert a message alert + //! \return text presentation + Standard_EXPORT static TCollection_AsciiString GetPointerAlertInfo (const Handle(Message_Alert)& theAlert); + + //! Returns TopoDS_Shape type alert information or empty string + //! \param theAlert a message alert + //! \return text presentation + Standard_EXPORT static TCollection_AsciiString GetShapeTypeAlertInfo (const Handle(Message_Alert)& theAlert); + + //! Returns dynamic type of an alert object/shape + //! \param theAlert a message alert + //! \return text presentation + Standard_EXPORT static TCollection_AsciiString GetStandardTypeAlertInfo (const Handle(Message_Alert)& theAlert); + + //! Fills container of table values + //! \param theAlert a message alert + //! \param theTableValue container of values + Standard_EXPORT static void GetPropertyTableValues (const TreeModel_ItemBasePtr& theItem, + QList& theTableValues); +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TreeModel.cxx b/tools/MessageModel/MessageModel_TreeModel.cxx new file mode 100644 index 0000000000..a994a4ed99 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.cxx @@ -0,0 +1,153 @@ +// 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 + +const int COLUMN_NAME_WIDTH = 310; +const int COLUMN_SIZE_WIDTH = 30; +const int COLUMN_POINTER_WIDTH = 70; +const int COLUMN_SHAPE_TYPE_WIDTH = 75; +const int COLUMN_STANDARD_TYPE_WIDTH = 120; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_TreeModel::MessageModel_TreeModel (QObject* theParent) +: TreeModel_ModelBase (theParent), myIsReversed (Standard_False) +{ + SetHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + SetHeaderItem (1, TreeModel_HeaderSection ("Size", COLUMN_SIZE_WIDTH)); + SetHeaderItem (2, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); + SetHeaderItem (3, TreeModel_HeaderSection ("Row", COLUMN_SIZE_WIDTH)); + + //SetHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + // column 1 is reserved for visiblity state + //SetHeaderItem (2, TreeModel_HeaderSection ("Size", COLUMN_SIZE_WIDTH)); + + SetHeaderItem (4, TreeModel_HeaderSection ("Metric", -1)); + SetHeaderItem (5, TreeModel_HeaderSection ("Difference", -1)); + + SetHeaderItem (6, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); + SetHeaderItem (7, TreeModel_HeaderSection ("Shape Type", COLUMN_SHAPE_TYPE_WIDTH)); + SetHeaderItem (8, TreeModel_HeaderSection ("Standard Type", COLUMN_STANDARD_TYPE_WIDTH)); + SetHeaderItem (9, TreeModel_HeaderSection ("Description", -1)); +} + +// ======================================================================= +// function : createRootItem +// purpose : +// ======================================================================= +void MessageModel_TreeModel::createRootItem (const int theColumnId) +{ + myRootItems.insert (theColumnId, MessageModel_ItemRoot::CreateItem (TreeModel_ItemBasePtr(), 0, theColumnId)); + if (theColumnId == 0) + m_pRootItem = myRootItems[0]; +} + +// ======================================================================= +// 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 : 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..c4403a0c7f --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.hxx @@ -0,0 +1,93 @@ +// 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 + +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 {}; + + //! 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 = ""); + + //! 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); + + //! Returns root item by column + //! \param theColumn an index of the column + //! \return root item instance + virtual TreeModel_ItemBasePtr RootItem (const int theColumn) const Standard_OVERRIDE + { return myRootItems.contains (theColumn) ? myRootItems[theColumn] : TreeModel_ItemBasePtr(); } + + //! Updates tree model + Standard_EXPORT void UpdateTreeModel(); + +protected: + //! Creates root item + //! \param theColumnId index of a column + virtual void createRootItem (const int theColumnId) Standard_OVERRIDE; + +private: + QMap myRootItems; //!< container of root items, for each column own root item + 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 0000000000000000000000000000000000000000..a808bc55e505fa5e0dd00fc0df80eae5a9eac27c GIT binary patch literal 614 zcmV-s0-61ZP)b8c02hlmzzCYT+BYadXK|ku3NE#KtD1J<#s-Q>%sQ+!Pd3G zm6gg}U6+q^T}lH05CSkipMA8s`T6fXR$sZ?FF zZT+PvV&u1!A~?>>v-R~)PXS_v;(7bR$;s&(%Szt4ddE4y!ot0tvrgx{lgo*c5QVvJ z#rFN6W?9K}zYhLHk^}}2(Q=`%=V+RIXc&osvCHWJi^b}aZ5!_uMU>-;2>Ji|UbI{) zRoBMHlTQ%)?|O{a1y@&h%M%moYi2T28X^KAfB#At_CD5V zw4mAaLq(CA>9qOn0z5nOU$X2_AQBCryTFnpoQop$DJ92(fZqjyd_lwm z#^^`J@a^23(THuaP + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfReal.png b/tools/MessageModel/icons/item_vectorOfReal.png new file mode 100644 index 0000000000000000000000000000000000000000..7181f9460e4986e85dba66ca426b4cb2797c5a5b GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^!ayvgcyqV(DCY@~pSZg{#l zhFJ8zonn}G*nr2?K9tvFP1^Uws=fu+3m(U^PtcpV*TMhdX^YuetNWZc2Ai*TW#pIr z6mDnJbbwv6MS+2*tb?^-S*G0a!a3Oix3}dp%v+v$D*E%f*K$E#;oJQy;j9Uh_mVWFKf{g+P3I)AOy z*7$RGM@`;Y*CSmgE(%S2Hb?)kfsbh<$HQGZr={{$unc`-ETA4tmYw)LIL1oR_=r>mdKI;Vst0G)P;+W-In literal 0 HcmV?d00001 diff --git a/tools/MessageModel/icons/item_vectorOfReal.svg b/tools/MessageModel/icons/item_vectorOfReal.svg new file mode 100644 index 0000000000..38b1032701 --- /dev/null +++ b/tools/MessageModel/icons/item_vectorOfReal.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfRealVec3.png b/tools/MessageModel/icons/item_vectorOfRealVec3.png new file mode 100644 index 0000000000000000000000000000000000000000..4d0ebf93d945e38f981902fdd551b149a5cd4bea GIT binary patch literal 421 zcmV;W0b2fvP)B`-7>Bsb(1K*cp8t`U@e50Gu> zXgL8LHR2G^@>774C`gOFvCZyK1dxzyIdl|x-P1gMGsV-;xwSzu3jnAkQ1`LYFY^JQ zLYL$&Ku2HZW*-lWLks|bZqrAeA0MnHcXQ_ZL7wNn36f=5&pB7g&UFBYh=u4yV@zzC z8)Jml8e$#Ty4t}0F1oNbroa;c@nxI)KBWo(_*M6**sA~_#ziW`+ch(XMhFox^H4fw zs+Bs4F&03n46 + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfValues.png b/tools/MessageModel/icons/item_vectorOfValues.png new file mode 100644 index 0000000000000000000000000000000000000000..7181f9460e4986e85dba66ca426b4cb2797c5a5b GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^!ayvgcyqV(DCY@~pSZg{#l zhFJ8zonn}G*nr2?K9tvFP1^Uws=fu+3m(U^PtcpV*TMhdX^YuetNWZc2Ai*TW#pIr z6mDnJbbwv6MS+2*tb?^-S*G0a!a3Oix3}dp%v+v$D*E%f*K$E#;oJQy;j9Uh_mVWFKf{g+P3I)AOy z*7$RGM@`;Y*CSmgE(%S2Hb?)kfsbh<$HQGZr={{$unc`-ETA4tmYw)LIL1oR_=r>mdKI;Vst0G)P;+W-In literal 0 HcmV?d00001 diff --git a/tools/MessageModel/icons/item_vectorOfValues.svg b/tools/MessageModel/icons/item_vectorOfValues.svg new file mode 100644 index 0000000000..38b1032701 --- /dev/null +++ b/tools/MessageModel/icons/item_vectorOfValues.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/tools/MessageView/FILES b/tools/MessageView/FILES new file mode 100644 index 0000000000..529ec64718 --- /dev/null +++ b/tools/MessageView/FILES @@ -0,0 +1,6 @@ +MessageView_Communicator.cxx +MessageView_Communicator.hxx +MessageView_VisibilityState.cxx +MessageView_VisibilityState.hxx +MessageView_Window.cxx +MessageView_Window.hxx 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..2164e2257b --- /dev/null +++ b/tools/MessageView/MessageView_Communicator.hxx @@ -0,0 +1,68 @@ +// 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 +#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)) + { myWindow->SetCallBack (new MessageModel_ReportCallBack (this)); } + + //! 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..5b7e5d415f --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.cxx @@ -0,0 +1,140 @@ +// 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->GetPresentations (aPresentations); + if (!aPresentations.IsEmpty()) + return true; + } + + return !getShape (theIndex).IsNull();// || hasTableValues (theIndex); +} + +// ======================================================================= +// function : SetVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::SetVisible (const QModelIndex& theIndex, const bool theState, const bool toEmitDataChanged) +{ + TopoDS_Shape aShape = getShape (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 (getShape (theIndex), myPresentationType); +} + +// ======================================================================= +// 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 : getShape +// purpose : +// ======================================================================= +TopoDS_Shape MessageView_VisibilityState::getShape (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..787558a684 --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.hxx @@ -0,0 +1,87 @@ +// 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 TreeModel_VisibilityState +{ +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; + +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 getShape (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..69fda29840 --- /dev/null +++ b/tools/MessageView/MessageView_Window.cxx @@ -0,0 +1,818 @@ +// 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 +#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 = 400;// 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->SetReversed (Standard_True); + for (int i = 6; i <= 8; i++) // hide shape parameters columns + { + TreeModel_HeaderSection anItem = aModel->GetHeaderItem (i); + anItem.SetIsHidden (true); + aModel->SetHeaderItem (i, anItem); + } + + 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); + + 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); + myTreeView->setContextMenuPolicy (Qt::CustomContextMenu); + connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)), + this, SLOT (onTreeViewContextMenuRequested (const QPoint&))); + new TreeModel_ContextMenu (myTreeView); + + 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 (propertyViewSelectionChanged()), this, SLOT (onPropertyViewSelectionChanged ())); + + // view + myViewWindow = new View_Window (myMainWindow, false); + connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed())); + aVisibilityState->SetDisplayer (myViewWindow->GetDisplayer()); + aVisibilityState->SetPresentationType (View_PresentationType_Main); + myViewWindow->GetView()->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); +} + +// ======================================================================= +// 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); + View_Tools::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) +{ + if (theItem.IsEmpty()) + { + TreeModel_Tools::SetDefaultHeaderSections (myTreeView); + return; + } + + 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 (View_Tools::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_Report::CurrentReport( Standard_False); + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aDefaultReport.IsNull() && !aViewModel->HasReport (aDefaultReport)) + { + aDefaultReport->SetCallBack (myCallBack); + addReport (aDefaultReport); + } + // reload report of selected item + onReloadReport(); + + updateTreeModel(); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageView_Window::Init (NCollection_List& theParameters) +{ + Handle(AIS_InteractiveContext) aContext; + NCollection_List aParameters; + + Handle(Message_ReportCallBack) aReportCallBack; + 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()) + { + aMessageReport->SetCallBack (myCallBack); + 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); + } + + if (!aViewCamera.IsNull()) + myViewWindow->GetView()->GetViewer()->GetView()->Camera()->Copy (aViewCamera); + + theParameters = aParameters; +} + +// ======================================================================= +// function : openFile +// purpose : +// ======================================================================= +void MessageView_Window::openFile(const TCollection_AsciiString& theFileName) +{ + Handle(Message_Report) aReport = XmlDrivers_MessageReportStorage::ImportReport(theFileName); + if (aReport.IsNull()) + return; + + 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); +} + +// ======================================================================= +// function : onTreeViewSelectionChanged +// 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(); + + NCollection_List aPresentations; + MessageModel_ItemRootPtr aRootItem; + 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; + + //Handle(TreeModel_ItemProperties) anItemProperties = anItemBase->GetProperties(); + //if (anItemProperties) + // anItemProperties->GetPresentations (-1, -1, aPresentations); + TreeModel_ItemStreamPtr aStreamParent = itemDynamicCast (anItemBase); + if (!aStreamParent) + return; + + Handle(TreeModel_ItemProperties) anItemProperties = aStreamParent->Properties (); + if (anItemProperties) + anItemProperties->GetPresentations (-1, -1, aPresentations); + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + if (!anAlertItem) + continue; + anAlertItem->GetPresentations (aPresentations); + } + updatePreviewPresentation (aPresentations); +} + +// ======================================================================= +// 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 ("Import Report"), SLOT (onImportReport()), 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)); + } + } + aMenu->addSeparator(); + myTreeViewActions->AddMenuActions (aSelectedIndices, aMenu); + + QPoint aPoint = myTreeView->mapToGlobal (thePosition); + aMenu->exec (aPoint); +} + +// ======================================================================= +// function : onPropertyPanelShown +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyPanelShown (bool isToggled) +{ + if (!isToggled) + return; + + updatePropertyPanelBySelection(); +} + +// ======================================================================= +// function : onPropertyViewSelectionChanged +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyViewSelectionChanged() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex aSelectedIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + QModelIndex anIndex = myTreeView->model()->index (aSelectedIndex.row(), TreeModel_ColumnType_Visibility, aSelectedIndex.parent()); + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + if (!anAlertItem) + return; + + QList aPropertyTables; + myPropertyView->GetActiveTables (aPropertyTables); + if (aPropertyTables.isEmpty()) + return; + + ViewControl_Table* aFirstTable = aPropertyTables[0]; // TODO: implement for several tables + + QMap> aSelectedIndices; + aFirstTable->GetSelectedIndices (aSelectedIndices); + + // clear presentation if selection is empty + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + TreeModel_VisibilityState* aVisibilityState = aTreeModel->GetVisibilityState(); + if (aSelectedIndices.isEmpty() && aVisibilityState->IsVisible (anIndex)) + { + aVisibilityState->SetVisible (anIndex, false, true); + anAlertItem->SetCustomShape (TopoDS_Shape()); + return; + } + + /*TopoDS_Shape aShapeOfSelection = MessageModel_Tools::BuildShape (anAlertItem->GetAlert(), aSelectedIndices[0], aFirstTable); + if (aShapeOfSelection.IsNull()) + return; + + if (aVisibilityState->IsVisible (anIndex)) + { + View_Displayer* aDisplayer = myViewWindow->GetDisplayer(); + + Handle(AIS_InteractiveObject) aPresentation = myViewWindow->GetDisplayer()->FindPresentation (anAlertItem->GetCustomShape()); + + Handle(AIS_Shape) aShapePresentation = Handle(AIS_Shape)::DownCast (aPresentation); + aShapePresentation->Set (aShapeOfSelection); + + aDisplayer->RedisplayPresentation (aPresentation); + anAlertItem->SetCustomShape (aShapeOfSelection); + } + else + { + anAlertItem->SetCustomShape (aShapeOfSelection); + aVisibilityState->SetVisible (anIndex, true); + }*/ +} + +// ======================================================================= +// 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 (*.xml *)")); + QString aSelectedFilter; + QString aFileName = QFileDialog::getSaveFileName (0, tr ("Export report to file"), QString(), aFilter, &aSelectedFilter); + + XmlDrivers_MessageReportStorage::ExportReport (aReportItem->GetReport(), + TCollection_AsciiString (aFileName.toStdString().c_str())); +} + +// ======================================================================= +// function : onImportReport +// purpose : +// ======================================================================= +void MessageView_Window::onImportReport() +{ + QString aFilter (tr ("Document file (*.cbf *)")); + QString aSelectedFilter; + + QString aFileName = QFileDialog::getOpenFileName (0, tr("Import report"), QString(), aSelectedFilter); + openFile (TCollection_AsciiString (aFileName.toStdString().c_str())); +} + +// ======================================================================= +// 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(); + Handle(Message_Report) aReport = XmlDrivers_MessageReportStorage::ImportReport (aDescription); + if (aReport.IsNull()) + return; + + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + aModel->clearSelection(); + aTreeModel->SetReport (aReportItem->Row(), aReport, aDescription); +} + +// ======================================================================= +// 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);*/ + QList aTableValuesList; + + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemStreamPtr aStreamItem = itemDynamicCast (TreeModel_ModelBase::GetItemByIndex (anIndex)); + if (aStreamItem) + { + Handle(TreeModel_ItemProperties) anItemProperties = aStreamItem->Properties (); + if (!anItemProperties.IsNull()) + { + ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (anItemProperties); + aTableValuesList.append (aTableValues); + } + } + myPropertyView->Init (aTableValuesList); +} + +// ======================================================================= +// function : updatePreviewPresentation +// purpose : +// ======================================================================= +void MessageView_Window::updatePreviewPresentation (const NCollection_List& thePresentations) +{ + Handle(AIS_InteractiveContext) aContext = myViewWindow->GetViewToolBar()->GetCurrentContext(); + if (aContext.IsNull()) + return; + + if (!myPreviewPresentations.IsEmpty()) + { + for (NCollection_List::Iterator aDisplayedIt (myPreviewPresentations); aDisplayedIt.More(); aDisplayedIt.Next()) + { + Handle(AIS_InteractiveObject) aPrs = Handle(AIS_InteractiveObject)::DownCast (aDisplayedIt.Value()); + if (!aPrs.IsNull() && aPrs->GetContext() == aContext) + aContext->Remove (aPrs, Standard_True); + } + } + myPreviewPresentations.Clear(); + + myPreviewPresentations = thePresentations; + if (myPreviewPresentations.IsEmpty()) + return; + + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + for (NCollection_List::Iterator aDisplayedIt (myPreviewPresentations); aDisplayedIt.More(); aDisplayedIt.Next()) + { + Handle(AIS_InteractiveObject) aPrs = Handle(AIS_InteractiveObject)::DownCast (aDisplayedIt.Value()); + if (!aPrs.IsNull()) + { + if (!aPrs->GetContext().IsNull()) + continue; // not possible to display one object in several contexts + aContext->Display (aPrs, AIS_Shaded, -1/*do not participate in selection*/, Standard_True); + } + else if (!Handle(Convert_TransientShape)::DownCast (aDisplayedIt.Value()).IsNull()) + { + Handle(Convert_TransientShape) aShapeObject = Handle(Convert_TransientShape)::DownCast (aDisplayedIt.Value()); + aBuilder.Add (aCompound, aShapeObject->GetShape()); + } + } + + if (aCompound.IsNull()) + { + if (!aContext.IsNull() && myPreviewPresentation->GetContext() == aContext) + aContext->Remove (myPreviewPresentation, Standard_True); + myPreviewPresentation = NULL; + return; + + } + else + { + if (myPreviewPresentation.IsNull()) + { + myPreviewPresentation = new AIS_Shape (aCompound); + myPreviewPresentation->SetAttributes (GetPreviewAttributes(aContext)); + //myPreviewPresentation->SetAttributes (myPreviewParameters->GetDrawer()); + + //myPreviewPresentation->SetTransformPersistence(thePersistent); + if (!aContext.IsNull()) + aContext->Display (myPreviewPresentation, AIS_Shaded, -1/*do not participate in selection*/, Standard_True); + } + else + { + Handle(AIS_Shape)::DownCast (myPreviewPresentation)->Set (aCompound); + //myPreviewPresentation->SetTransformPersistence(thePersistent); + if (!aContext.IsNull() && myPreviewPresentation->GetContext() == aContext) + aContext->Redisplay (myPreviewPresentation, Standard_True); + } + } +} diff --git a/tools/MessageView/MessageView_Window.hxx b/tools/MessageView/MessageView_Window.hxx new file mode 100644 index 0000000000..6ff19ed309 --- /dev/null +++ b/tools/MessageView/MessageView_Window.hxx @@ -0,0 +1,186 @@ +// 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_Window; + +class ViewControl_PropertyView; +class MessageModel_ReportCallBack; + +class QDockWidget; +class QMainWindow; +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); } + + //! Sets message callback to update the current content of the view + //! \param theCallBack + void SetCallBack (const Handle(Message_ReportCallBack)& theCallBack) { myCallBack = theCallBack; } + + //! 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 presentation of the selected tree view item using information about selection in property view + //! \param theSelected container of selected table cells + //! \param theDeselected container of selected table cells + void onPropertyViewSelectionChanged(); + + //! Updates visibility states by erase all in context + void onEraseAllPerformed(); + + //! Export report into document + void onExportReport(); + + //! Import report into document + void onImportReport(); + + //! 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(); + +protected: + //! 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 + //!< \param theShape container of shapes + void updatePreviewPresentation (const NCollection_List& thePresentations); + +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 + + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + Handle(Message_ReportCallBack) myCallBack; //! < message call back to update content of the view + + Handle(AIS_InteractiveObject) myPreviewPresentation; //!< presentation of preview for a selected object + NCollection_List myPreviewPresentations; +}; + +#endif diff --git a/tools/TInspectorEXE/TInspectorEXE.cxx b/tools/TInspectorEXE/TInspectorEXE.cxx index b3f1a5ad37..1c42a38530 100644 --- a/tools/TInspectorEXE/TInspectorEXE.cxx +++ b/tools/TInspectorEXE/TInspectorEXE.cxx @@ -126,10 +126,10 @@ int main (int argc, char** argv) aPlugins.insert("TKShapeView"); aPlugins.insert("TKVInspector"); - //Handle(Message_Report) aReport = Message_Report::CurrentReport (Standard_True); - //aReport->SetLimit (100);//30); - //aReport->SetActive (Standard_True);//Standard_False); - //aPlugins.insert("TKMessageView"); + Handle(Message_Report) aReport = Message_Report::CurrentReport (Standard_True); + aReport->SetLimit (100);//30); + aReport->SetActive (Standard_True);//Standard_False); + aPlugins.insert("TKMessageView"); anActivatedPluginName = "TKVInspector"; //anActivatedPluginName = "TKMessageView"; 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 618620f544..c8adc9a663 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,7 +393,7 @@ 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." diff --git a/tools/TreeModel/TreeModel_ItemBase.cxx b/tools/TreeModel/TreeModel_ItemBase.cxx index 09c1735db0..eb10736835 100644 --- a/tools/TreeModel/TreeModel_ItemBase.cxx +++ b/tools/TreeModel/TreeModel_ItemBase.cxx @@ -122,18 +122,24 @@ void TreeModel_ItemBase::Init() { m_bInitialized = true; - NCollection_List aHierarchicalValues; + m_iStreamChildren = 0; if (Column() == 0) { NCollection_IndexedDataMap aValues; + NCollection_List aHierarchicalValues; Standard_SStream aStream; GetStream (aStream); Standard_Dump::SplitJson (Standard_Dump::Text (aStream), aValues); aHierarchicalValues = Standard_Dump::HierarchicalValueIndices (aValues); - //if (aHierarchicalValues.Size() == 1) + m_iStreamChildren = aHierarchicalValues.Extent(); + if (!m_iStreamChildren && aValues.Extent()) + { + TreeModel_ItemStreamPtr aStreamParent = itemDynamicCast(currentItem()); + if (!aStreamParent) + m_iStreamChildren = 1; + } } - m_iStreamChildren = aHierarchicalValues.Extent(); } // ======================================================================= diff --git a/tools/TreeModel/TreeModel_ItemStream.cxx b/tools/TreeModel/TreeModel_ItemStream.cxx index 94c67d031d..17cda16e60 100644 --- a/tools/TreeModel/TreeModel_ItemStream.cxx +++ b/tools/TreeModel/TreeModel_ItemStream.cxx @@ -38,7 +38,7 @@ void TreeModel_ItemStream::Init() if (!myProperties->Item()) myProperties->SetItem (currentItem()); - TCollection_AsciiString aKey, aKeyValue; + TCollection_AsciiString aKey, aKeyValue, aPropertiesValue; TreeModel_ItemStreamPtr aStreamParent = itemDynamicCast(Parent()); if (!aStreamParent) { @@ -50,6 +50,13 @@ void TreeModel_ItemStream::Init() aKey = aValues.FindKey (Row() + 1); aKeyValue = aValues.FindFromIndex (Row() + 1); + + // one row value, like gp_XYZ, without additional { for type + aValues.Clear(); + if (!Standard_Dump::SplitJson (aKeyValue, aValues)) + aPropertiesValue = Standard_Dump::Text (aStream); + else + aPropertiesValue = aKeyValue; } else { @@ -57,10 +64,11 @@ void TreeModel_ItemStream::Init() TCollection_AsciiString aValue; aStreamParent->GetChildStream (Row(), aKey, aKeyValue); + aPropertiesValue = aKeyValue; } myKey = aKey; - myProperties->Init (aKeyValue); + myProperties->Init (aPropertiesValue); myStreamValue = aKeyValue; NCollection_IndexedDataMap aValues; diff --git a/tools/VInspector/VInspector_Window.cxx b/tools/VInspector/VInspector_Window.cxx index c2bd8ed934..ab1d960991 100644 --- a/tools/VInspector/VInspector_Window.cxx +++ b/tools/VInspector/VInspector_Window.cxx @@ -1071,35 +1071,30 @@ void VInspector_Window::updatePropertyPanelBySelection() return; QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); - TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); - if (!anItemBase) - return; - - TreeModel_ItemStreamPtr aStreamItem = itemDynamicCast (anItemBase); - if (!aStreamItem) - return; - - Handle(TreeModel_ItemProperties) anItemProperties = aStreamItem->Properties (); + TreeModel_ItemStreamPtr aStreamItem = itemDynamicCast (TreeModel_ModelBase::GetItemByIndex (anIndex)); QList aTableValuesList; - if (!anItemProperties.IsNull()) + if (aStreamItem) { - ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); - aTableValues->SetProperties (anItemProperties); - aTableValuesList.append (aTableValues); - } - - /*QItemSelectionModel* aModel = myTreeView->selectionModel(); - if (!aModel) - return; + Handle(TreeModel_ItemProperties) anItemProperties = aStreamItem->Properties (); + if (!anItemProperties.IsNull()) + { + ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (anItemProperties); + aTableValuesList.append (aTableValues); + } + /*QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; - QModelIndexList aSelected = TreeModel_ModelBase::GetSelected (aModel->selectedIndexes(), 0); - QList aTableValues; + QModelIndexList aSelected = TreeModel_ModelBase::GetSelected (aModel->selectedIndexes(), 0); + QList aTableValues; - if (aSelected.size() == 1) - { - TreeModel_ItemBasePtr aSelectedItem = TreeModel_ModelBase::GetItemByIndex(aSelected.first()); - VInspector_Tools::GetPropertyTableValues (aSelectedItem, myPaneCreators, aTableValues); - }*/ + if (aSelected.size() == 1) + { + TreeModel_ItemBasePtr aSelectedItem = TreeModel_ModelBase::GetItemByIndex(aSelected.first()); + VInspector_Tools::GetPropertyTableValues (aSelectedItem, myPaneCreators, aTableValues); + }*/ + } myPropertyView->Init (aTableValuesList); } -- 2.39.5