From: nds Date: Tue, 25 Dec 2018 06:12:51 +0000 (+0300) Subject: 0029451: Information Message Alert to debug an algorithm or object functionality X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=9a3d03bedb29dbf0124f5d53478d331d7ba877ff;p=occt-copy.git 0029451: Information Message Alert to debug an algorithm or object functionality Modifications: - Message_AlertExtended to store additional parameters (attributes, composite alert container, performance meter) - Message_Attribute and inherited classes to store custom information about alert - Message_CompositeAlerts to have hierarchical structure of alerts - Message_PerfMeter to automatically calculate time between alerts adding into report - Message_ReportCall back to be able to react to message report filling. - Import/Export message report report. Currently it is implemented using XmlDrivers_MessageReportStorage - MessageView/MessageModel - Inspector plugin for GUI presentation of Message_Report (cherry picked from commit e4529dcf83b12759e47efb89ded8207f802556a7) Conflicts: tools/ViewControl/FILES tools/ViewControl/ViewControl_PropertyView.cxx tools/ViewControl/ViewControl_PropertyView.hxx tools/ViewControl/ViewControl_Table.cxx tools/ViewControl/ViewControl_Table.hxx tools/ViewControl/ViewControl_TableModel.hxx tools/ViewControl/ViewControl_TableModelFilter.cxx tools/ViewControl/ViewControl_TableModelFilter.hxx tools/ViewControl/ViewControl_TableModelValues.hxx tools/ViewControl/ViewControl_TableProperty.cxx tools/ViewControl/ViewControl_TableProperty.hxx tools/ViewControl/ViewControl_Tools.cxx tools/ViewControl/ViewControl_Tools.hxx (cherry picked from commit 68876fcc5a99f13fcfdbc5c868491f0be6139bbb) --- 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..fe9884e26d 100755 --- a/src/Message/FILES +++ b/src/Message/FILES @@ -1,8 +1,22 @@ Message.cxx Message.hxx +Message_Alert.cxx +Message_Alert.hxx +Message_AlertExtended.cxx +Message_AlertExtended.hxx Message_Algorithm.cxx Message_Algorithm.hxx Message_Algorithm.lxx +Message_Attribute.hxx +Message_Attribute.cxx +Message_AttributeObject.hxx +Message_AttributeObject.cxx +Message_AttributeVectorOfReal.hxx +Message_AttributeVectorOfReal.cxx +Message_AttributeVectorOfRealVec3.hxx +Message_AttributeVectorOfRealVec3.cxx +Message_CompositeAlerts.cxx +Message_CompositeAlerts.hxx Message_ExecStatus.hxx Message_Gravity.hxx Message_HArrayOfMsg.hxx @@ -15,6 +29,8 @@ Message_Msg.hxx Message_Msg.lxx Message_MsgFile.cxx Message_MsgFile.hxx +Message_PerfMeter.cxx +Message_PerfMeter.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..cbaa470231 100644 --- a/src/Message/Message.cxx +++ b/src/Message/Message.cxx @@ -49,3 +49,43 @@ 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" + }; +} + +//======================================================================= +//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; +} diff --git a/src/Message/Message.hxx b/src/Message/Message.hxx index 72693ce93e..1d78005932 100644 --- a/src/Message/Message.hxx +++ b/src/Message/Message.hxx @@ -17,6 +17,8 @@ #ifndef _Message_HeaderFile #define _Message_HeaderFile +#include + #include #include #include @@ -59,6 +61,27 @@ 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); diff --git a/src/Message/Message_AlertExtended.cxx b/src/Message/Message_AlertExtended.cxx new file mode 100644 index 0000000000..5bcb3416a9 --- /dev/null +++ b/src/Message/Message_AlertExtended.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 +#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 : 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..6864ec316e --- /dev/null +++ b/src/Message/Message_AlertExtended.hxx @@ -0,0 +1,123 @@ +// 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 +//! 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(), myCumulativeTime (GetUndefinedTime()) {} + + //! 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 the alert cumulative time. It includes times of sub alerts + //! @return value + Standard_Real GetCumulativeTime() const { return myCumulativeTime; } + + //! Sets cumulative time of alert + //! \param theCumulativeTime time of the alert + void SetCumulativeTime (const Standard_Real theCumulativeTime) { myCumulativeTime = theCumulativeTime; } + + //! 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 when it is not defined + //! \return integer value + static Standard_Integer GetUndefinedTime() { return -1; } + + //! 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 myCumulativeTime; //!< alert cumulative time + + friend Message_PerfMeter; +}; + +#endif // _Message_Alert_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..83788cacdb --- /dev/null +++ b/src/Message/Message_AttributeObject.cxx @@ -0,0 +1,31 @@ +// 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_Attribute) + +//======================================================================= +//function : Message_AttributeObject +//purpose : +//======================================================================= + +Message_AttributeObject::Message_AttributeObject (const Handle(Standard_Transient)& theObject, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute (theName, theDescription) +{ + myObject = theObject; +} diff --git a/src/Message/Message_AttributeObject.hxx b/src/Message/Message_AttributeObject.hxx new file mode 100644 index 0000000000..bbf7afe727 --- /dev/null +++ b/src/Message/Message_AttributeObject.hxx @@ -0,0 +1,45 @@ +// 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_Attribute +{ +public: + //! Constructor with string argument + Standard_EXPORT Message_AttributeObject (const Handle(Standard_Transient)& theObject, + 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_Attribute) + +private: + Handle(Standard_Transient) myObject; +}; + +#endif // _Message_AttributeObject_HeaderFile diff --git a/src/Message/Message_AttributeVectorOfReal.cxx b/src/Message/Message_AttributeVectorOfReal.cxx new file mode 100644 index 0000000000..0880b5b1a2 --- /dev/null +++ b/src/Message/Message_AttributeVectorOfReal.cxx @@ -0,0 +1,68 @@ +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeVectorOfReal, Message_Attribute) + +//======================================================================= +//function : Message_AttributeVectorOfReal +//purpose : +//======================================================================= + +Message_AttributeVectorOfReal::Message_AttributeVectorOfReal (const NCollection_Vector& theValues, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute(theName, theDescription) +{ + SetValues (theValues); +} + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= + +void Message_AttributeVectorOfReal::SetValues (const NCollection_Vector& theValues) +{ + myValues = theValues; + + myCachedValue = TCollection_AsciiString ("[") + (Standard_Integer)myValues.Length() + "] : "; + if (myValues.Length() < 2) + return; + + myCachedValue += myValues.First(); + myCachedValue += " ... "; + myCachedValue += myValues.Last(); +} + +//======================================================================= +//function : GetDescription +//purpose : +//======================================================================= + +const TCollection_AsciiString& Message_AttributeVectorOfReal::GetDescription() const +{ + if (!Message_Attribute::GetDescription().IsEmpty()) + return Message_Attribute::GetDescription(); + + return myCachedValue; +} + diff --git a/src/Message/Message_AttributeVectorOfReal.hxx b/src/Message/Message_AttributeVectorOfReal.hxx new file mode 100644 index 0000000000..ec0fa52da7 --- /dev/null +++ b/src/Message/Message_AttributeVectorOfReal.hxx @@ -0,0 +1,58 @@ +// 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_AttributeVectorOfReal_HeaderFile +#define _Message_AttributeVectorOfReal_HeaderFile + +#include +#include + +#include + +class Message_PerfMeter; +class Message_Report; + +//! Alert object storing container of Standard_Real values in its field +class Message_AttributeVectorOfReal : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeVectorOfReal (const NCollection_Vector& theValues, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()); + + //! Sets the values + //! @param theValues container of values + Standard_EXPORT void SetValues (const NCollection_Vector& theValues); + + //! Returns values + //! @return values + const NCollection_Vector& GetValues() const { return myValues; } + + //! Returns description of alert if it is set + //! @return alert description + virtual const TCollection_AsciiString& GetDescription() const; + + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeVectorOfReal, Message_Attribute) + +private: + NCollection_Vector myValues; //!< container of values + TCollection_AsciiString myCachedValue; //!< short description of the values in form: [size] : first ... last +}; + +#endif // _Message_AttributeVectorOfReal_HeaderFile diff --git a/src/Message/Message_AttributeVectorOfRealVec3.cxx b/src/Message/Message_AttributeVectorOfRealVec3.cxx new file mode 100644 index 0000000000..36bb716b49 --- /dev/null +++ b/src/Message/Message_AttributeVectorOfRealVec3.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 +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeVectorOfRealVec3, Message_Attribute) + +//======================================================================= +//function : Message_AttributeVectorOfRealVec3 +//purpose : +//======================================================================= + +Message_AttributeVectorOfRealVec3::Message_AttributeVectorOfRealVec3 (const NCollection_Vector>& theValues, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute (theName, theDescription) +{ + SetValues (theValues); +} + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= + +void Message_AttributeVectorOfRealVec3::SetValues (const NCollection_Vector>& theValues) +{ + myValues = theValues; + + myCachedValue = TCollection_AsciiString ("[") + (Standard_Integer)myValues.Length() + "] : "; + if (myValues.Length() < 2) + return; + + NCollection_Vec3 aValue = myValues.First(); + myCachedValue = myCachedValue + "(" + aValue.x() + "," + aValue.y() + "," + aValue.z() + ")"; + myCachedValue += " ... "; + aValue = myValues.Last(); + myCachedValue = myCachedValue + "(" + aValue.x() + "," + aValue.y() + "," + aValue.z() + ")"; +} + +//======================================================================= +//function : GetDescription +//purpose : +//======================================================================= + +const TCollection_AsciiString& Message_AttributeVectorOfRealVec3::GetDescription() const +{ + if (!Message_Attribute::GetDescription().IsEmpty()) + return Message_Attribute::GetDescription(); + + return myCachedValue; +} + diff --git a/src/Message/Message_AttributeVectorOfRealVec3.hxx b/src/Message/Message_AttributeVectorOfRealVec3.hxx new file mode 100644 index 0000000000..b47b80beed --- /dev/null +++ b/src/Message/Message_AttributeVectorOfRealVec3.hxx @@ -0,0 +1,56 @@ +// 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_AttributeVectorOfRealVec3_HeaderFile +#define _Message_AttributeVectorOfRealVec3_HeaderFile + +#include +#include + +#include +#include + +//! Alert object storing container of Standard_Real values in its field +class Message_AttributeVectorOfRealVec3 : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeVectorOfRealVec3 (const NCollection_Vector>& theValues, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()); + + //! Sets the values + //! @param theValues container of values + Standard_EXPORT void SetValues (const NCollection_Vector>& theValues); + + //! Returns values + //! @return values + const NCollection_Vector>& GetValues() const { return myValues; } + + //! Returns description of alert if it is set + //! @return alert description + virtual const TCollection_AsciiString& GetDescription() const; + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeVectorOfRealVec3, Message_Attribute) + +private: + NCollection_Vector> myValues; //!< container of values + TCollection_AsciiString myCachedValue; + TCollection_AsciiString myDescription; //!< short description of the values in form: [size] : first ... last +}; + +#endif // _Message_AttributeVectorOfRealVec3_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..4c584e7982 --- /dev/null +++ b/src/Message/Message_PerfMeter.cxx @@ -0,0 +1,168 @@ +// 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 + +//======================================================================= +//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) +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anExtendedAlert.IsNull()) + return; + + if (myActiveAlerts.IsEmpty()) + { + setAlert (0, theAlert); + 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); + 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) +{ + 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, getCurrentTime())); + anAlertExtended->SetPerfMeter (this); + 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->SetCumulativeTime (getCurrentTime() - anAlertInfo.myStartTime); + 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 : getCurrentTime +//purpose : +//======================================================================= + +Standard_Real Message_PerfMeter::getCurrentTime() +{ + Standard_Real aSystemSeconds, aCurrentSeconds; + OSD_Chronometer::GetThreadCPU (aCurrentSeconds, aSystemSeconds); + + return aCurrentSeconds; +} diff --git a/src/Message/Message_PerfMeter.hxx b/src/Message/Message_PerfMeter.hxx new file mode 100644 index 0000000000..aa1c802a2e --- /dev/null +++ b/src/Message/Message_PerfMeter.hxx @@ -0,0 +1,92 @@ +// 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 + +//! 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) {} + + //! 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); + +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); + + //! 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 time of the performance meter + //! \param theMeterId a performance meter index + //! \return time value + static Standard_Real getCurrentTime(); + +protected: + //! Struct to store start time for the alert + struct AlertInfo + { + AlertInfo (const Handle(Message_AlertExtended)& theAlert, Standard_Real theStartTime) + : myAlert (theAlert), myStartTime (theStartTime) {} + + Handle(Message_AlertExtended) myAlert; //!< an alert + Standard_Real myStartTime; //!< start time of the alert + }; + + NCollection_DataMap myActiveAlerts; //!< container of current alerts + Message_Gravity myGravity; //!< perf meter alert gravity +}; + + +#endif // _Message_PerfMeter_HeaderFile diff --git a/src/Message/Message_Report.cxx b/src/Message/Message_Report.cxx index 07324599d2..ab3b9823d3 100644 --- a/src/Message/Message_Report.cxx +++ b/src/Message/Message_Report.cxx @@ -14,8 +14,14 @@ // commercial license or contractual agreement. #include + +#include +#include #include #include +#include +#include + #include IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) @@ -26,7 +32,9 @@ IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) //======================================================================= Message_Report::Message_Report () +: myIsUsePerfMeter (Standard_False), myLimit (-1) { + SetActive (Standard_True); } //======================================================================= @@ -36,6 +44,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 +69,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 = getLastAlert(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); + + if (!myCallBack.IsNull()) + myCallBack->Update(theAlert); } //======================================================================= @@ -73,6 +141,64 @@ const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity return myAlerts[theGravity]; } +//======================================================================= +//function : getLastAlert +//purpose : +//======================================================================= + +Handle(Message_Alert) Message_Report::getLastAlert (const Message_Gravity theGravity) +{ + 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 +374,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..c3b8edf19a 100644 --- a/src/Message/Message_Report.hxx +++ b/src/Message/Message_Report.hxx @@ -21,9 +21,11 @@ #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. //! @@ -58,6 +60,15 @@ public: //! 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 +105,62 @@ 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 state whether the time of each alert should be stored + //! \param theValue boolean state + //! \return the previous state + Standard_EXPORT void UsePerfMeter (const Standard_Boolean theValue) + { myIsUsePerfMeter = theValue; } + + //! Returns a state whether the time of each alert is stored + //! \return the state + Standard_EXPORT Standard_Boolean IsUsePerfMeter () const + { return myIsUsePerfMeter; } + + //! 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; } + + //! 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); + 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]; + Standard_Boolean myIsUsePerfMeter; //! If true, each alert will store time + 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/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..2a6f29f22d --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.cxx @@ -0,0 +1,20 @@ +// 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) diff --git a/src/TopoDS/TopoDS_AlertAttribute.hxx b/src/TopoDS/TopoDS_AlertAttribute.hxx new file mode 100644 index 0000000000..ed82829e91 --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.hxx @@ -0,0 +1,43 @@ +// 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_Attribute +{ +public: + //! Constructor with shape argument + TopoDS_AlertAttribute (const TopoDS_Shape& theShape, + const TCollection_AsciiString& theName = TCollection_AsciiString(), + const TCollection_AsciiString& theDescription = TCollection_AsciiString()) + : Message_Attribute (theName, theDescription), myShape (theShape) {} + + //! Returns contained shape + const TopoDS_Shape& GetShape() const { return myShape; } + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute) + +private: + TopoDS_Shape myShape; +}; + + +#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..8a3512f1e5 --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx @@ -0,0 +1,374 @@ +// 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->GetCumulativeTime()); + + 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_AttributeVectorOfReal)->Name()) + { + Handle(Message_AttributeVectorOfReal) aRealArrayAlert = Handle(Message_AttributeVectorOfReal)::DownCast (anAttribute); + // store values + const NCollection_Vector& anArrayValues = aRealArrayAlert->GetValues(); + // create real list attribute only if there are values in the attribute + if (anArrayValues.IsEmpty()) + return; + int anArraySize = anArrayValues.Length(); + Handle(TDataStd_RealArray) aRealListAttribute = TDataStd_RealArray::Set (theAlertLabel, 0, anArraySize - 1); + for (int aValueId = 0; aValueId < anArraySize; aValueId++) + aRealListAttribute->SetValue (aValueId, anArrayValues.Value (aValueId)); + } + else if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeVectorOfRealVec3)->Name()) + { + Handle(Message_AttributeVectorOfRealVec3) aRealArrayAlert = Handle(Message_AttributeVectorOfRealVec3)::DownCast (anAttribute); + // store values + const NCollection_Vector>& anArrayValues = aRealArrayAlert->GetValues(); + // create real list attribute only if there are values in the attribute + if (anArrayValues.IsEmpty()) + return; + int anArraySize = anArrayValues.Length(); + Handle(TDataStd_RealArray) aRealListAttribute = TDataStd_RealArray::Set (theAlertLabel, 0, 3 * anArraySize - 1); + for (int aValueId = 0; aValueId < anArraySize; aValueId++) + { + NCollection_Vec3 aValue = anArrayValues.Value (aValueId); + aRealListAttribute->SetValue (3 * aValueId, aValue.x()); + aRealListAttribute->SetValue (3 * aValueId + 1, aValue.y()); + aRealListAttribute->SetValue (3 * aValueId + 2, aValue.z()); + } + } +} + +// ======================================================================= +// 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_AttributeVectorOfReal)->Name()) + { + // values + NCollection_Vector anArrayValues; + if (!aParametersLabel.FindAttribute (TDataStd_RealArray::GetID(), anAttribute)) + return Handle(Message_Alert)(); + + Handle(TDataStd_RealArray) aValuesAttribute = Handle(TDataStd_RealArray)::DownCast (anAttribute); + if (aValuesAttribute.IsNull()) + return Handle(Message_Alert)(); + + for (int aValueId = aValuesAttribute->Lower(); aValueId <= aValuesAttribute->Upper(); aValueId++) + anArrayValues.Append (aValuesAttribute->Value (aValueId)); + + aMessageAttribute = new Message_AttributeVectorOfReal (anArrayValues); + } + else if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeVectorOfRealVec3)->Name()) + { + // values + NCollection_Vector> anArrayValues; + if (!aParametersLabel.FindAttribute(TDataStd_RealArray::GetID(), anAttribute)) + return Handle(Message_Alert)(); + + Handle(TDataStd_RealArray) aValuesAttribute = Handle(TDataStd_RealArray)::DownCast (anAttribute); + if (aValuesAttribute.IsNull()) + return Handle(Message_Alert)(); + + for (int aValueId = aValuesAttribute->Lower(); aValueId <= aValuesAttribute->Upper(); + aValueId = aValueId + 3) + { + NCollection_Vec3 aValue (aValuesAttribute->Value (aValueId), + aValuesAttribute->Value (aValueId + 1), + aValuesAttribute->Value (aValueId + 2)); + anArrayValues.Append (aValue); + } + aMessageAttribute = new Message_AttributeVectorOfRealVec3 (anArrayValues); + } + + 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->SetCumulativeTime (aTime); + return anAlert; +} 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..10dbf13fbe --- /dev/null +++ b/tools/MessageModel/FILES @@ -0,0 +1,22 @@ +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_TableModelRealValues.cxx +MessageModel_TableModelRealValues.hxx +MessageModel_TableModelRealVec3Values.cxx +MessageModel_TableModelRealVec3Values.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..b8cc9bd31c --- /dev/null +++ b/tools/MessageModel/MessageModel.qrc @@ -0,0 +1,7 @@ + + + icons/item_shape.png + icons/item_vectorOfReal.png + icons/item_vectorOfRealVec3.png + + diff --git a/tools/MessageModel/MessageModel_ActionType.hxx b/tools/MessageModel/MessageModel_ActionType.hxx new file mode 100644 index 0000000000..d5092aa08e --- /dev/null +++ b/tools/MessageModel/MessageModel_ActionType.hxx @@ -0,0 +1,27 @@ +// 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_ExportToShapeView //!< export TopoDS_Shape of selected item into TKShapeView plugin +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Actions.cxx b/tools/MessageModel/MessageModel_Actions.cxx new file mode 100644 index 0000000000..57fde16fa5 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.cxx @@ -0,0 +1,221 @@ +// 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 + +// ======================================================================= +// 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_ExportToShapeView, + ViewControl_Tools::CreateAction (tr ("Export to ShapeView"), SLOT (OnExportToShapeView()), parent(), this)); +} + +// ======================================================================= +// function : GetAction +// purpose : +// ======================================================================= +QAction* MessageModel_Actions::GetAction (const MessageModel_ActionType& theType) +{ + if (myActions.contains (theType)) + return myActions[theType]; + + return 0; +} + +// ======================================================================= +// function : AddMenuActions +// purpose : +// ======================================================================= +void MessageModel_Actions::AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu) +{ + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + MessageModel_ItemAlertPtr anAlertItem; + for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin(); aSelIt != theSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + + anAlertItem = itemDynamicCast (anItemBase); + if (anAlertItem) + break; + } + + if (aReportItem && !aReportItem->GetReport().IsNull()) + { + theMenu->addAction (myActions[MessageModel_ActionType_Deactivate]); + theMenu->addAction (myActions[MessageModel_ActionType_Activate]); + } + 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)->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)->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(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast (anAlert); + if (aShapeAlert.IsNull() || aShapeAlert->GetShape().IsNull()) + continue; + + const TopoDS_Shape aShape = aShapeAlert->GetShape(); + if (aShape.IsNull()) + continue; + aPluginParameters.Append (aShape.TShape()); + anItemNames.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape)); + + anExportedPointers.append (MessageModel_Tools::GetPointerInfo (aShape.TShape(), true).ToCString()); + } + + if (anExportedPointers.empty()) + return; + myParameters->SetSelectedNames (aPluginName, anItemNames); + myParameters->SetParameters (aPluginName, aPluginParameters); + QMessageBox::information (0, "Information", QString ("TShapes '%1' are sent to %2 tool.") + .arg (anExportedPointers.join (", ")).arg (QString (aPluginName.ToCString()))); +} diff --git a/tools/MessageModel/MessageModel_Actions.hxx b/tools/MessageModel/MessageModel_Actions.hxx new file mode 100644 index 0000000000..3315a9f652 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.hxx @@ -0,0 +1,97 @@ +// 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 + +#ifdef _MSC_VER + #pragma warning(disable : 4127 4718) // conditional expression is constant, recursive call has no side effects +#endif + +#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(); + + //! Exports the first selected shape into ShapeViewer plugin. + void OnExportToShapeView(); + +protected: + //! Returns report of selected tree view item if a report item is selected + //! \param theReportIndex tree model index of the found report + //! \return report instance or NULL + Handle(Message_Report) getSelectedReport (QModelIndex& theReportIndex) const; + +protected: + MessageModel_TreeModel* myTreeModel; //< tree model + QItemSelectionModel* mySelectionModel; //< selection model + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + QMap myActions; //!< container of all actions +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemAlert.cxx b/tools/MessageModel/MessageModel_ItemAlert.cxx new file mode 100644 index 0000000000..f149cf5711 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.cxx @@ -0,0 +1,342 @@ +// 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 + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemAlert::initValue (const int theRole) const +{ + if (theRole == Qt::ForegroundRole) + { + MessageModel_ItemReportPtr aReportItem = MessageModel_ItemReport::FindReportItem (Parent()); + if (!aReportItem) + return QVariant(); + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport.IsNull()) + return QVariant(); + + 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(); + if (anAlert.IsNull()) + return QVariant(); + + // if the alert is composite, process the real alert + if (theRole == Qt::DecorationRole && Column() == 0) + { + if (anAlert->IsKind (STANDARD_TYPE (TopoDS_AlertWithShape))) + return QIcon (":/icons/item_shape.png"); + else if (anAlert->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + return QIcon (":/icons/item_vectorOfReal.png"); + else if (anAlert->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + return QIcon (":/icons/item_vectorOfRealVec3.png"); + else + return QVariant(); + } + + if (theRole != Qt::DisplayRole && theRole != Qt::ToolTipRole) + return QVariant(); + + const Message_ListOfAlert& aUnitedAlerts = GetUnitedAlerts(); + if (anAlert.IsNull() && !aUnitedAlerts.IsEmpty()) // give information about last united alert + anAlert = !isReversed() ? aUnitedAlerts.Last() : aUnitedAlerts.First(); + 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 3: return AmountElapsedTime (anAlert); + case 4: + { + TreeModel_ItemBasePtr aParentItem = Parent(); + MessageModel_ItemReportPtr aReportItem = itemDynamicCast (aParentItem); + while (!aReportItem) + { + aParentItem = aParentItem->Parent(); + aReportItem = itemDynamicCast (aParentItem); + } + double aDivideTo = MessageModel_ItemReport::AmountElapsedTime (aReportItem->GetReport()); + return aDivideTo == 0 ? QVariant() : 100. * AmountElapsedTime (anAlert) / aDivideTo; + } + case 5: return MessageModel_Tools::GetPointerAlertInfo (anAlert).ToCString(); + case 6: return MessageModel_Tools::GetShapeTypeAlertInfo (anAlert).ToCString(); + case 7: return MessageModel_Tools::GetStandardTypeAlertInfo (anAlert).ToCString(); + case 8: + { + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + 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 GetUnitedAlerts().Size(); + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + if (anExtendedAlert.IsNull()) + return GetUnitedAlerts().Size(); + + Handle(Message_CompositeAlerts) aCompositeAlert = anExtendedAlert->GetCompositeAlerts(); + if (aCompositeAlert.IsNull()) + return GetUnitedAlerts().Size(); + + int aRowCount = 0; + NCollection_Vector aUnitedAlerts; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aCompositeAlert->GetAlerts ((Message_Gravity)aGravityId); + if (isUniteAlerts()) + GetUnitedAlerts (anAlerts, aUnitedAlerts); + else + aRowCount += anAlerts.Size(); + } + return isUniteAlerts() ? aUnitedAlerts.Size() : aRowCount; +} + +// ======================================================================= +// 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_Report) aReport; + Handle(Message_Alert) anAlert; + if (aReportItem) + aReport = aReportItem->GetReport(); + else + { + anAlertItem = itemDynamicCast (Parent()); + if (anAlertItem) + anAlert = anAlertItem->GetAlert(); + } + if (aReport.IsNull() && anAlert.IsNull() && !anAlertItem) + return; + + if (anAlert.IsNull() && anAlertItem) // union folder item + { + int aCurrentSubId = 0; + for (Message_ListOfAlert::Iterator anAlertsIt (anAlertItem->GetUnitedAlerts()); anAlertsIt.More(); + anAlertsIt.Next(), aCurrentSubId++) + { + if (aCurrentSubId != Row()) + continue; + myAlert = anAlertsIt.Value(); + MessageModel_ItemBase::Init(); + return; + } + return; + } + + // iterates through all gravity types, skip types where report is empty, if report is not empty, increment + // current index until it equal to the current row index + Message_ListOfAlert anAlerts; + NCollection_Vector aUnitedAlerts; + int aRowId = Row(); + int aPreviousAlertsCount = 0; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + if (!aReport.IsNull()) + anAlerts = aReport->GetAlerts ((Message_Gravity)aGravityId); + else if (!anAlert.IsNull()) + { + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + Handle(Message_CompositeAlerts) aCompositeAlert = !anExtendedAlert.IsNull() ? anExtendedAlert->GetCompositeAlerts() + : Handle(Message_CompositeAlerts)(); + if (!aCompositeAlert.IsNull()) + anAlerts = aCompositeAlert->GetAlerts ((Message_Gravity)aGravityId); + } + + if (isReversed()) + anAlerts.Reverse(); + + if (isUniteAlerts()) + { + GetUnitedAlerts (anAlerts, aUnitedAlerts); + if (aRowId < aUnitedAlerts.Size()) + { + anAlerts = aUnitedAlerts.Value (aRowId); + + if (anAlerts.Size() == 1) + myAlert = anAlerts.First(); + else + myUnitedAlerts = anAlerts; + + MessageModel_ItemBase::Init(); + return; + } + } + else + { + if (aRowId < aPreviousAlertsCount + anAlerts.Size()) + { + aRowId = aRowId - aPreviousAlertsCount; + int aCurrentId = 0; + for (Message_ListOfAlert::Iterator anAlertsIt (anAlerts); anAlertsIt.More(); anAlertsIt.Next(), aCurrentId++) + { + if (aCurrentId != Row()) + continue; + myAlert = anAlertsIt.Value(); + MessageModel_ItemBase::Init(); + return; + } + } + aPreviousAlertsCount += anAlerts.Size(); + } + } +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::Reset() +{ + MessageModel_ItemBase::Reset(); + myAlert = Handle(Message_Alert)(); + myUnitedAlerts.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; +} + +// ======================================================================= +// function : getUnitedAlerts +// purpose : +// ======================================================================= +const Message_ListOfAlert& MessageModel_ItemAlert::getUnitedAlerts() const +{ + initItem(); + return myUnitedAlerts; +} + +// ======================================================================= +// function : AmountElapsedTime +// purpose : +// ======================================================================= +double MessageModel_ItemAlert::AmountElapsedTime(const Handle(Message_Alert)& theAlert) +{ + if (theAlert.IsNull()) + return 0; + + double anAmountTime = 0; + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(theAlert); + if (anExtendedAlert->GetCumulativeTime() > 0) + anAmountTime = anExtendedAlert->GetCumulativeTime(); + + return anAmountTime; +} + +// ======================================================================= +// function : GetUnitedAlerts +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::GetUnitedAlerts(const Message_ListOfAlert& theAlerts, + NCollection_Vector& theUnitedAlerts) +{ + //theUnitedAlerts.Clear(); + TCollection_AsciiString anAlertMessageKey; + for (Message_ListOfAlert::Iterator anAlertsIt (theAlerts); anAlertsIt.More(); anAlertsIt.Next()) + { + Handle(Message_Alert) anAlert = anAlertsIt.Value(); + if (anAlertMessageKey.IsEqual (anAlert->GetMessageKey())) { + Message_ListOfAlert anAlerts = theUnitedAlerts.Last(); + anAlerts.Append (anAlert); + theUnitedAlerts.SetValue(theUnitedAlerts.Size()-1, anAlerts); + } + else { + Message_ListOfAlert anAlerts; + anAlerts.Append (anAlert); + theUnitedAlerts.Append (anAlerts); + anAlertMessageKey = anAlert->GetMessageKey(); + } + } +} diff --git a/tools/MessageModel/MessageModel_ItemAlert.hxx b/tools/MessageModel/MessageModel_ItemAlert.hxx new file mode 100644 index 0000000000..9fda8eeddc --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.hxx @@ -0,0 +1,128 @@ +// 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 + +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 united alerts or empty list + const Message_ListOfAlert& GetUnitedAlerts() const { return myUnitedAlerts; } + + //! 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; + + //! 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 summ of children alert elapsed times. The method is recusive. + //! \param theAlert a message alert + //! \return double value + Standard_EXPORT static double AmountElapsedTime (const Handle(Message_Alert)& theAlert); + + //! Returns alerts united by Message Key + //! \param theAlerts source message alert + //! \param theUnitedAlerts arranged source message alerts + Standard_EXPORT static void GetUnitedAlerts (const Message_ListOfAlert& theAlerts, + NCollection_Vector & theUnitedAlerts); + +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; + + //! Returns current united alert, initialized item if it has not been initialized yet + //! \return container of united alert value + const Message_ListOfAlert& getUnitedAlerts() const; + + //! Returns summ of children alert elapsed times. The method is recusive. + //! \param theAlert a message alert + //! \return double value + double getAmountElapsedTime() const; + +private: + + //! Constructor + MessageModel_ItemAlert (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn) {} + +private: + Handle(Message_Alert) myAlert; + Message_ListOfAlert myUnitedAlerts; + TopoDS_Shape myCustomShape; +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemBase.cxx b/tools/MessageModel/MessageModel_ItemBase.cxx new file mode 100644 index 0000000000..bf14da937a --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.cxx @@ -0,0 +1,58 @@ +// 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 : isUniteAlerts +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemBase::isUniteAlerts() const +{ + TreeModel_ItemBasePtr aParentItem = GetRootItem(); + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (aParentItem); + return aRootItem ? aRootItem->IsUniteAlerts() : 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..813493411b --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.hxx @@ -0,0 +1,60 @@ +// 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 whether the view is reversed or not + //! \return boolean value + Standard_Boolean isUniteAlerts() 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..07bd1be492 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.cxx @@ -0,0 +1,191 @@ +// 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 : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemReport::initValue (const int theRole) const +{ + 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 3: + { + double anAmountTime = AmountElapsedTime (aReport); + return anAmountTime < 1 ? QVariant() : anAmountTime; + } + case 4: return "100"; + case 8: + { + 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; + + int aRowCount = 0; + NCollection_Vector aUnitedAlerts; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aReport->GetAlerts ((Message_Gravity)aGravityId); + if (isUniteAlerts()) + { + MessageModel_ItemAlert::GetUnitedAlerts (anAlerts, aUnitedAlerts); + aRowCount += aUnitedAlerts.Size(); + } + else + aRowCount += anAlerts.Size(); + } + return isUniteAlerts() ? aUnitedAlerts.Size() : aRowCount; +} + +// ======================================================================= +// 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)(); +} + +// ======================================================================= +// 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)(); +} + +// ======================================================================= +// 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 : AmountElapsedTime +// purpose : +// ======================================================================= +double MessageModel_ItemReport::AmountElapsedTime (const Handle(Message_Report)& theReport) +{ + if (theReport.IsNull()) + return 0; + + double anAmountTime = 0; + + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + for (Message_ListOfAlert::Iterator anAlertsIt (theReport->GetAlerts ((Message_Gravity)aGravityId)); anAlertsIt.More(); anAlertsIt.Next()) + { + double aSubItemTime = MessageModel_ItemAlert::AmountElapsedTime (anAlertsIt.Value()); + if (aSubItemTime > 0) + anAmountTime += aSubItemTime; + } + } + return anAmountTime; +} diff --git a/tools/MessageModel/MessageModel_ItemReport.hxx b/tools/MessageModel/MessageModel_ItemReport.hxx new file mode 100644 index 0000000000..067861daec --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.hxx @@ -0,0 +1,106 @@ +// 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 + +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; } + + 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 summ of children alert elapsed times. The method is recusive. + //! \param theAlert a message alert + //! \return double value + Standard_EXPORT static double AmountElapsedTime (const Handle(Message_Report)& theReport); + +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: + + 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..3d46c1f61c --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.cxx @@ -0,0 +1,77 @@ +// 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 : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemRoot::initValue (const int theRole) const +{ + 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..337576e21d --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.hxx @@ -0,0 +1,127 @@ +// 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 = ""); + + //! 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 SetUniteAlerts (const Standard_Boolean& theUniteAlerts) { myIsUniteAlerts = theUniteAlerts; } + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsUniteAlerts() const { return myIsUniteAlerts; }; + + //! 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 + Standard_Boolean myIsUniteAlerts; //!< state whether equal named alerts should be united in a folder + 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..d59fea8ba2 --- /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_TableModelRealValues.cxx b/tools/MessageModel/MessageModel_TableModelRealValues.cxx new file mode 100644 index 0000000000..0e16f14c30 --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealValues.cxx @@ -0,0 +1,106 @@ +// 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 + +const int REAL_SIGNS = 16; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= + +MessageModel_TableModelRealValues::MessageModel_TableModelRealValues (const Handle(Message_Attribute)& theAttribute, + const int theSectionWidth) + : myAttribute (Handle(Message_AttributeVectorOfReal)::DownCast (theAttribute)) +{ + SetUseTableProperties (true); + SetUseTablePropertiesXStep (true, -1); + + SetDefaultSectionSize (Qt::Horizontal, theSectionWidth); +} + +// ======================================================================= +// function : ColumnCount +// purpose : +// ======================================================================= + +int MessageModel_TableModelRealValues::ColumnCount (const QModelIndex&) const +{ + return myAttribute->GetValues().Length(); +} + +// ======================================================================= +// function : Data +// purpose : +// ======================================================================= + +QVariant MessageModel_TableModelRealValues::Data (const int, const int theColumn, int theRole) const +{ + if (theRole == Qt::DisplayRole && theColumn < myAttribute->GetValues().Length()) + { + return myAttribute->GetValues().Value(theColumn); + } + + return QVariant(); +} + +// ======================================================================= +// function : GetRangeValues +// purpose : +// ======================================================================= + +void MessageModel_TableModelRealValues::GetRangeValues (QString& theMinValue, QString& theMaxValue, const QModelIndexList& theSelected) const +{ + double aMinValue, aMaxValue; + aMinValue = DBL_MAX; + aMaxValue = DBL_MIN; + + NCollection_Vector aValues = myAttribute->GetValues(); + int aValuesSize = aValues.Length(); + if (aValuesSize < 1) + return; + + if (theSelected.isEmpty()) + { + aMinValue = aMaxValue = aValues.First(); + for (int i = 1; i < aValuesSize; i++) + { + double aValue = aValues.Value (i); + if (aValue < aMinValue) aMinValue = aValue; + if (aValue > aMaxValue) aMaxValue = aValue; + } + } + else + { + ViewControl_TableModel* aModel = (ViewControl_TableModel*)theSelected[0].model(); + int aRow, aColumn; + for (QModelIndexList::const_iterator aSelIt = theSelected.begin(); aSelIt != theSelected.end(); aSelIt++) + { + aModel->GetSourcePosition (*aSelIt, aRow, aColumn); + if (aColumn >= aValuesSize) + continue; + + double aValue = aValues.Value (aColumn); + if (aValue < aMinValue) aMinValue = aValue; + if (aValue > aMaxValue) aMaxValue = aValue; + } + } + + theMinValue = QString::number(aMinValue, 'g', REAL_SIGNS); + theMaxValue = QString::number(aMaxValue, 'g', REAL_SIGNS); +} diff --git a/tools/MessageModel/MessageModel_TableModelRealValues.hxx b/tools/MessageModel/MessageModel_TableModelRealValues.hxx new file mode 100644 index 0000000000..346b3bb7c5 --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealValues.hxx @@ -0,0 +1,66 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_TableModelRealValues_H +#define MessageModel_TableModelRealValues_H + +#ifdef _MSC_VER + #pragma warning(disable : 4127 4718) // conditional expression is constant, recursive call has no side effects +#endif + +#include + +#include + +//! \class MessageModel_TableModelRealValues +//! \brief This is an implementation for ViewControl_TableModel to present Message_AttributeVectorOfReal object +class MessageModel_TableModelRealValues : public ViewControl_TableModelValues +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TableModelRealValues (const Handle(Message_Attribute)& theAttribute, const int theSectionWidth); + + //! Destructor + virtual ~MessageModel_TableModelRealValues() Standard_OVERRIDE {} + + //! Returns number of columns, size of header values + //! \param theParent an index of the parent item + //! \return an integer value + Standard_EXPORT virtual int ColumnCount (const QModelIndex& theParent = QModelIndex()) const; + + //! Returns number of rows, depending on orientation: myColumnCount or size of values container + //! \param theParent an index of the parent item + //! \return an integer value + virtual int RowCount (const QModelIndex& theParent = QModelIndex()) const { (void)theParent; return 1; } + + //! Returns content of the model index for the given role, it is obtained from internal container of values + //! It returns value only for DisplayRole. + //! \param theIndex a model index + //! \param theRole a view role + //! \return value intepreted depending on the given role + Standard_EXPORT virtual QVariant Data (const int theRow, const int theColumn, int theRole = Qt::DisplayRole) const; + + //! Returns minimum and maximum values of selected items or the table content (if selected list is empty) + //! \param theMinValue minimum + //! \param theMaxValue maximum + //! \param theSelected selected cells + virtual void GetRangeValues (QString& theMinValue, QString& theMaxValue, const QModelIndexList& theSelected) const; + +private: + Handle(Message_AttributeVectorOfReal) myAttribute; //!< alert attribute, container of table values +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx b/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx new file mode 100644 index 0000000000..1e653f0d8d --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx @@ -0,0 +1,122 @@ +// 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 : Constructor +// purpose : +// ======================================================================= + +MessageModel_TableModelRealVec3Values::MessageModel_TableModelRealVec3Values (const Handle(Message_Attribute)& theAttribute, + const int theSectionWidth) + : myAttribute (Handle(Message_AttributeVectorOfRealVec3)::DownCast (theAttribute)) +{ + SetUseTableProperties (true); + + SetDefaultSectionSize (Qt::Horizontal, theSectionWidth); +} + +// ======================================================================= +// function : ColumnCount +// purpose : +// ======================================================================= + +int MessageModel_TableModelRealVec3Values::ColumnCount (const QModelIndex&) const +{ + return myAttribute->GetValues().Length(); +} + +// ======================================================================= +// function : Data +// purpose : +// ======================================================================= + +QVariant MessageModel_TableModelRealVec3Values::Data (const int, const int theColumn, int theRole) const +{ + if (theRole != Qt::DisplayRole || theColumn > myAttribute->GetValues().Length()) + return QVariant(); + + NCollection_Vec3 aValue = myAttribute->GetValues().Value(theColumn); + return QString ("%1, %2, %3").arg (aValue.x()).arg (aValue.y()).arg (aValue.z()); +} + +// ======================================================================= +// function : GetRangeValues +// purpose : +// ======================================================================= + +void MessageModel_TableModelRealVec3Values::GetRangeValues (QString& theMinValue, QString& theMaxValue, + const QModelIndexList& theSelected) const +{ + theMinValue = DBL_MAX; + theMaxValue = DBL_MIN; + + QList aValuePositions; + if (!theSelected.isEmpty()) + { + ViewControl_TableModel* aModel = (ViewControl_TableModel*)theSelected[0].model(); + int aRow, aColumn; + for (QModelIndexList::const_iterator aSelIt = theSelected.begin(); aSelIt != theSelected.end(); aSelIt++) + { + aModel->GetSourcePosition (*aSelIt, aRow, aColumn); + aValuePositions.append (aColumn); + } + } + + NCollection_Vector> aValues = myAttribute->GetValues(); + int aValuesSize = aValues.Length(); + if (aValuesSize < 1) + return; + + double aXMinValue = aValues.First().x(), aXMaxValue = aValues.First().x(); + NCollection_Vec3 aValue; + for (int i = 1; i < aValuesSize; i++) + { + if (!aValuePositions.empty() && !aValuePositions.contains (i)) + continue; + + aValue = aValues.Value (i); + if (aValue.x() < aXMinValue) aXMinValue = aValue.x(); + if (aValue.x() > aXMaxValue) aXMaxValue = aValue.x(); + } + + double anYMinValue = aValues.First().y(), anYMaxValue = aValues.First().y(); + for (int i = 1; i < aValuesSize; i++) + { + if (!aValuePositions.empty() && !aValuePositions.contains (i)) + continue; + + aValue = aValues.Value (i); + if (aValue.x() == aXMinValue && aValue.y() < anYMinValue) anYMinValue = aValue.y(); + if (aValue.x() == aXMaxValue && aValue.y() > anYMaxValue) anYMaxValue = aValue.y(); + } + + double aZMinValue = aValues.First().z(), aZMaxValue = aValues.First().z(); + for (int i = 1; i < aValuesSize; i++) + { + if (!aValuePositions.empty() && !aValuePositions.contains (i)) + continue; + aValue = aValues.Value (i); + if (aValue.x() == aXMinValue && aValue.y() == anYMinValue && aValue.z() < aZMinValue) aZMinValue = aValue.z(); + if (aValue.x() == aXMaxValue && aValue.y() == anYMaxValue && aValue.z() > aZMaxValue) aZMaxValue = aValue.z(); + } + + theMinValue = QString ("%1, %2, %3").arg (aXMinValue).arg (anYMinValue).arg (aZMinValue); + theMaxValue = QString ("%1, %2, %3").arg (aXMaxValue).arg (anYMaxValue).arg (aZMaxValue); +} diff --git a/tools/MessageModel/MessageModel_TableModelRealVec3Values.hxx b/tools/MessageModel/MessageModel_TableModelRealVec3Values.hxx new file mode 100644 index 0000000000..d10a1de91c --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealVec3Values.hxx @@ -0,0 +1,67 @@ +// 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_TableModelRealVec3Values_H +#define MessageModel_TableModelRealVec3Values_H + +#ifdef _MSC_VER + #pragma warning(disable : 4127 4718) // conditional expression is constant, recursive call has no side effects +#endif + +#include + +#include + +//! \class MessageModel_TableModelRealVec3Values +//! \brief This is an implementation for ViewControl_TableModel to present Message_AttributeVectorOfRealVec3 object +class MessageModel_TableModelRealVec3Values : public ViewControl_TableModelValues +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TableModelRealVec3Values (const Handle(Message_Attribute)& theAttribute, const int theSectionWidth); + + //! Destructor + virtual ~MessageModel_TableModelRealVec3Values() Standard_OVERRIDE {} + + //! Returns number of columns, size of header values + //! \param theParent an index of the parent item + //! \return an integer value + Standard_EXPORT virtual int ColumnCount (const QModelIndex& theParent = QModelIndex()) const; + + //! Returns number of rows, depending on orientation: myColumnCount or size of values container + //! \param theParent an index of the parent item + //! \return an integer value + virtual int RowCount (const QModelIndex& theParent = QModelIndex()) const { (void)theParent; return 1; } + + //! Returns content of the model index for the given role, it is obtained from internal container of values + //! It returns value only for DisplayRole. + //! \param theIndex a model index + //! \param theRole a view role + //! \return value intepreted depending on the given role + Standard_EXPORT virtual QVariant Data (const int theRow, const int theColumn, int theRole = Qt::DisplayRole) const; + + //! Returns minimum and maximum values of selected items or the table content (if selected list is empty) + //! It finds firstly Xmax, then Ymax, after that Zmax. The same for min values. + //! \param theMinValue minimum + //! \param theMaxValue maximum + //! \param theSelected selected cells + virtual void GetRangeValues (QString& theMinValue, QString& theMaxValue, const QModelIndexList& theSelected) const; + +private: + Handle(Message_AttributeVectorOfRealVec3) myAttribute; //!< alert attribute, container of table values +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Tools.cxx b/tools/MessageModel/MessageModel_Tools.cxx new file mode 100644 index 0000000000..569eabf937 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.cxx @@ -0,0 +1,239 @@ +// 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 + +// ======================================================================= +// 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) +{ + if (theAlert->IsKind (STANDARD_TYPE (TopoDS_AlertWithShape))) + return GetPointerInfo (Handle(TopoDS_AlertWithShape)::DownCast (theAlert)->GetShape().TShape()); + else if (theAlert->IsKind (STANDARD_TYPE (Message_AttributeObject))) + return GetPointerInfo (Handle(Message_AttributeObject)::DownCast (theAlert)->GetObject()); + return TCollection_AsciiString(); +} + +// ======================================================================= +// function : GetShapeTypeAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetShapeTypeAlertInfo (const Handle(Message_Alert)& theAlert) +{ + TopoDS_Shape aShape; + + if (theAlert->IsKind (STANDARD_TYPE (TopoDS_AlertWithShape))) + aShape = Handle(TopoDS_AlertWithShape)::DownCast (theAlert)->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(Standard_Transient) aPointer; + if (theAlert->IsKind (STANDARD_TYPE (TopoDS_AlertWithShape))) + aPointer = Handle(TopoDS_AlertWithShape)::DownCast (theAlert)->GetShape().TShape(); + else if (theAlert->IsKind (STANDARD_TYPE (Message_AttributeObject))) + aPointer = Handle(Message_AttributeObject)::DownCast (theAlert)->GetObject(); + + if (aPointer.IsNull()) + return TCollection_AsciiString(); + + return aPointer->DynamicType()->Name(); +} + +// ======================================================================= +// function : GetPropertyTableValues +// purpose : +// ======================================================================= +void MessageModel_Tools::GetPropertyTableValues (const Handle(Message_Alert)& theAlert, + QList& theTableValues) +{ + ViewControl_TableModelValues* aTableValues = 0; + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(theAlert); + if (anExtendedAlert.IsNull()) + return; + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return; + + if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + { + int aSectionSize = 60; + aTableValues = new MessageModel_TableModelRealValues (anAttribute, aSectionSize); + theTableValues.append (aTableValues); + } + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + { + int aSectionSize = 160; + aTableValues = new MessageModel_TableModelRealVec3Values (anAttribute, aSectionSize); + theTableValues.append (aTableValues); + } + else + { + if (!anAttribute->GetDescription().IsEmpty()) + { + aTableValues = new ViewControl_TableModelValues(); + 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); + } + } +} + +// ======================================================================= +// function : BuildShape +// purpose : +// ======================================================================= +TopoDS_Shape MessageModel_Tools::BuildShape (const Handle(Message_Alert)& theAlert, QList theSelectedIndices, ViewControl_Table* theTable) +{ + if (theAlert.IsNull()) + return TopoDS_Shape(); + + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound(aCompound); + + if (theAlert->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + { + Handle(Message_AttributeVectorOfReal) aValuesAlert = Handle(Message_AttributeVectorOfReal)::DownCast (theAlert); + NCollection_Vector aValues = aValuesAlert->GetValues(); + int aValuesSize = aValues.Size(); + + gp_Pnt aPreviousPoint(0, 0, 0), aCurrentPoint(0, 0, 0); + double aXStep = theTable->GetProperty()->GetXStep(); + if (aXStep < 0) + aXStep = 1; + double aCurrentXValue = 0; + for (QList::const_iterator anIt = theSelectedIndices.begin(); anIt != theSelectedIndices.end(); anIt++) + { + if (*anIt >= aValuesSize) + continue; + + if (aCurrentXValue == 0) + { //just define the previous point + aPreviousPoint.SetX (aCurrentXValue); + aPreviousPoint.SetY (aValues.Value (*anIt)); + aCurrentXValue = aCurrentXValue + aXStep; + continue; + } + aCurrentPoint.SetX (aCurrentXValue); + aCurrentPoint.SetY (aValues.Value (*anIt)); + if (aPreviousPoint.Distance (aCurrentPoint) < Precision::Confusion()) + continue; + + TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge (aPreviousPoint, aCurrentPoint); + aBuilder.Add (aCompound, anEdge); + aPreviousPoint = aCurrentPoint; + aCurrentXValue = aCurrentXValue + aXStep; + } + } + else if (theAlert->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + { + Handle(Message_AttributeVectorOfRealVec3) aValuesAlert = Handle(Message_AttributeVectorOfRealVec3)::DownCast (theAlert); + NCollection_Vector> aValues = aValuesAlert->GetValues(); + int aValuesSize = aValues.Size(); + + gp_Pnt aCurrentPoint(0, 0, 0); + NCollection_Vec3 aValue; + for (QList::const_iterator anIt = theSelectedIndices.begin(); anIt != theSelectedIndices.end(); anIt++) + { + if (*anIt >= aValuesSize) + continue; + + aValue = aValues.Value (*anIt); + aCurrentPoint.SetX (aValue.x()); + aCurrentPoint.SetY (aValue.y()); + aCurrentPoint.SetZ (aValue.z()); + + TopoDS_Vertex aVertex = BRepBuilderAPI_MakeVertex (aCurrentPoint); + aBuilder.Add (aCompound, aVertex); + } + } + + return aCompound; +} diff --git a/tools/MessageModel/MessageModel_Tools.hxx b/tools/MessageModel/MessageModel_Tools.hxx new file mode 100644 index 0000000000..58c86a601f --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.hxx @@ -0,0 +1,75 @@ +// 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 + +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 Handle(Message_Alert)& theAlert, + QList& theTableValues); + + //! Creates TopoDS_Compound with TopoDS_Edge/Vertex on alert data + //! \param theAlert a message alert + //! \parm theSelectedIndices a container of indices + //! \param theTableView source view + Standard_EXPORT TopoDS_Shape static BuildShape (const Handle(Message_Alert)& theAlert, QList aSelectedIndices, + ViewControl_Table* theTableView); +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TreeModel.cxx b/tools/MessageModel/MessageModel_TreeModel.cxx new file mode 100644 index 0000000000..84775c4186 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.cxx @@ -0,0 +1,155 @@ +// 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), myIsUniteAlerts (Standard_False) +{ + SetHeaderItem (0, TreeModel_HeaderSection ("Name", COLUMN_NAME_WIDTH)); + // column 1 is reserved for visiblity state + SetHeaderItem (2, TreeModel_HeaderSection ("Size", COLUMN_SIZE_WIDTH)); + + SetHeaderItem (3, TreeModel_HeaderSection ("Whole Time", -1)); + SetHeaderItem (4, TreeModel_HeaderSection ("Percent", -1)); + + SetHeaderItem (5, TreeModel_HeaderSection ("Pointer", COLUMN_POINTER_WIDTH)); + SetHeaderItem (6, TreeModel_HeaderSection ("Shape Type", COLUMN_SHAPE_TYPE_WIDTH)); + SetHeaderItem (7, TreeModel_HeaderSection ("Standard Type", COLUMN_STANDARD_TYPE_WIDTH)); + SetHeaderItem (8, 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 : 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); + aRootItem->SetUniteAlerts (myIsUniteAlerts); + } + + 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 : SetUniteAlerts +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetUniteAlerts (const Standard_Boolean& theUniteAlerts) +{ + myIsUniteAlerts = theUniteAlerts; + + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (aRootItem) + aRootItem->SetUniteAlerts (myIsUniteAlerts); + } + + 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..0769fd4473 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.hxx @@ -0,0 +1,95 @@ +// 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 + +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 {}; + + //! 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; }; + + //! Set union of alerts having equal message in additional folder item. + //! \param theUniteAlerts boolean flag + Standard_EXPORT void SetUniteAlerts (const Standard_Boolean& theUniteAlerts); + + //! Return whether the alerts should be united + //! \return boolean value + Standard_Boolean IsUniteAlerts() const { return myIsUniteAlerts; }; + + //! 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 + Standard_Boolean myIsUniteAlerts; //!< state if alerts should be united +}; + +#endif diff --git a/tools/MessageModel/icons/item_shape.png b/tools/MessageModel/icons/item_shape.png new file mode 100644 index 0000000000..a808bc55e5 Binary files /dev/null and b/tools/MessageModel/icons/item_shape.png differ diff --git a/tools/MessageModel/icons/item_shape.svg b/tools/MessageModel/icons/item_shape.svg new file mode 100644 index 0000000000..14313ed68a --- /dev/null +++ b/tools/MessageModel/icons/item_shape.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfReal.png b/tools/MessageModel/icons/item_vectorOfReal.png new file mode 100644 index 0000000000..7181f9460e Binary files /dev/null and b/tools/MessageModel/icons/item_vectorOfReal.png differ 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 0000000000..4d0ebf93d9 Binary files /dev/null and b/tools/MessageModel/icons/item_vectorOfRealVec3.png differ diff --git a/tools/MessageModel/icons/item_vectorOfRealVec3.svg b/tools/MessageModel/icons/item_vectorOfRealVec3.svg new file mode 100644 index 0000000000..4d2d42b17f --- /dev/null +++ b/tools/MessageModel/icons/item_vectorOfRealVec3.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + 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..db75105fc2 --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.cxx @@ -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. + +#include +#include + +#include +#include +#include + +#include + +// ======================================================================= +// function : CanBeVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::CanBeVisible (const QModelIndex& theIndex) const +{ + 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_AttributeVectorOfReal)) || anAlert->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + 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..1f778f488e --- /dev/null +++ b/tools/MessageView/MessageView_Window.cxx @@ -0,0 +1,615 @@ +// 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 + +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; + +// ======================================================================= +// 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); + for (int i = 5; i <= 7; 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); + ViewControl_PropertyView::SaveState (myPropertyView, 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; + else if (ViewControl_PropertyView::RestoreState (myPropertyView, 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; + } + // 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; + + 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 + { + aParameters.Append (anObject); + if (aContext.IsNull()) + aContext = Handle(AIS_InteractiveContext)::DownCast (anObject); + } + } + QAbstractItemModel* aModel = myTreeView->model(); + if (!aModel) + return; + MessageModel_TreeModel* aTreeModel = dynamic_cast (aModel); + if (!aTreeModel) + return; + aTreeModel->EmitLayoutChanged(); + + if (!aContext.IsNull()) + myViewWindow->SetContext (View_ContextType_External, aContext); + + 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(); +} + +// ======================================================================= +// 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)); + 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 : 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; + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + if (!anAlertItem) + return; + + QList aTableValues; + MessageModel_Tools::GetPropertyTableValues (anAlertItem->GetAlert(), aTableValues); + + myPropertyView->Init (aTableValues); +} diff --git a/tools/MessageView/MessageView_Window.hxx b/tools/MessageView/MessageView_Window.hxx new file mode 100644 index 0000000000..470ba79054 --- /dev/null +++ b/tools/MessageView/MessageView_Window.hxx @@ -0,0 +1,170 @@ +// 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 + +#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(); + + //! 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(); + +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 +}; + +#endif 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 08e720ae54..ca4b96c779 100644 --- a/tools/ToolsDraw/ToolsDraw.cxx +++ b/tools/ToolsDraw/ToolsDraw.cxx @@ -53,6 +53,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; } @@ -296,6 +297,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(); } @@ -382,7 +384,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."