From babb4d0d805a8463ef8b71a16076e689b46a4780 Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 28 Jun 2018 11:00:39 +0300 Subject: [PATCH] 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) --- adm/TOOLS | 2 +- src/Draw/Draw.cxx | 24 + src/Draw/Draw.hxx | 6 + src/Draw/Draw_Commands.cxx | 1 + src/Draw/Draw_MessageCommands.cxx | 104 +++ src/Draw/Draw_Report.cxx | 50 ++ src/Draw/Draw_Report.hxx | 69 ++ src/Draw/FILES | 3 + src/GeomAbs/FILES | 2 + src/GeomAbs/GeomAbs.cxx | 59 ++ src/GeomAbs/GeomAbs.hxx | 54 ++ src/IntTools/IntTools_FaceFace.cxx | 2 + src/Message/FILES | 19 +- src/Message/Message.cxx | 40 ++ src/Message/Message.hxx | 23 + src/Message/Message_Alert.cxx | 10 + src/Message/Message_Alert.hxx | 5 + src/Message/Message_AlertNode.cxx | 88 +++ src/Message/Message_AlertNode.hxx | 132 ++++ src/Message/Message_Alerts.hxx | 68 ++ src/Message/Message_Attribute.cxx | 43 ++ src/Message/Message_Attribute.hxx | 72 ++ src/Message/Message_AttributeObject.cxx | 51 ++ src/Message/Message_AttributeObject.hxx | 52 ++ src/Message/Message_AttributeVectorOfReal.cxx | 103 +++ src/Message/Message_AttributeVectorOfReal.hxx | 74 ++ .../Message_AttributeVectorOfRealVec3.cxx | 102 +++ .../Message_AttributeVectorOfRealVec3.hxx | 72 ++ src/Message/Message_PerfMeter.cxx | 165 +++++ src/Message/Message_PerfMeter.hxx | 92 +++ src/Message/Message_Report.cxx | 155 +++++ src/Message/Message_Report.hxx | 68 +- src/Message/Message_ReportCallBack.cxx | 22 + src/Message/Message_ReportCallBack.hxx | 44 ++ src/TopoDS/FILES | 2 + src/TopoDS/TopoDS_AlertAttribute.cxx | 43 ++ src/TopoDS/TopoDS_AlertAttribute.hxx | 58 ++ src/XmlDrivers/FILES | 2 + .../XmlDrivers_MessageReportStorage.cxx | 401 +++++++++++ .../XmlDrivers_MessageReportStorage.hxx | 68 ++ tools/CMakeLists.txt | 40 +- tools/DFBrowser/DFBrowser_TreeModel.cxx | 8 +- .../DFBrowserPane_AttributePaneSelector.cxx | 2 + tools/MessageModel/FILES | 24 + tools/MessageModel/MessageModel.qrc | 7 + .../MessageModel/MessageModel_ActionType.hxx | 27 + tools/MessageModel/MessageModel_Actions.cxx | 239 +++++++ tools/MessageModel/MessageModel_Actions.hxx | 95 +++ tools/MessageModel/MessageModel_ItemAlert.cxx | 341 +++++++++ tools/MessageModel/MessageModel_ItemAlert.hxx | 130 ++++ tools/MessageModel/MessageModel_ItemBase.cxx | 58 ++ tools/MessageModel/MessageModel_ItemBase.hxx | 60 ++ .../MessageModel/MessageModel_ItemReport.cxx | 193 ++++++ .../MessageModel/MessageModel_ItemReport.hxx | 108 +++ tools/MessageModel/MessageModel_ItemRoot.cxx | 92 +++ tools/MessageModel/MessageModel_ItemRoot.hxx | 132 ++++ .../MessageModel_ReportCallBack.cxx | 18 + .../MessageModel_ReportCallBack.hxx | 48 ++ .../MessageModel_TableModelCompareValues.cxx | 120 ++++ .../MessageModel_TableModelCompareValues.hxx | 64 ++ .../MessageModel_TableModelRealValues.cxx | 121 ++++ .../MessageModel_TableModelRealValues.hxx | 72 ++ .../MessageModel_TableModelRealVec3Values.cxx | 129 ++++ .../MessageModel_TableModelRealVec3Values.hxx | 76 ++ tools/MessageModel/MessageModel_Tools.cxx | 290 ++++++++ tools/MessageModel/MessageModel_Tools.hxx | 84 +++ tools/MessageModel/MessageModel_TreeModel.cxx | 168 +++++ tools/MessageModel/MessageModel_TreeModel.hxx | 108 +++ tools/MessageModel/icons/item_shape.png | Bin 0 -> 614 bytes tools/MessageModel/icons/item_shape.svg | 122 ++++ .../MessageModel/icons/item_vectorOfReal.png | Bin 0 -> 347 bytes .../MessageModel/icons/item_vectorOfReal.svg | 103 +++ .../icons/item_vectorOfRealVec3.png | Bin 0 -> 421 bytes .../icons/item_vectorOfRealVec3.svg | 124 ++++ tools/MessageView/FILES | 6 + .../MessageView/MessageView_Communicator.cxx | 26 + .../MessageView/MessageView_Communicator.hxx | 68 ++ .../MessageView_VisibilityState.cxx | 141 ++++ .../MessageView_VisibilityState.hxx | 87 +++ tools/MessageView/MessageView_Window.cxx | 649 ++++++++++++++++++ tools/MessageView/MessageView_Window.hxx | 172 +++++ tools/ShapeView/ShapeView_ItemShape.cxx | 27 +- tools/ShapeView/ShapeView_ItemShape.hxx | 13 +- tools/ShapeView/ShapeView_Tools.cxx | 24 + tools/ShapeView/ShapeView_Tools.hxx | 6 + tools/ShapeView/ShapeView_TreeModel.cxx | 7 +- tools/ShapeView/ShapeView_Window.cxx | 90 ++- tools/ShapeView/ShapeView_Window.hxx | 6 + tools/TInspectorEXE/TInspectorEXE.cxx | 4 + tools/TKMessageModel/CMakeLists.txt | 5 + tools/TKMessageModel/EXTERNLIB | 10 + tools/TKMessageModel/FILES | 2 + tools/TKMessageModel/PACKAGES | 1 + tools/TKMessageView/CMakeLists.txt | 5 + tools/TKMessageView/EXTERNLIB | 13 + tools/TKMessageView/FILES | 2 + tools/TKMessageView/PACKAGES | 1 + tools/TKTreeModel/CMakeLists.txt | 2 + tools/ToolsDraw/ToolsDraw.cxx | 4 +- tools/TreeModel/TreeModel_ModelBase.cxx | 31 +- tools/TreeModel/TreeModel_ModelBase.hxx | 8 + tools/VInspector/VInspector_ViewModel.cxx | 6 +- tools/View/View_Tools.cxx | 6 +- tools/View/View_Window.cxx | 47 +- tools/View/View_Window.hxx | 3 + tools/ViewControl/FILES | 15 +- tools/ViewControl/ViewControl.hxx | 33 + .../ViewControl/ViewControl_PropertyView.cxx | 279 ++++++++ .../ViewControl/ViewControl_PropertyView.hxx | 127 ++++ tools/ViewControl/ViewControl_Table.cxx | 137 ++++ tools/ViewControl/ViewControl_Table.hxx | 95 +++ tools/ViewControl/ViewControl_TableModel.cxx | 83 +++ tools/ViewControl/ViewControl_TableModel.hxx | 111 +++ .../ViewControl_TableModelFilter.cxx | 65 ++ .../ViewControl_TableModelFilter.hxx | 76 ++ .../ViewControl_TableModelValues.cxx | 91 +++ .../ViewControl_TableModelValues.hxx | 200 ++++++ .../ViewControl/ViewControl_TableProperty.cxx | 224 ++++++ .../ViewControl/ViewControl_TableProperty.hxx | 141 ++++ tools/ViewControl/ViewControl_Tools.cxx | 35 + tools/ViewControl/ViewControl_Tools.hxx | 6 + upgrade.bat | 23 - 122 files changed, 8793 insertions(+), 73 deletions(-) create mode 100644 src/Draw/Draw_MessageCommands.cxx create mode 100644 src/Draw/Draw_Report.cxx create mode 100644 src/Draw/Draw_Report.hxx create mode 100644 src/GeomAbs/GeomAbs.cxx create mode 100644 src/GeomAbs/GeomAbs.hxx create mode 100644 src/Message/Message_AlertNode.cxx create mode 100644 src/Message/Message_AlertNode.hxx create mode 100644 src/Message/Message_Alerts.hxx create mode 100644 src/Message/Message_Attribute.cxx create mode 100644 src/Message/Message_Attribute.hxx create mode 100644 src/Message/Message_AttributeObject.cxx create mode 100644 src/Message/Message_AttributeObject.hxx create mode 100644 src/Message/Message_AttributeVectorOfReal.cxx create mode 100644 src/Message/Message_AttributeVectorOfReal.hxx create mode 100644 src/Message/Message_AttributeVectorOfRealVec3.cxx create mode 100644 src/Message/Message_AttributeVectorOfRealVec3.hxx create mode 100644 src/Message/Message_PerfMeter.cxx create mode 100644 src/Message/Message_PerfMeter.hxx create mode 100644 src/Message/Message_ReportCallBack.cxx create mode 100644 src/Message/Message_ReportCallBack.hxx create mode 100644 src/TopoDS/TopoDS_AlertAttribute.cxx create mode 100644 src/TopoDS/TopoDS_AlertAttribute.hxx create mode 100644 src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx create mode 100644 src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx create mode 100644 tools/MessageModel/FILES create mode 100644 tools/MessageModel/MessageModel.qrc create mode 100644 tools/MessageModel/MessageModel_ActionType.hxx create mode 100644 tools/MessageModel/MessageModel_Actions.cxx create mode 100644 tools/MessageModel/MessageModel_Actions.hxx create mode 100644 tools/MessageModel/MessageModel_ItemAlert.cxx create mode 100644 tools/MessageModel/MessageModel_ItemAlert.hxx create mode 100644 tools/MessageModel/MessageModel_ItemBase.cxx create mode 100644 tools/MessageModel/MessageModel_ItemBase.hxx create mode 100644 tools/MessageModel/MessageModel_ItemReport.cxx create mode 100644 tools/MessageModel/MessageModel_ItemReport.hxx create mode 100644 tools/MessageModel/MessageModel_ItemRoot.cxx create mode 100644 tools/MessageModel/MessageModel_ItemRoot.hxx create mode 100644 tools/MessageModel/MessageModel_ReportCallBack.cxx create mode 100644 tools/MessageModel/MessageModel_ReportCallBack.hxx create mode 100644 tools/MessageModel/MessageModel_TableModelCompareValues.cxx create mode 100644 tools/MessageModel/MessageModel_TableModelCompareValues.hxx create mode 100644 tools/MessageModel/MessageModel_TableModelRealValues.cxx create mode 100644 tools/MessageModel/MessageModel_TableModelRealValues.hxx create mode 100644 tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx create mode 100644 tools/MessageModel/MessageModel_TableModelRealVec3Values.hxx create mode 100644 tools/MessageModel/MessageModel_Tools.cxx create mode 100644 tools/MessageModel/MessageModel_Tools.hxx create mode 100644 tools/MessageModel/MessageModel_TreeModel.cxx create mode 100644 tools/MessageModel/MessageModel_TreeModel.hxx create mode 100644 tools/MessageModel/icons/item_shape.png create mode 100644 tools/MessageModel/icons/item_shape.svg create mode 100644 tools/MessageModel/icons/item_vectorOfReal.png create mode 100644 tools/MessageModel/icons/item_vectorOfReal.svg create mode 100644 tools/MessageModel/icons/item_vectorOfRealVec3.png create mode 100644 tools/MessageModel/icons/item_vectorOfRealVec3.svg create mode 100644 tools/MessageView/FILES create mode 100644 tools/MessageView/MessageView_Communicator.cxx create mode 100644 tools/MessageView/MessageView_Communicator.hxx create mode 100644 tools/MessageView/MessageView_VisibilityState.cxx create mode 100644 tools/MessageView/MessageView_VisibilityState.hxx create mode 100644 tools/MessageView/MessageView_Window.cxx create mode 100644 tools/MessageView/MessageView_Window.hxx create mode 100644 tools/TKMessageModel/CMakeLists.txt create mode 100644 tools/TKMessageModel/EXTERNLIB create mode 100644 tools/TKMessageModel/FILES create mode 100644 tools/TKMessageModel/PACKAGES create mode 100644 tools/TKMessageView/CMakeLists.txt create mode 100644 tools/TKMessageView/EXTERNLIB create mode 100644 tools/TKMessageView/FILES create mode 100644 tools/TKMessageView/PACKAGES create mode 100644 tools/ViewControl/ViewControl.hxx create mode 100644 tools/ViewControl/ViewControl_PropertyView.cxx create mode 100644 tools/ViewControl/ViewControl_PropertyView.hxx create mode 100644 tools/ViewControl/ViewControl_Table.cxx create mode 100644 tools/ViewControl/ViewControl_Table.hxx create mode 100644 tools/ViewControl/ViewControl_TableModel.cxx create mode 100644 tools/ViewControl/ViewControl_TableModel.hxx create mode 100644 tools/ViewControl/ViewControl_TableModelFilter.cxx create mode 100644 tools/ViewControl/ViewControl_TableModelFilter.hxx create mode 100644 tools/ViewControl/ViewControl_TableModelValues.cxx create mode 100644 tools/ViewControl/ViewControl_TableModelValues.hxx create mode 100644 tools/ViewControl/ViewControl_TableProperty.cxx create mode 100644 tools/ViewControl/ViewControl_TableProperty.hxx delete mode 100644 upgrade.bat 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/Draw/Draw.cxx b/src/Draw/Draw.cxx index e6292aeb27..98061de276 100644 --- a/src/Draw/Draw.cxx +++ b/src/Draw/Draw.cxx @@ -575,3 +575,27 @@ void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey, (*fp) (theDI); } + +//======================================================================= +//function : ParseOnOff +//purpose : +//======================================================================= +Standard_Boolean Draw::ParseOnOff (Standard_CString theArg, + Standard_Boolean& theIsOn) +{ + TCollection_AsciiString aFlag(theArg); + aFlag.LowerCase(); + if (aFlag == "on" + || aFlag == "1") + { + theIsOn = Standard_True; + return Standard_True; + } + else if (aFlag == "off" + || aFlag == "0") + { + theIsOn = Standard_False; + return Standard_True; + } + return Standard_False; +} diff --git a/src/Draw/Draw.hxx b/src/Draw/Draw.hxx index e546d98902..5e55a12b0d 100644 --- a/src/Draw/Draw.hxx +++ b/src/Draw/Draw.hxx @@ -129,7 +129,13 @@ public: //! Defines Draw unit commands Standard_EXPORT static void UnitCommands (Draw_Interpretor& I); + //! Defines Draw message commands + Standard_EXPORT static void MessageCommands (Draw_Interpretor& I); + //! Parses boolean argument. + //! Handles either flag specified by 0|1 or on|off. + Standard_EXPORT static Standard_Boolean ParseOnOff (Standard_CString theArg, + Standard_Boolean& theIsOn); protected: diff --git a/src/Draw/Draw_Commands.cxx b/src/Draw/Draw_Commands.cxx index 6444f5d722..6e52e1908d 100644 --- a/src/Draw/Draw_Commands.cxx +++ b/src/Draw/Draw_Commands.cxx @@ -45,4 +45,5 @@ void Draw::Commands (Draw_Interpretor& theCommands) Draw::GraphicCommands(theCommands); Draw::PloadCommands(theCommands); Draw::UnitCommands(theCommands); + Draw::MessageCommands(theCommands); } diff --git a/src/Draw/Draw_MessageCommands.cxx b/src/Draw/Draw_MessageCommands.cxx new file mode 100644 index 0000000000..e7e4b23cf7 --- /dev/null +++ b/src/Draw/Draw_MessageCommands.cxx @@ -0,0 +1,104 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include + +//============================================================================== +//function : ActivateReport +//purpose : +//============================================================================== + +static Standard_Integer ActivateReport (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec) +{ + bool isActiveMode = true; + bool isGravityDefined = false; + Standard_Integer aGravity = -1; + for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt) + { + const TCollection_AsciiString anArg = theArgVec[anArgIt]; + TCollection_AsciiString anArgCase = anArg; + anArgCase.LowerCase(); + if (anArgCase == "-mode") + { + if (anArgIt + 1 < theArgsNb + && Draw::ParseOnOff (theArgVec[anArgIt + 1], isActiveMode)) + { + ++anArgIt; + } + } + if (anArgCase == "-gravity") + { + if (anArgIt + 1 < theArgsNb) + { + Message_Gravity aGravityType; + isGravityDefined = Message::GravityFromString (theArgVec[anArgIt + 1], aGravityType); + aGravity = (Standard_Integer)aGravityType; + ++anArgIt; + } + } + else + { + std::cout << "Syntax error: unknown argument " << anArg << ".\n"; + return 1; + } + } + + Handle(Message_Report) aCurrentReport = Message_Report::CurrentReport (isActiveMode); + if (!aCurrentReport.IsNull()) + aCurrentReport->SetActive(isActiveMode, aGravity); + + return 0; +} + +//============================================================================== +//function : ClearReport +//purpose : +//============================================================================== + +static Standard_Integer ClearReport (Draw_Interpretor&, Standard_Integer, const char**) +{ + Handle(Message_Report) aCurrentReport = Message_Report::CurrentReport (Standard_False); + if (!aCurrentReport.IsNull()) + aCurrentReport->Clear(); + + return 0; +} + +//======================================================================= +//function : PloadCommands +//purpose : +//======================================================================= + +void Draw::MessageCommands(Draw_Interpretor& theCommands) +{ + static Standard_Boolean Done = Standard_False; + if (Done) return; + Done = Standard_True; + + const char* g = "DRAW Message Commands"; + + theCommands.Add("activateReport" , + "activateReport [-mode {-on|-off}=-on]" + "[-gravity {trace|info|warning|alarm|fail}]" + "Activates default Message_Report object" , + __FILE__, ActivateReport, g); + + theCommands.Add("clearReport" , "clearReport: Clears content of default Message_Report object" , + __FILE__, ClearReport, g); +} diff --git a/src/Draw/Draw_Report.cxx b/src/Draw/Draw_Report.cxx new file mode 100644 index 0000000000..b3535cc895 --- /dev/null +++ b/src/Draw/Draw_Report.cxx @@ -0,0 +1,50 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Draw_Report,Draw_Drawable3D) + +//======================================================================= +//function : Copy +//purpose : +//======================================================================= +Handle(Draw_Drawable3D) Draw_Report::Copy()const +{ + Handle(Draw_Report) aReport = new Draw_Report (myReport); + return aReport; +} + +//======================================================================= +//function : Dump +//purpose : +//======================================================================= +void Draw_Report::Dump (Standard_OStream& S)const +{ + (void)S; + //S << myReport; +} + + +//======================================================================= +//function : Whatis +//purpose : +//======================================================================= +void Draw_Report::Whatis (Draw_Interpretor& S)const +{ + S << "Draw_Report"; +} diff --git a/src/Draw/Draw_Report.hxx b/src/Draw/Draw_Report.hxx new file mode 100644 index 0000000000..b099c54bc8 --- /dev/null +++ b/src/Draw/Draw_Report.hxx @@ -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. + +#ifndef _Draw_Report_HeaderFile +#define _Draw_Report_HeaderFile + +#include +#include + +#include +#include +#include +#include + +#include + +class Draw_Report; +DEFINE_STANDARD_HANDLE(Draw_Report, Draw_Drawable3D) + +//! To store nummbers in variables. +class Draw_Report : public Draw_Drawable3D +{ + +public: + + Standard_EXPORT Draw_Report (const Handle(Message_Report)& theReport) : myReport (theReport) {} + + Standard_EXPORT const Handle(Message_Report)& GetReport() const { return myReport; } + + Standard_EXPORT void SetReport (const Handle(Message_Report)& theReport) { myReport = theReport; } + + //! Does nothhing. + Standard_EXPORT void DrawOn (Draw_Display& dis) const Standard_OVERRIDE { (void)dis; } + + //! For variable copy. + Standard_EXPORT virtual Handle(Draw_Drawable3D) Copy() const Standard_OVERRIDE; + + //! For variable dump. + Standard_EXPORT virtual void Dump (Standard_OStream& S) const Standard_OVERRIDE; + + //! For variable whatis command. Set as a result the + //! type of the variable. + Standard_EXPORT virtual void Whatis (Draw_Interpretor& I) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTIEXT(Draw_Report,Draw_Drawable3D) + +private: + Handle(Message_Report) myReport; +}; + + + + + + + +#endif // _Draw_Report_HeaderFile diff --git a/src/Draw/FILES b/src/Draw/FILES index b4eb578743..b99db0d08c 100755 --- a/src/Draw/FILES +++ b/src/Draw/FILES @@ -43,6 +43,7 @@ Draw_Marker2D.hxx Draw_Marker3D.cxx Draw_Marker3D.hxx Draw_MarkerShape.hxx +Draw_MessageCommands.cxx Draw_Number.cxx Draw_Number.hxx Draw_PInterp.hxx @@ -53,6 +54,8 @@ Draw_Printer.hxx Draw_ProgressIndicator.cxx Draw_ProgressIndicator.hxx Draw_Replace.tcl +Draw_Report.cxx +Draw_Report.hxx Draw_Segment2D.cxx Draw_Segment2D.hxx Draw_Segment3D.cxx diff --git a/src/GeomAbs/FILES b/src/GeomAbs/FILES index 80df5eea2e..53cf13d3eb 100644 --- a/src/GeomAbs/FILES +++ b/src/GeomAbs/FILES @@ -1,3 +1,5 @@ +GeomAbs.cxx +GeomAbs.hxx GeomAbs_BSplKnotDistribution.hxx GeomAbs_CurveForm.hxx GeomAbs_CurveType.hxx diff --git a/src/GeomAbs/GeomAbs.cxx b/src/GeomAbs/GeomAbs.cxx new file mode 100644 index 0000000000..39d4c4bad4 --- /dev/null +++ b/src/GeomAbs/GeomAbs.cxx @@ -0,0 +1,59 @@ +// 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 + +namespace +{ + static Standard_CString GeomAbs_Table_PrintSurfaceTypeEnum[11] = + { + "Plane", "Cylinder", "Cone", "Sphere", "Torus", "BezierSurface", "BSplineSurface", + "SurfaceOfRevolution", "SurfaceOfExtrusion", "OffsetSurface", "OtherSurface" + }; +} + +//======================================================================= +//function : SurfaceTypeToString +//purpose : +//======================================================================= + +Standard_CString GeomAbs::SurfaceTypeToString (const GeomAbs_SurfaceType theValue) +{ + return GeomAbs_Table_PrintSurfaceTypeEnum[theValue]; +} + +//======================================================================= +//function : SurfaceTypeFromString +//purpose : +//======================================================================= + +Standard_Boolean GeomAbs::SurfaceTypeFromString (const Standard_CString theString, + GeomAbs_SurfaceType& theType) +{ + TCollection_AsciiString aName (theString); + //aName.UpperCase(); + for (Standard_Integer aTypeIter = GeomAbs_Plane; aTypeIter <= GeomAbs_OtherSurface; ++aTypeIter) + { + Standard_CString aTypeName = GeomAbs_Table_PrintSurfaceTypeEnum[aTypeIter]; + if (aName == aTypeName) + { + theType = GeomAbs_SurfaceType (aTypeIter); + return Standard_True; + } + } + return Standard_False; +} diff --git a/src/GeomAbs/GeomAbs.hxx b/src/GeomAbs/GeomAbs.hxx new file mode 100644 index 0000000000..c46edda6e6 --- /dev/null +++ b/src/GeomAbs/GeomAbs.hxx @@ -0,0 +1,54 @@ +// 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 _GeomAbs_HeaderFile +#define _GeomAbs_HeaderFile + +#include +#include +#include + +//! Defines +//! - tools to work with geomAbs +class GeomAbs +{ +public: + + DEFINE_STANDARD_ALLOC + + //! Returns the string name for a type. + //! @param surface type + //! @return string identifier from the enumeration + Standard_EXPORT static Standard_CString SurfaceTypeToString (const GeomAbs_SurfaceType theSurfaceType); + + //! Returns the surface type from the given string identifier (using case-insensitive comparison). + //! @param theString string identifier + //! @return type or GeomAbs_OtherSurface if string identifier is invalid + static GeomAbs_SurfaceType SurfaceTypeFromString (const Standard_CString theString) + { + GeomAbs_SurfaceType aSurfaceType = GeomAbs_OtherSurface; + SurfaceTypeFromString (theString, aSurfaceType); + return aSurfaceType; + } + + //! Determines the surface type from the given string identifier (using case-insensitive comparison). + //! @param theString string identifier + //! @param theSurfaceType detected surface type + //! @return TRUE if string identifier is known + Standard_EXPORT static Standard_Boolean SurfaceTypeFromString (const Standard_CString theString, + GeomAbs_SurfaceType& theType); +}; + +#endif // _GeomAbs_HeaderFile diff --git a/src/IntTools/IntTools_FaceFace.cxx b/src/IntTools/IntTools_FaceFace.cxx index 8726f0ad56..06adf14e11 100644 --- a/src/IntTools/IntTools_FaceFace.cxx +++ b/src/IntTools/IntTools_FaceFace.cxx @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1487,6 +1488,7 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index, mbspc.Knots(), mbspc.Multiplicities(), mbspc.Degree()); + MESSAGE_INFO_OBJECT(BS, "IntTools_FaceFace::MakeCurve", "", 0, NULL); GeomLib_CheckBSplineCurve Check(BS,TOLCHECK,TOLANGCHECK); Check.FixTangent(Standard_True,Standard_True); // diff --git a/src/Message/FILES b/src/Message/FILES index e502c6903c..76cad124c3 100755 --- a/src/Message/FILES +++ b/src/Message/FILES @@ -1,8 +1,21 @@ Message.cxx Message.hxx +Message_Alert.cxx +Message_Alert.hxx +Message_AlertNode.cxx +Message_AlertNode.hxx +Message_Alerts.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_ExecStatus.hxx Message_Gravity.hxx Message_HArrayOfMsg.hxx @@ -15,6 +28,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 +47,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..d1a422d9f2 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 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_Alert.cxx b/src/Message/Message_Alert.cxx index 5901a49a09..9d05d3a2ae 100644 --- a/src/Message/Message_Alert.cxx +++ b/src/Message/Message_Alert.cxx @@ -48,3 +48,13 @@ Standard_Boolean Message_Alert::Merge (const Handle(Message_Alert)& /*theTarget* // by default, merge trivially return Standard_True; } + +//======================================================================= +//function : IsEqual +//purpose : +//======================================================================= + +Standard_Boolean Message_Alert::IsSame(const Handle(Message_Alert)& theAlert) +{ + return IsEqual (GetMessageKey(), theAlert->GetMessageKey()); +} diff --git a/src/Message/Message_Alert.hxx b/src/Message/Message_Alert.hxx index 030efb0f99..041df286dc 100644 --- a/src/Message/Message_Alert.hxx +++ b/src/Message/Message_Alert.hxx @@ -54,6 +54,11 @@ public: //! Base implementation always returns true. virtual Standard_EXPORT Standard_Boolean Merge (const Handle(Message_Alert)& theTarget); + //! Return true if the current and parameter alert have the same content + //! \param theAlert an alert to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Alert)& theAlert); + // OCCT RTTI DEFINE_STANDARD_RTTIEXT(Message_Alert,Standard_Transient) }; diff --git a/src/Message/Message_AlertNode.cxx b/src/Message/Message_AlertNode.cxx new file mode 100644 index 0000000000..7a38fbdf73 --- /dev/null +++ b/src/Message/Message_AlertNode.cxx @@ -0,0 +1,88 @@ +// 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_AlertNode,Message_Alert) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_AlertNode::GetMessageKey () const +{ + if (myAttribute.IsNull()) + return Message_Alert::GetMessageKey(); + + return myAttribute->GetMessageKey(); +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= + +Handle(Message_Alert) Message_AlertNode::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_AlertNode) anAlert = new Message_AlertNode(); + anAlert->SetAttribute (theAttribute); + theReport->AddAlert (Message_Info, anAlert, thePerfMeter, theParentAlert); + + return anAlert; +} + +//======================================================================= +//function : HasAlerts +//purpose : +//======================================================================= + +Standard_Boolean Message_AlertNode::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; +} + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean Message_AlertNode::IsSame (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.IsNull()) + return Standard_False; + + if (Attribute().IsNull() && aNodeAlert->Attribute().IsNull()) + return Standard_True; + + return Attribute()->IsSame (aNodeAlert->Attribute()); +} diff --git a/src/Message/Message_AlertNode.hxx b/src/Message/Message_AlertNode.hxx new file mode 100644 index 0000000000..34ed362d1e --- /dev/null +++ b/src/Message/Message_AlertNode.hxx @@ -0,0 +1,132 @@ +// 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_AlertNode_HeaderFile +#define _Message_AlertNode_HeaderFile + +#include +#include +#include +#include + +class Message_Attribute; +class Message_PerfMeter; +class Message_Report; + +DEFINE_STANDARD_HANDLE(Message_AlertNode, Message_Alert) + +//! 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 +//! + +class Message_AlertNode : public Message_Alert +{ +public: + //! Empty constructor + Standard_EXPORT Message_AlertNode() + : 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 list of collected alerts with specified gravity + Standard_EXPORT Message_ListOfAlert& GetAlerts (const Message_Gravity theGravity) + { return myChildAlerts[theGravity]; } + + //! 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 = 0, + const Handle(Message_Alert)& theParentAlert = Handle(Message_Alert)()); + + //! 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); + + //! Return true if the current and parameter alert have the same content + //! \param theAlert an alert to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Alert)& theAlert); + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AlertNode, Message_Alert) + +protected: + //! Sets performance meter + //! \param theMeter instance pointer or NULL + void SetPerfMeter (Message_PerfMeter* theMeter) { myPerfMeter = theMeter; } + +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]; + + 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_Alerts.hxx b/src/Message/Message_Alerts.hxx new file mode 100644 index 0000000000..c9618b8701 --- /dev/null +++ b/src/Message/Message_Alerts.hxx @@ -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. + +#ifndef _Message_Alerts_HeaderFile +#define _Message_Alerts_HeaderFile + +#include +#include +#include +#include +#include +#include + +static Handle(Message_Alert) OCCT_Message_Alert; + +#define MESSAGE_INFO(Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertNode::AddAlert (Message_Report::CurrentReport(), \ + new Message_Attribute (Name, Description), PerfMeter, ParentAlert); \ + } \ + } + +#define MESSAGE_INFO_OBJECT(Object, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertNode::AddAlert (Message_Report::CurrentReport(), \ + new Message_AttributeObject (Object, Name, Description), PerfMeter, ParentAlert ); \ + } \ + } + +#define MESSAGE_INFO_VECTOR_OF_REAL(Vector, ColumnCount, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertNode::AddAlert (Message_Report::CurrentReport(), \ + new Message_AttributeVectorOfReal (Vector, ColumnCount, Name, Description), PerfMeter, ParentAlert ); \ + } \ + } + +#define MESSAGE_INFO_VECTOR_OF_REAL_VEC3(Vector, ColumnCount, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertNode::AddAlert (Message_Report::CurrentReport(), \ + new Message_AttributeVectorOfRealVec3 (Vector, ColumnCount, Name, Description), PerfMeter, ParentAlert); \ + } \ + } + +#endif // _Message_Alerts_HeaderFile diff --git a/src/Message/Message_Attribute.cxx b/src/Message/Message_Attribute.cxx new file mode 100644 index 0000000000..d0bb64f35e --- /dev/null +++ b/src/Message/Message_Attribute.cxx @@ -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. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_Attribute::GetMessageKey () const +{ + return !myName.IsEmpty() ? myName.ToCString() : ""; +} + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean Message_Attribute::IsSame (const Handle(Message_Attribute)& theAttribute) +{ + if (theAttribute.IsNull()) + return Standard_False; + + return myName.IsEqual(theAttribute->GetName()) && myDescription.IsEqual (theAttribute->GetName()); +} diff --git a/src/Message/Message_Attribute.hxx b/src/Message/Message_Attribute.hxx new file mode 100644 index 0000000000..1c96df509f --- /dev/null +++ b/src/Message/Message_Attribute.hxx @@ -0,0 +1,72 @@ +// 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; } + + //! Return true if the current and parameter alert have the same content + //! \param theAttribute an attribute to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Attribute)& theAttribute); + + // 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..c48e32d8b8 --- /dev/null +++ b/src/Message/Message_AttributeObject.cxx @@ -0,0 +1,51 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#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; +} + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean Message_AttributeObject::IsSame (const Handle(Message_Attribute)& theAttribute) +{ + if (!Message_Attribute::IsSame (theAttribute)) + return Standard_False; + + Handle(Message_AttributeObject) anAttribute = Handle(Message_AttributeObject)::DownCast (theAttribute); + if (anAttribute.IsNull()) + return Standard_False; + + if (myObject.IsNull() != anAttribute->GetObject().IsNull()) + return Standard_False; + + return Standard_True; +} diff --git a/src/Message/Message_AttributeObject.hxx b/src/Message/Message_AttributeObject.hxx new file mode 100644 index 0000000000..ecaa065f8b --- /dev/null +++ b/src/Message/Message_AttributeObject.hxx @@ -0,0 +1,52 @@ +// 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 +#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; } + + //! Return true if the current and parameter alert have the same content + //! \param theAttribute an attribute to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Attribute)& theAttribute) Standard_OVERRIDE; + + // 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..64ba6f8edd --- /dev/null +++ b/src/Message/Message_AttributeVectorOfReal.cxx @@ -0,0 +1,103 @@ +// 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_AttributeVectorOfReal, Message_Attribute) + +//======================================================================= +//function : Message_AttributeVectorOfReal +//purpose : +//======================================================================= + +Message_AttributeVectorOfReal::Message_AttributeVectorOfReal (const NCollection_Vector& theValues, + const Standard_Integer& theColumnCount, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute(theName, theDescription), myColumnCount (theColumnCount) +{ + SetValues (theValues); +} + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= + +void Message_AttributeVectorOfReal::SetValues (const NCollection_Vector& theValues) +{ + myValues = theValues; + + int aLength = (Standard_Integer)myValues.Length(); + if (aLength < 2) + return; + + if (myColumnCount <= 0) + myCachedValue = TCollection_AsciiString ("[") + aLength + "] : "; + else + myCachedValue = TCollection_AsciiString ("[") + (aLength / myColumnCount) + ", " + myColumnCount + "] : "; + + 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; +} + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean Message_AttributeVectorOfReal::IsSame (const Handle(Message_Attribute)& theAttribute) +{ + if (!Message_Attribute::IsSame (theAttribute)) + return Standard_False; + + Handle(Message_AttributeVectorOfReal) anAttribute = Handle(Message_AttributeVectorOfReal)::DownCast (theAttribute); + if (anAttribute.IsNull()) + return Standard_False; + + if (GetColumnCount() != anAttribute->GetColumnCount() || + GetValues().Length() != anAttribute->GetValues().Length()) + return Standard_False; + + NCollection_Vector::Iterator anIterator (GetValues()); + NCollection_Vector::Iterator anOtherIterator (anAttribute->GetValues()); + for (; anIterator.More() && anOtherIterator.More(); anIterator.Next(), anOtherIterator.Next()) + { + if (fabs (anIterator.Value() - anOtherIterator.Value()) > Precision::Confusion()) + return Standard_False; + } + return Standard_True; +} diff --git a/src/Message/Message_AttributeVectorOfReal.hxx b/src/Message/Message_AttributeVectorOfReal.hxx new file mode 100644 index 0000000000..68e337a6b2 --- /dev/null +++ b/src/Message/Message_AttributeVectorOfReal.hxx @@ -0,0 +1,74 @@ +// 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 +//! Values might be presented as table if column size is defined +class Message_AttributeVectorOfReal : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeVectorOfReal (const NCollection_Vector& theValues, + const Standard_Integer& theColumnCount, + 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; } + + //! Sets value to present values in a table view + //! \param theValue value of division the values on sub-containers + void SetColumnCount (const Standard_Integer& theValue) { myColumnCount = theValue; } + + //! Gets value to present values in a table view + //! \param theSubSize value of division the values on sub-containers + Standard_Integer GetColumnCount() const { return myColumnCount; } + + //! Returns description of alert if it is set + //! @return alert description + virtual const TCollection_AsciiString& GetDescription() const; + + //! Return true if the current and parameter alert have the same content + //! \param theAttribute an attribute to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Attribute)& theAttribute) Standard_OVERRIDE; + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeVectorOfReal, Message_Attribute) + +private: + NCollection_Vector myValues; //!< container of values + Standard_Integer myColumnCount; //!< value to present container of values into table + + 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..385978530c --- /dev/null +++ b/src/Message/Message_AttributeVectorOfRealVec3.cxx @@ -0,0 +1,102 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeVectorOfRealVec3, Message_Attribute) + +//======================================================================= +//function : Message_AttributeVectorOfRealVec3 +//purpose : +//======================================================================= + +Message_AttributeVectorOfRealVec3::Message_AttributeVectorOfRealVec3 (const NCollection_Vector>& theValues, + const Standard_Integer& theColumnCount, + const TCollection_AsciiString& theName, + const TCollection_AsciiString& theDescription) +: Message_Attribute (theName, theDescription), myColumnCount (theColumnCount) +{ + SetValues (theValues); +} + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= + +void Message_AttributeVectorOfRealVec3::SetValues (const NCollection_Vector>& theValues) +{ + myValues = theValues; + + int aLength = (Standard_Integer)myValues.Length(); + if (aLength < 2) + return; + + if (myColumnCount <= 0) + myCachedValue = TCollection_AsciiString ("[") + aLength + "] : "; + else + myCachedValue = TCollection_AsciiString ("[") + (aLength / myColumnCount) + ", " + myColumnCount + "] : "; + + 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; +} + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean Message_AttributeVectorOfRealVec3::IsSame (const Handle(Message_Attribute)& theAttribute) +{ + if (!Message_Attribute::IsSame (theAttribute)) + return Standard_False; + + Handle(Message_AttributeVectorOfRealVec3) anAttribute = Handle(Message_AttributeVectorOfRealVec3)::DownCast (theAttribute); + if (anAttribute.IsNull()) + return Standard_False; + + NCollection_Vector >::Iterator anIterator (GetValues()); + NCollection_Vector >::Iterator anOtherIterator (anAttribute->GetValues()); + for (; anIterator.More() && anOtherIterator.More(); anIterator.Next(), anOtherIterator.Next()) + { + if (fabs (anIterator.Value().x() - anOtherIterator.Value().x()) > Precision::Confusion() || + fabs (anIterator.Value().y() - anOtherIterator.Value().y()) > Precision::Confusion() || + fabs (anIterator.Value().z() - anOtherIterator.Value().z()) > Precision::Confusion()) + return Standard_False; + } + return Standard_True; +} diff --git a/src/Message/Message_AttributeVectorOfRealVec3.hxx b/src/Message/Message_AttributeVectorOfRealVec3.hxx new file mode 100644 index 0000000000..fe425eedea --- /dev/null +++ b/src/Message/Message_AttributeVectorOfRealVec3.hxx @@ -0,0 +1,72 @@ +// 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 three Standard_Real values in its field +//! Values might be presented as table if column size is defined +class Message_AttributeVectorOfRealVec3 : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeVectorOfRealVec3 (const NCollection_Vector>& theValues, + const Standard_Integer& theColumnCount, + 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; } + + //! Sets value to present values in a table view + //! \param theValue value of division the values on sub-containers + void SetColumnCount (const Standard_Integer& theValue) { myColumnCount = theValue; } + + //! Gets value to present values in a table view + //! \param theSubSize value of division the values on sub-containers + Standard_Integer GetColumnCount() const { return myColumnCount; } + + //! Returns description of alert if it is set + //! @return alert description + virtual const TCollection_AsciiString& GetDescription() const; + + //! Return true if the current and parameter alert have the same content + //! \param theAttribute an attribute to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Attribute)& theAttribute) Standard_OVERRIDE; + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(Message_AttributeVectorOfRealVec3, Message_Attribute) + +private: + NCollection_Vector > myValues; //!< container of values + Standard_Integer myColumnCount; //!< value to present container of values into table + 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_PerfMeter.cxx b/src/Message/Message_PerfMeter.cxx new file mode 100644 index 0000000000..93e1f59ccf --- /dev/null +++ b/src/Message/Message_PerfMeter.cxx @@ -0,0 +1,165 @@ +// 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 + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= + +Message_PerfMeter::~Message_PerfMeter() +{ + releaseAlert (0); +} + +//======================================================================= +//function : GetAlert +//purpose : +//======================================================================= + +Handle(Message_AlertNode) Message_PerfMeter::GetAlert (const Standard_Integer theLevelId) const +{ + if (!myActiveAlerts.IsBound (theLevelId)) + return Handle(Message_AlertNode)(); + + return myActiveAlerts.Find (theLevelId).myAlert; +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= + +void Message_PerfMeter::AddAlert (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.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_AlertNode) anAlert = GetAlert (aLevelId); + if (!anAlert->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_AlertNode) anAlertExtended = Handle(Message_AlertNode)::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_AlertNode) aNodeAlert = anAlertInfo.myAlert; + + aNodeAlert->SetCumulativeTime (getCurrentTime() - anAlertInfo.myStartTime); + aNodeAlert->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..aa07bbe440 --- /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_AlertNode) 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_AlertNode)& theAlert, Standard_Real theStartTime) + : myAlert (theAlert), myStartTime (theStartTime) {} + + Handle(Message_AlertNode) 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..c34352f1d5 100644 --- a/src/Message/Message_Report.cxx +++ b/src/Message/Message_Report.cxx @@ -14,19 +14,41 @@ // commercial license or contractual agreement. #include + +#include #include #include +#include +#include + #include IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) +static Handle(Message_Report) MyReport; + //======================================================================= //function : Message_Report //purpose : //======================================================================= Message_Report::Message_Report () +: myIsUsePerfMeter (Standard_False), myLimit (-1) { + SetActive (Standard_True); +} + +//======================================================================= +//function : CurrentReport +//purpose : +//======================================================================= + +Handle(Message_Report) Message_Report::CurrentReport(const Standard_Boolean theToCreate) +{ + if (MyReport.IsNull() && theToCreate) + MyReport = new Message_Report(); + + return MyReport; } //======================================================================= @@ -36,6 +58,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 +83,61 @@ 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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(aParentAlert); + Message_ListOfAlert& aList = !aNodeAlert.IsNull() ? aNodeAlert->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 +153,62 @@ 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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (aLastAlert); + if (aNodeAlert.IsNull()) + return aLastAlert; + Handle(Message_AlertNode) aParentExtendedAlert = aNodeAlert; + + Standard_Boolean aHasPerfMeter = aNodeAlert->GetPerfMeter() != NULL; + if (!aHasPerfMeter) // the alert has finished and is not the last alert anymore + return Handle(Message_Alert)(); + + while (!aParentExtendedAlert.IsNull() && !aParentExtendedAlert->GetAlerts (theGravity).IsEmpty()) + { + Handle(Message_Alert) anAlert = aParentExtendedAlert->GetAlerts (theGravity).Last(); + + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (anAlert); + if (aNodeAlert.IsNull()) + { + if (!aHasPerfMeter) // if there is a perf meter, use alert of it + aLastAlert = anAlert; + break; + } + + if (!aHasPerfMeter) + aHasPerfMeter = aNodeAlert->GetPerfMeter() != NULL; + else if (!aNodeAlert->GetPerfMeter()) + break; // last alert is the previous alert where perf meter is not NULL + + aLastAlert = aNodeAlert; + aParentExtendedAlert = aNodeAlert; + } + + // if alert has perf meter, use as the last alert, an alert of the perf meter + aNodeAlert = Handle(Message_AlertNode)::DownCast (aLastAlert); + if (aNodeAlert.IsNull()) + return aLastAlert; + if (aNodeAlert->GetPerfMeter()) + aLastAlert = aNodeAlert->GetPerfMeter()->GetAlert(); + + return aLastAlert; +} + //======================================================================= //function : HasAlert //purpose : @@ -248,3 +384,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..0d7cb90419 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. //! @@ -54,10 +56,25 @@ public: //! Empty constructor Standard_EXPORT Message_Report (); + + //! returns the only one instance of Report + //! When theToCreate is true - automatically creates message report when not exist. + //! that has been created. + Standard_EXPORT static Handle(Message_Report) CurrentReport (const Standard_Boolean theToCreate = Standard_False); + //! Add alert with specified gravity. //! This method is thread-safe, i.e. alerts can be added from parallel threads safely. Standard_EXPORT void AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert); + //! Add alert with specified gravity. The alert is a sub-alert of report or another alert + //! The parent alert is the parameter alert or the last alert if found else report. + //! \param theGravity a message gravity + //! \param theAlert a new alert to be added + //! \param thePerfMeter performance meter calculates the alert spent time and participate in searching the last alert if needed + //! \param theParentAlert if not NULL specifies parent alert where the alert should be placed, if the parent is an extednded alert + Standard_EXPORT void AddAlert (const Message_Gravity theGravity, const Handle(Message_Alert)& theAlert, + Message_PerfMeter* thePerfMeter, const Handle(Message_Alert)& theParentAlert = Handle(Message_Alert)()); + //! Returns list of collected alerts with specified gravity Standard_EXPORT const Message_ListOfAlert& GetAlerts (Message_Gravity theGravity) const; @@ -94,15 +111,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 13892f659b..4602bf04ac 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..5c23ad25a0 --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.cxx @@ -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. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute) + +//======================================================================= +//function : IsSame +//purpose : +//======================================================================= + +Standard_Boolean TopoDS_AlertAttribute::IsSame (const Handle(Message_Attribute)& theAttribute) +{ + if (!Message_Attribute::IsSame (theAttribute)) + return Standard_False; + + Handle(TopoDS_AlertAttribute) anAttribute = Handle(TopoDS_AlertAttribute)::DownCast (theAttribute); + if (anAttribute.IsNull()) + return Standard_False; + + if (GetShape().IsNull() != anAttribute->GetShape().IsNull()) + return Standard_False; + + if (GetShape().IsNull()) + return Standard_True; + + return GetShape().IsSame (anAttribute->GetShape()); +} diff --git a/src/TopoDS/TopoDS_AlertAttribute.hxx b/src/TopoDS/TopoDS_AlertAttribute.hxx new file mode 100644 index 0000000000..f587fcca5d --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.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 _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; } + + //! Return true if the current and parameter alert have the same content + //! \param theAttribute an attribute to compare + //! @return True if equal. + virtual Standard_EXPORT Standard_Boolean IsSame (const Handle(Message_Attribute)& theAttribute) Standard_OVERRIDE; + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute) + +private: + TopoDS_Shape myShape; +}; + +#define MESSAGE_INFO_SHAPE(Shape, Name, Description, PerfMeter, ParentAlert) \ + { \ + if (!Message_Report::CurrentReport().IsNull() && \ + Message_Report::CurrentReport()->IsActive (Message_Info)) \ + { \ + OCCT_Message_Alert = Message_AlertNode::AddAlert (Message_Report::CurrentReport(), \ + new TopoDS_AlertAttribute (Shape, Name, Description), PerfMeter, ParentAlert ); \ + } \ + } + + +#endif // _TopoDS_AlertAttribute_HeaderFile diff --git a/src/XmlDrivers/FILES b/src/XmlDrivers/FILES index 058b8acc20..d4a93d94ff 100644 --- a/src/XmlDrivers/FILES +++ b/src/XmlDrivers/FILES @@ -4,3 +4,5 @@ XmlDrivers_DocumentRetrievalDriver.cxx XmlDrivers_DocumentRetrievalDriver.hxx XmlDrivers_DocumentStorageDriver.cxx XmlDrivers_DocumentStorageDriver.hxx +XmlDrivers_MessageReportStorage.cxx +XmlDrivers_MessageReportStorage.hxx diff --git a/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx new file mode 100644 index 0000000000..e8cf7866c7 --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx @@ -0,0 +1,401 @@ +// 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 +#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_AlertNode) anAlertExtended = Handle(Message_AlertNode)::DownCast (theAlert); + if (anAlertExtended.IsNull()) + continue; + const Message_ListOfAlert& anAlerts = anAlertExtended->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_AlertNode) anAlertExtended = Handle(Message_AlertNode)::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)); + TDataStd_Integer::Set (theAlertLabel, aRealArrayAlert->GetColumnCount()); + } + 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()); + } + TDataStd_Integer::Set (theAlertLabel, aRealArrayAlert->GetColumnCount()); + } + else if (aDynamicTypeName == STANDARD_TYPE (TopoDS_AlertAttribute)->Name()) + { + //Handle(TopoDS_AlertAttribute) aShapeAlert = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute); + //TNaming_Builder aNBuilder(theAlertLabel); + //aNBuilder.Generated(aShapeAlert->GetShape()); + } +} + +// ======================================================================= +// 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_AlertNode) anAlert = new Message_AlertNode(); + 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)); + + Standard_Integer aColumnCount = 0; + Handle(TDataStd_Integer) aColumnCountAttribute; + if (aParametersLabel.FindAttribute (TDataStd_Integer::GetID(), aColumnCountAttribute)) + aColumnCount = aColumnCountAttribute->Get(); + + aMessageAttribute = new Message_AttributeVectorOfReal (anArrayValues, aColumnCount); + } + 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); + } + + Standard_Integer aColumnCount = 0; + Handle(TDataStd_Integer) aColumnCountAttribute; + if (aParametersLabel.FindAttribute (TDataStd_Integer::GetID(), aColumnCountAttribute)) + aColumnCount = aColumnCountAttribute->Get(); + aMessageAttribute = new Message_AttributeVectorOfRealVec3 (anArrayValues, aColumnCount); + } + else if (aDynamicTypeName == STANDARD_TYPE (TopoDS_AlertAttribute)->Name()) + { + //Handle(TNaming_NamedShape) aNamedShape= new TNaming_NamedShape(); + //if (!aParametersLabel.FindAttribute(TNaming_NamedShape::GetID(), anAttribute)) + // return Handle(Message_Alert)(); + //aMessageAttribute = new TopoDS_AlertAttribute (aNamedShape->Get()); + } + + 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/CMakeLists.txt b/tools/CMakeLists.txt index e22c877da1..8cbf3cdf93 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -26,6 +26,23 @@ set (CMAKE_SUPPRESS_REGENERATION TRUE) set (CMAKE_CONFIGURATION_TYPES Release Debug RelWithDebInfo CACHE INTERNAL "" FORCE) +# build variables +macro (BUILD_TOOL_MESSAGE BUILD_TOOL_TARGET_VARIABLE BUILD_TOOL_TARGET_STRING) +set (${BUILD_TOOL_TARGET_VARIABLE}_DESCR +"Indicates whether ${BUILD_TOOL_TARGET_STRING} tool should be built or not. +It should be noted that some toolkits of the module can be built even if this module +is not checked (this happens if some other modules depend on these toolkits)") +set (${BUILD_TOOL_TARGET_VARIABLE} ON CACHE BOOL "${${BUILD_TOOL_TARGET_VARIABLE}_DESCR}") +endmacro() + +BUILD_TOOL_MESSAGE (BUILD_PLUGIN_TKTreeModel "TKTreeModel") +BUILD_TOOL_MESSAGE (BUILD_PLUGIN_TKDFBrowser "TKDFBrowser") +BUILD_TOOL_MESSAGE (BUILD_PLUGIN_TKVInspector "TKVInspector") +BUILD_TOOL_MESSAGE (BUILD_PLUGIN_TKShapeView "TKShapeView") +if (NOT BUILD_PLUGIN_TKDFBrowser AND NOT BUILD_PLUGIN_TKVInspector AND NOT BUILD_PLUGIN_TKShapeView) + set (BUILD_TREE_MODEL_ONLY ON) +endif() + # macro: include patched file if it exists macro (OCCT_INCLUDE_CMAKE_FILE BEING_INCLUDED_FILE) if (BUILD_PATCH AND EXISTS "${BUILD_PATCH}/${BEING_INCLUDED_FILE}.cmake") @@ -333,9 +350,16 @@ endif() # list will contain all tools #if (BUILD_Inspector) OCCT_MODULES_AND_TOOLKITS (TOOLS "TOOL_TOOLKITS" OCCT_TOOLS) - foreach (OCCT_TOOL ${OCCT_TOOLS}) - list (APPEND BUILD_TOOL_TOOLKITS ${${OCCT_TOOL}_TOOL_TOOLKITS}) - endforeach() + + if (DEFINED BUILD_TREE_MODEL_ONLY AND BUILD_TREE_MODEL_ONLY) + list (APPEND BUILD_TOOL_TOOLKITS "TKTreeModel") + else() + foreach (OCCT_TOOL ${OCCT_TOOLS}) + list (APPEND BUILD_TOOL_TOOLKITS ${${OCCT_TOOL}_TOOL_TOOLKITS}) + endforeach() + endif() + + message("Build: ${BUILD_TOOL_TOOLKITS}") # collect all the headers to /inc/inspector folder string(TIMESTAMP CURRENT_TIME "%H:%M:%S") @@ -363,9 +387,15 @@ if (3RDPARTY_LIBRARY_DIRS) endif() # include patched toolkit projects or original ones -if (BUILD_TOOL_TOOLKITS) +if (BUILD_TREE_MODEL_ONLY) + OCCT_ADD_SUBDIRECTORY ("tools/TKTreeModel") + message (STATUS "Info: TKTreeModel OCCT toolkits processed") +else() foreach (BUILD_TOOL_TOOLKIT ${BUILD_TOOL_TOOLKITS}) - OCCT_ADD_SUBDIRECTORY ("tools/${BUILD_TOOL_TOOLKIT}") + if (NOT DEFINED BUILD_PLUGIN_${BUILD_TOOL_TOOLKIT} OR BUILD_PLUGIN_${BUILD_TOOL_TOOLKIT}) + OCCT_ADD_SUBDIRECTORY ("tools/${BUILD_TOOL_TOOLKIT}") + message (STATUS "Info: ${BUILD_TOOL_TOOLKIT} toolkits processed") + endif() endforeach() endif() diff --git a/tools/DFBrowser/DFBrowser_TreeModel.cxx b/tools/DFBrowser/DFBrowser_TreeModel.cxx index 16fe10485e..c5d25f1e5d 100644 --- a/tools/DFBrowser/DFBrowser_TreeModel.cxx +++ b/tools/DFBrowser/DFBrowser_TreeModel.cxx @@ -98,12 +98,12 @@ QModelIndex DFBrowser_TreeModel::FindIndex (const TDF_Label& theLabel) const } } bool aDocumentItemFound = false; - QModelIndex aParentIndex = index (0, 0); - TreeModel_ItemBasePtr aParentItem = TreeModel_ModelBase::GetItemByIndex (aParentIndex); // application item + QModelIndex aParentIndex; + TreeModel_ItemBasePtr aParentItem; // find document, where label of document item is equal to Root label - for (int aChildId = 0, aCount = aParentItem->rowCount(); aChildId < aCount; aChildId++) + for (int aChildId = 0, aCount = rowCount(); aChildId < aCount; aChildId++) { - QModelIndex anIndex = index (aChildId, 0, aParentIndex); + QModelIndex anIndex = index (aChildId, 0); TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); DFBrowser_ItemDocumentPtr anItem = itemDynamicCast (anItemBase); if (anItem->GetLabel() == aRoot) diff --git a/tools/DFBrowserPane/DFBrowserPane_AttributePaneSelector.cxx b/tools/DFBrowserPane/DFBrowserPane_AttributePaneSelector.cxx index 870a2f68d4..cbe46e10e3 100644 --- a/tools/DFBrowserPane/DFBrowserPane_AttributePaneSelector.cxx +++ b/tools/DFBrowserPane/DFBrowserPane_AttributePaneSelector.cxx @@ -15,7 +15,9 @@ #include +#include #include +#include // ======================================================================= // function : Constructor diff --git a/tools/MessageModel/FILES b/tools/MessageModel/FILES new file mode 100644 index 0000000000..682edec67e --- /dev/null +++ b/tools/MessageModel/FILES @@ -0,0 +1,24 @@ +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_TableModelCompareValues.cxx +MessageModel_TableModelCompareValues.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..b8d45ec57f --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.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 +#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(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (anAlert); + if (aNodeAlert.IsNull()) + continue; + + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + continue; + + if (!anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + continue; + + //return GetPointerInfo (Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape().TShape()); + + const TopoDS_Shape aShape = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape(); +//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..2de60eca78 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.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_Actions_H +#define MessageModel_Actions_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Message_Report; +class MessageModel_TreeModel; + +class QAction; +class QItemSelectionModel; +class QMenu; +class QWidget; + +//! \class MessageModel_Actions +//! \brief This is a listener of popup context menu items and selection change in message model +class MessageModel_Actions : public QObject +{ + Q_OBJECT + +public: + + //! Constructor + Standard_EXPORT MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, + QItemSelectionModel* theModel); + + //! Destructor + virtual ~MessageModel_Actions() Standard_OVERRIDE {} + + //! Returns action by the type + //! \param theType an action type + //! \return an action instance if it exists + Standard_EXPORT QAction* GetAction (const MessageModel_ActionType& theType); + + //! Fills popup menu with actions depending on the current selection + //! \param theSelectedIndices tree model selected indices + //! \param theMenu menu to be filled + Standard_EXPORT void AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu); + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) + { myParameters = theParameters; } + +public slots: + //! Set selected report not active + void OnDeactivateReport(); + + //! Set selected report active + void OnActivateReport(); + + //! 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..d5bab0ea00 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.cxx @@ -0,0 +1,341 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_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) + { + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(anAlert); + if (aNodeAlert.IsNull() || aNodeAlert->Attribute().IsNull()) + return QVariant(); + + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertWithShape))) + return QIcon (":/icons/item_shape.png"); + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + return QIcon (":/icons/item_vectorOfReal.png"); + else if (anAttribute->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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(anAlert); + if (!aNodeAlert.IsNull() && !aNodeAlert->Attribute().IsNull()) + { + TCollection_AsciiString aDescription = aNodeAlert->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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(anAlert); + if (aNodeAlert.IsNull()) + return GetUnitedAlerts().Size(); + + int aRowCount = 0; + NCollection_Vector aUnitedAlerts; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aNodeAlert->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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(anAlert); + anAlerts = aNodeAlert->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_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(theAlert); + if (aNodeAlert->GetCumulativeTime() > 0) + anAmountTime = aNodeAlert->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..3f338c1d0c --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.hxx @@ -0,0 +1,130 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemAlert_H +#define MessageModel_ItemAlert_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +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..2ba14ae1c7 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.cxx @@ -0,0 +1,193 @@ +// 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 + +// ======================================================================= +// 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..1c7c081fa7 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.hxx @@ -0,0 +1,108 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemReport_H +#define MessageModel_ItemReport_H + +#include +#include +#include +#include + +#include +#include +#include +#include + +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..15c40e4a31 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.cxx @@ -0,0 +1,92 @@ +// 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 : HasReport +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemRoot::HasReport (const Handle(Message_Report)& theReport) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aReportsIt.Value().myReport == theReport) + return Standard_True; + } + return Standard_False; +} + +// ======================================================================= +// function : 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..f98e31b3d4 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.hxx @@ -0,0 +1,132 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemRoot_H +#define MessageModel_ItemRoot_H + +#include +#include +#include +#include +#include + +#include + +class MessageModel_ItemRoot; +typedef QExplicitlySharedDataPointer MessageModel_ItemRootPtr; + +//! \class MessageModel_ItemRoot +//! Collects message reports that should be visualized in tree view. Reports are cached and if reports are not needed, +//! cache should be cleared using RemoveAllReports +//! Parent is NULL, children are MessageModel_ItemReport items. +class MessageModel_ItemRoot : public MessageModel_ItemBase +{ +private: + //! \struct to extend report by description + struct MessageModel_ReportInformation + { + //! Constructor + MessageModel_ReportInformation (Handle(Message_Report) theReport, const TCollection_AsciiString& theDescription) + : myReport (theReport), myDescription (theDescription) {} + + Handle(Message_Report) myReport; //! report + TCollection_AsciiString myDescription; //! report description + }; +public: + + //! Creates an item wrapped by a shared pointer + static MessageModel_ItemRootPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemRootPtr (new MessageModel_ItemRoot (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemRoot() Standard_OVERRIDE {}; + + //! Appends new report + //! \param theReport a report instance + //! \param theReportDescription an additional report information + void AddReport (const Handle(Message_Report)& theReport, const TCollection_AsciiString& theReportDescription) + { myReports.Append (MessageModel_ReportInformation (theReport, theReportDescription)); } + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Returns true if report exists is in the list of the current reports + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //! Clears internal container of added reports + void RemoveAllReports() { myReports.Clear(); } + + //! Returns report by the number + //! \param theRowId an index of the report in the internal container. + Standard_EXPORT const Handle(Message_Report)& GetReport (const int theRowId, TCollection_AsciiString& theReportDescription); + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void SetReversed (const Standard_Boolean& theReversed) { myIsReversed = theReversed; } + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void 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_TableModelCompareValues.cxx b/tools/MessageModel/MessageModel_TableModelCompareValues.cxx new file mode 100644 index 0000000000..40ebad7c43 --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelCompareValues.cxx @@ -0,0 +1,120 @@ +// 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 + +const int REAL_SIGNS = 16; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= + +MessageModel_TableModelCompareValues::MessageModel_TableModelCompareValues (ViewControl_TableModelValues* theValues1, + ViewControl_TableModelValues* theValues2) + : myValues1 (theValues1), myValues2 (theValues2) +{ + SetUseTableSeparateSize (theValues1->UseTableSeparateSize()); + SetUseTableProperties (false); + + Standard_Integer aSectionSize; + theValues1->GetDefaultSectionSize(Qt::Horizontal, aSectionSize); + SetDefaultSectionSize (Qt::Horizontal, aSectionSize); +} + +// ======================================================================= +// function : Destructor +// purpose : +// ======================================================================= + +MessageModel_TableModelCompareValues::~MessageModel_TableModelCompareValues() +{ + if (myValues1) + delete myValues1; + + if (myValues2) + delete myValues2; +} + +// ======================================================================= +// function : ColumnCount +// purpose : +// ======================================================================= + +int MessageModel_TableModelCompareValues::ColumnCount (const QModelIndex& theIndex) const +{ + int aColumnCount1 = myValues1->ColumnCount (theIndex); + return aColumnCount1 == myValues2->ColumnCount (theIndex) ? aColumnCount1 : 0; +} + +// ======================================================================= +// function : Data +// purpose : +// ======================================================================= + +QVariant MessageModel_TableModelCompareValues::Data (const int theRow, const int theColumn, int theRole) const +{ + QVariant aValue1 = myValues1->Data (theRow, theColumn, Qt::DisplayRole); + QVariant aValue2 = myValues2->Data (theRow, theColumn, Qt::DisplayRole); + + QVariant aToolTipValue; + QVariant aDifference; + if (aValue1 != aValue2) { + bool isOk1, isOk2; + double aDoubleValue_1 = aValue1.toDouble(&isOk1); + double aDoubleValue_2 = aValue2.toDouble(&isOk2); + + if (isOk1 && isOk2) + { + double aDoubleDifference = fabs (aDoubleValue_1 - aDoubleValue_2); + if (aDoubleDifference > Precision::Confusion()) + { + aDifference = aDoubleDifference; + aToolTipValue = QString ("%1 (first value)\n%2 (second value)\n%3 (difference: first-second)") + .arg (QString::number (aDoubleValue_1, 'g', REAL_SIGNS)) + .arg (QString::number (aDoubleValue_2, 'g', REAL_SIGNS)) + .arg (aDifference.toString()); + } + } + else { + aDifference = QString ("%1 / %2").arg (aValue1.toString()).arg (aValue2.toString()); + aToolTipValue = QString ("(first value) / (second value)"); + } + } + + switch (theRole) + { + case Qt::DisplayRole: return aDifference; + case Qt::ToolTipRole: return aToolTipValue; + case Qt::BackgroundRole: return !aDifference.isNull() ? QVariant (QColor (200, 191, 231)) : QVariant(); + default: break; + } + return QVariant(); +} + +// ======================================================================= +// function : GetRangeValues +// purpose : +// ======================================================================= + +void MessageModel_TableModelCompareValues::GetRangeValues (QString& theMinValue, QString& theMaxValue, + const QModelIndexList& theSelected) const +{ + (void)theMinValue; (void)theMaxValue; (void)theSelected; +} diff --git a/tools/MessageModel/MessageModel_TableModelCompareValues.hxx b/tools/MessageModel/MessageModel_TableModelCompareValues.hxx new file mode 100644 index 0000000000..039b9e8cf6 --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelCompareValues.hxx @@ -0,0 +1,64 @@ +// 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_TableModelCompareValues_H +#define MessageModel_TableModelCompareValues_H + +#include + +#include + +//! \class MessageModel_TableModelCompareValues +//! \brief This is an implementation for ViewControl_TableModel to present Message_AttributeVectorOfReal object +class MessageModel_TableModelCompareValues : public ViewControl_TableModelValues +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TableModelCompareValues (ViewControl_TableModelValues* theValues1, + ViewControl_TableModelValues* theValues2); + + //! Destructor + virtual ~MessageModel_TableModelCompareValues() 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 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; + + //! 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 GetValuesCount () const { return myValues1->GetValuesCount(); } + +private: + ViewControl_TableModelValues* myValues1; // first table values + ViewControl_TableModelValues* myValues2; // second table values +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TableModelRealValues.cxx b/tools/MessageModel/MessageModel_TableModelRealValues.cxx new file mode 100644 index 0000000000..d3a77309a3 --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealValues.cxx @@ -0,0 +1,121 @@ +// 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 + +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)), myFilter(0) +{ + if (myAttribute->GetColumnCount() > 0) + myFilter = new ViewControl_TableModelFilter (myAttribute->GetColumnCount()); + + SetUseTableSeparateSize (!myFilter); + + SetUseTableProperties (true); + SetUseTablePropertiesXStep (true, -1); + + SetDefaultSectionSize (Qt::Horizontal, theSectionWidth); +} + +// ======================================================================= +// function : ColumnCount +// purpose : +// ======================================================================= + +int MessageModel_TableModelRealValues::ColumnCount (const QModelIndex&) const +{ + int aColumnCount = myAttribute->GetValues().Length(); + if (myFilter) + aColumnCount = myFilter->ColumnCount (aColumnCount); + + return aColumnCount; +} + +// ======================================================================= +// function : Data +// purpose : +// ======================================================================= + +QVariant MessageModel_TableModelRealValues::Data (const int theRow, const int theColumn, int theRole) const +{ + if (theRole != Qt::DisplayRole || theColumn > myAttribute->GetValues().Length()) + return QVariant(); + + int aRow = theRow, aColumn = theColumn; + if (myFilter) + myFilter->GetSourcePosition (theRow, theColumn, aRow, aColumn); + + return myAttribute->GetValues().Value(aColumn); +} + +// ======================================================================= +// 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++) + { + if (myFilter) + myFilter->GetSourcePosition (*aSelIt, aRow, aColumn); + else + 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..f44279a80a --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealValues.hxx @@ -0,0 +1,72 @@ +// 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 + +#include +#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 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; + + //! 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 GetValuesCount () const Standard_OVERRIDE { return myAttribute->GetValues().Length(); } + + //! Returns source row/column indices for the filtered model index for the given role + //! \param theSourceRow model row index + //! \param theSourceColumn model column index + //! \param theRow [out] row number value + //! \param theColumn [out] column value + Standard_EXPORT virtual void GetSourcePosition (const int theSourceRow, const int theSourceColumn, int& theRow, int& theColumn) const + { myFilter->GetSourcePosition (theSourceRow, theSourceColumn, theRow, theColumn); } + +private: + Handle(Message_AttributeVectorOfReal) myAttribute; //!< alert attribute, container of table values + ViewControl_TableModelFilter* myFilter; //!< rearrange vector of values into a table view +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx b/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx new file mode 100644 index 0000000000..685ad9194c --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealVec3Values.cxx @@ -0,0 +1,129 @@ +// 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)), myFilter (0) +{ + if (myAttribute->GetColumnCount() > 0) + myFilter = new ViewControl_TableModelFilter (myAttribute->GetColumnCount()); + + SetUseTableSeparateSize (!myFilter); + SetUseTableProperties (true); + SetDefaultSectionSize (Qt::Horizontal, theSectionWidth); +} + +// ======================================================================= +// function : ColumnCount +// purpose : +// ======================================================================= + +int MessageModel_TableModelRealVec3Values::ColumnCount (const QModelIndex&) const +{ + int aColumnCount = myAttribute->GetValues().Length(); + if (myFilter) + aColumnCount = myFilter->ColumnCount (aColumnCount); + + return aColumnCount; +} + +// ======================================================================= +// 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..48c1afe17f --- /dev/null +++ b/tools/MessageModel/MessageModel_TableModelRealVec3Values.hxx @@ -0,0 +1,76 @@ +// 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 + +#include + +#include + +#include + +class ViewControl_TableModelFilter; + +//! \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 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; + + //! 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 GetValuesCount () const Standard_OVERRIDE { return myAttribute->GetValues().Length(); } + + //! Returns source row/column indices for the filtered model index for the given role + //! \param theSourceRow model row index + //! \param theSourceColumn model column index + //! \param theRow [out] row number value + //! \param theColumn [out] column value + Standard_EXPORT virtual void GetSourcePosition (const int theSourceRow, const int theSourceColumn, int& theRow, int& theColumn) const + { myFilter->GetSourcePosition (theSourceRow, theSourceColumn, theRow, theColumn); } + +private: + Handle(Message_AttributeVectorOfRealVec3) myAttribute; //!< alert attribute, container of table values + ViewControl_TableModelFilter* myFilter; //!< rearrange vector of values into a table view +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Tools.cxx b/tools/MessageModel/MessageModel_Tools.cxx new file mode 100644 index 0000000000..36c50c5ee9 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.cxx @@ -0,0 +1,290 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ======================================================================= +// function : GetPointerInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetPointerInfo (const Handle(Standard_Transient)& thePointer, const bool isShortInfo) +{ + if (thePointer.IsNull()) + return TCollection_AsciiString(); + + std::ostringstream aPtrStr; + aPtrStr << thePointer.operator->(); + if (!isShortInfo) + return aPtrStr.str().c_str(); + + TCollection_AsciiString anInfoPtr (aPtrStr.str().c_str()); + for (int aSymbolId = 1; aSymbolId < anInfoPtr.Length(); aSymbolId++) + { + if (anInfoPtr.Value(aSymbolId) != '0') + { + anInfoPtr = anInfoPtr.SubString (aSymbolId, anInfoPtr.Length()); + anInfoPtr.Prepend("0x"); + return anInfoPtr; + } + } + return aPtrStr.str().c_str(); +} + +// ======================================================================= +// function : GetPointerAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetPointerAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.IsNull()) + return TCollection_AsciiString(); + + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + return GetPointerInfo (Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape().TShape()); + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + return GetPointerInfo (Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject()); + return TCollection_AsciiString(); +} + +// ======================================================================= +// function : GetShapeTypeAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetShapeTypeAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.IsNull()) + return TCollection_AsciiString(); + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + TopoDS_Shape aShape; + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + aShape = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape(); + + if (aShape.IsNull()) + return TCollection_AsciiString(); + + TopAbs_ShapeEnum aShapeType = aShape.ShapeType(); + Standard_SStream aSStream; + TopAbs::Print ((TopAbs_ShapeEnum)aShapeType, aSStream); + return aSStream.str().c_str(); +} + +// ======================================================================= +// function : GetStandardTypeAlertInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetStandardTypeAlertInfo (const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.IsNull()) + return TCollection_AsciiString(); + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + return TCollection_AsciiString(); + + Handle(Standard_Transient) aPointer; + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + aPointer = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape().TShape(); + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + aPointer = Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject(); + + if (aPointer.IsNull()) + return TCollection_AsciiString(); + + return aPointer->DynamicType()->Name(); +} + +// ======================================================================= +// function : GetPropertyTableValues +// purpose : +// ======================================================================= +void MessageModel_Tools::GetPropertyTableValues (const Handle(Message_Alert)& theAlert, + QList& theTableValues) +{ + ViewControl_TableModelValues* aTableValues = 0; + + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast(theAlert); + if (aNodeAlert.IsNull()) + return; + + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + return; + + if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + { + int aSectionSize = MessageModel_TreeModel::GetVectorOfRealSectionSize(); + aTableValues = new MessageModel_TableModelRealValues (anAttribute, aSectionSize); + theTableValues.append (aTableValues); + } + else if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + { + int aSectionSize = MessageModel_TreeModel::GetVectorOfRealVec3SectionSize(); + 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 : GetPropertyTableValues +// purpose : +// ======================================================================= +void MessageModel_Tools::GetPropertyTableValues (const Handle(Message_Alert)& theAlert1, + const Handle(Message_Alert)& theAlert2, + QList& theTableValues) +{ + QList aTableValues1, aTableValues2; + + GetPropertyTableValues (theAlert1, aTableValues1); + GetPropertyTableValues (theAlert2, aTableValues2); + + if (aTableValues1.size() != aTableValues2.size()) + return; + + for (int i = 0; i < aTableValues1.size(); i++) + theTableValues.append(new MessageModel_TableModelCompareValues(aTableValues1[i], aTableValues2[i])); +} + +// ======================================================================= +// function : BuildShape +// purpose : +// ======================================================================= +TopoDS_Shape MessageModel_Tools::BuildShape (const Handle(Message_Alert)& theAlert, QList theSelectedIndices, ViewControl_Table* theTable) +{ + if (theAlert.IsNull()) + return TopoDS_Shape(); + + Handle(Message_AlertNode) aNodeAlert = Handle(Message_AlertNode)::DownCast (theAlert); + if (aNodeAlert.IsNull()) + return TopoDS_Shape(); + + Handle(Message_Attribute) anAttribute = aNodeAlert->Attribute(); + if (anAttribute.IsNull()) + return TopoDS_Shape(); + + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound(aCompound); + + if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal))) + { + Handle(Message_AttributeVectorOfReal) aValuesAlert = Handle(Message_AttributeVectorOfReal)::DownCast (anAttribute); + 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 (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfRealVec3))) + { + Handle(Message_AttributeVectorOfRealVec3) aValuesAlert = Handle(Message_AttributeVectorOfRealVec3)::DownCast (anAttribute); + 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..7c6975b5ce --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.hxx @@ -0,0 +1,84 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_Tools_H +#define MessageModel_Tools_H + +#include + +#include +#include +#include + +#include +#include +#include + +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); + + //! Fills container of table values based on compare of the parameter alerts + //! \param theAlert1 the first message alert + //! \param theAlert2 the second message alert + //! \param theTableValue container of values + Standard_EXPORT static void GetPropertyTableValues (const Handle(Message_Alert)& theAlert1, + const Handle(Message_Alert)& theAlert2, + 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..7a96f35ff9 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.cxx @@ -0,0 +1,168 @@ +// 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 : HasShape +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_TreeModel::HasReport (const Handle(Message_Report)& theReport) +{ + if (columnCount() == 0) + return Standard_False; + + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + return aRootItem && aRootItem->HasReport (theReport); +} + +// ======================================================================= +// function : AddShape +// purpose : +// ======================================================================= +void MessageModel_TreeModel::AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (!aRootItem) + continue; + aRootItem->AddReport (theReport, theReportDescription); + aRootItem->SetReversed (myIsReversed); + 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..2128cedf38 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.hxx @@ -0,0 +1,108 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_TreeModel_H +#define MessageModel_TreeModel_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class MessageModel_TreeModel; + +//! \class MessageModel_TreeModel +//! View model to visualize MessageReport/s content +class MessageModel_TreeModel : public TreeModel_ModelBase +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TreeModel (QObject* theParent); + + //! Destructor + virtual ~MessageModel_TreeModel() Standard_OVERRIDE {}; + + //! Returns true if parameter report was added into the model + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //! Add shape, append it to the model root item + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + Standard_EXPORT void SetReversed (const Standard_Boolean& theReversed); + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! 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(); + + //! Default section size for table of real values + static Standard_Integer GetVectorOfRealSectionSize() { return 60; } + + //! Default section size for table of values of three real + static Standard_Integer GetVectorOfRealVec3SectionSize() { return 160; } + +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 0000000000000000000000000000000000000000..a808bc55e505fa5e0dd00fc0df80eae5a9eac27c GIT binary patch literal 614 zcmV-s0-61ZP)b8c02hlmzzCYT+BYadXK|ku3NE#KtD1J<#s-Q>%sQ+!Pd3G zm6gg}U6+q^T}lH05CSkipMA8s`T6fXR$sZ?FF zZT+PvV&u1!A~?>>v-R~)PXS_v;(7bR$;s&(%Szt4ddE4y!ot0tvrgx{lgo*c5QVvJ z#rFN6W?9K}zYhLHk^}}2(Q=`%=V+RIXc&osvCHWJi^b}aZ5!_uMU>-;2>Ji|UbI{) zRoBMHlTQ%)?|O{a1y@&h%M%moYi2T28X^KAfB#At_CD5V zw4mAaLq(CA>9qOn0z5nOU$X2_AQBCryTFnpoQop$DJ92(fZqjyd_lwm z#^^`J@a^23(THuaP + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfReal.png b/tools/MessageModel/icons/item_vectorOfReal.png new file mode 100644 index 0000000000000000000000000000000000000000..7181f9460e4986e85dba66ca426b4cb2797c5a5b GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^!ayvgcyqV(DCY@~pSZg{#l zhFJ8zonn}G*nr2?K9tvFP1^Uws=fu+3m(U^PtcpV*TMhdX^YuetNWZc2Ai*TW#pIr z6mDnJbbwv6MS+2*tb?^-S*G0a!a3Oix3}dp%v+v$D*E%f*K$E#;oJQy;j9Uh_mVWFKf{g+P3I)AOy z*7$RGM@`;Y*CSmgE(%S2Hb?)kfsbh<$HQGZr={{$unc`-ETA4tmYw)LIL1oR_=r>mdKI;Vst0G)P;+W-In literal 0 HcmV?d00001 diff --git a/tools/MessageModel/icons/item_vectorOfReal.svg b/tools/MessageModel/icons/item_vectorOfReal.svg new file mode 100644 index 0000000000..38b1032701 --- /dev/null +++ b/tools/MessageModel/icons/item_vectorOfReal.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/tools/MessageModel/icons/item_vectorOfRealVec3.png b/tools/MessageModel/icons/item_vectorOfRealVec3.png new file mode 100644 index 0000000000000000000000000000000000000000..4d0ebf93d945e38f981902fdd551b149a5cd4bea GIT binary patch literal 421 zcmV;W0b2fvP)B`-7>Bsb(1K*cp8t`U@e50Gu> zXgL8LHR2G^@>774C`gOFvCZyK1dxzyIdl|x-P1gMGsV-;xwSzu3jnAkQ1`LYFY^JQ zLYL$&Ku2HZW*-lWLks|bZqrAeA0MnHcXQ_ZL7wNn36f=5&pB7g&UFBYh=u4yV@zzC z8)Jml8e$#Ty4t}0F1oNbroa;c@nxI)KBWo(_*M6**sA~_#ziW`+ch(XMhFox^H4fw zs+Bs4F&03n46 + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/tools/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..cec5d2fa1d --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.cxx @@ -0,0 +1,141 @@ +// 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_AlertNode) anAlertNode = Handle(Message_AlertNode)::DownCast(anAlert); + if (anAlertNode.IsNull()) + return TopoDS_Shape(); + + Handle(TopoDS_AlertAttribute) aShapeAttribute = Handle(TopoDS_AlertAttribute)::DownCast (anAlertNode->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; + + Handle(Message_AlertNode) anAlertNode = Handle(Message_AlertNode)::DownCast(anAlert); + if (anAlertNode.IsNull()) + return false; + + Handle(Message_Attribute) anAttribute = anAlertNode->Attribute(); + if (anAttribute.IsNull()) + return false; + + if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeVectorOfReal)) || + anAttribute->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..110e05e5ac --- /dev/null +++ b/tools/MessageView/MessageView_Window.cxx @@ -0,0 +1,649 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include +//#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + } + Handle(Message_Report) aDefaultReport = Message_Report::CurrentReport( Standard_False); + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aDefaultReport.IsNull() && !aViewModel->HasReport (aDefaultReport)) + { + aDefaultReport->SetCallBack (myCallBack); + addReport (aDefaultReport); + } + + // reload report of selected item + onReloadReport(); + + updateTreeModel(); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageView_Window::Init (NCollection_List& theParameters) +{ + Handle(AIS_InteractiveContext) aContext; + NCollection_List aParameters; + + 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(); + + QModelIndexList aFirstColumnSelected = TreeModel_ModelBase::GetSelected (aSelectedIndices, 0); + if (aFirstColumnSelected.size() == 1) + { + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (aFirstColumnSelected.first()); + if (itemDynamicCast (anItemBase)) + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Import Report"), SLOT (onImportReport()), myMainWindow, this)); + else if (itemDynamicCast (anItemBase)) + { + aReportItem = itemDynamicCast(anItemBase); + 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)); + } + } + } + else if (aFirstColumnSelected.size() == 2) + { + MessageModel_ItemAlertPtr anAlertItem1 = itemDynamicCast + (TreeModel_ModelBase::GetItemByIndex (aFirstColumnSelected.at(0))); + MessageModel_ItemAlertPtr anAlertItem2 = itemDynamicCast + (TreeModel_ModelBase::GetItemByIndex (aFirstColumnSelected.at(1))); + if (anAlertItem1 && anAlertItem2) + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Compare"), SLOT (onCompareAlerts()), 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 : onCompareAlerts +// purpose : +// ======================================================================= +void MessageView_Window::onCompareAlerts() +{ + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + QModelIndexList aFirstColumnSelected = TreeModel_ModelBase::GetSelected (aSelectedIndices, 0); + if (aFirstColumnSelected.size() != 2) + return; + + MessageModel_ItemAlertPtr anAlertItem1 = itemDynamicCast + (TreeModel_ModelBase::GetItemByIndex (aFirstColumnSelected.at(0))); + MessageModel_ItemAlertPtr anAlertItem2 = itemDynamicCast + (TreeModel_ModelBase::GetItemByIndex (aFirstColumnSelected.at(1))); + + if (!anAlertItem1 || !anAlertItem2) + return; + +} + +// ======================================================================= +// function : updatePropertyPanelBySelection +// purpose : +// ======================================================================= +void MessageView_Window::updatePropertyPanelBySelection() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndexList aSelected = TreeModel_ModelBase::GetSelected (aModel->selectedIndexes(), 0); + QList aTableValues; + if (aSelected.size() == 1) + { + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast( + TreeModel_ModelBase::GetItemByIndex (aSelected.first())); + if (anAlertItem) + MessageModel_Tools::GetPropertyTableValues (anAlertItem->GetAlert(), aTableValues); + } + else if (aSelected.size() == 2) + { + MessageModel_ItemAlertPtr anAlertItem1 = itemDynamicCast( + TreeModel_ModelBase::GetItemByIndex (aSelected.at(0))); + MessageModel_ItemAlertPtr anAlertItem2 = itemDynamicCast( + TreeModel_ModelBase::GetItemByIndex (aSelected.at(1))); + if (anAlertItem1 && anAlertItem2) + MessageModel_Tools::GetPropertyTableValues (anAlertItem1->GetAlert(), anAlertItem2->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..69cfff82ad --- /dev/null +++ b/tools/MessageView/MessageView_Window.hxx @@ -0,0 +1,172 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_Window_H +#define MessageView_Window_H + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#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(); + + //! Compares selected alerts + void onCompareAlerts(); + +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/ShapeView/ShapeView_ItemShape.cxx b/tools/ShapeView/ShapeView_ItemShape.cxx index 952534ba4a..6bdd6bdbac 100644 --- a/tools/ShapeView/ShapeView_ItemShape.cxx +++ b/tools/ShapeView/ShapeView_ItemShape.cxx @@ -31,6 +31,9 @@ #include #include +#include +#include + #include #include #include @@ -189,7 +192,15 @@ QString locationInfo (const TopLoc_Location& theLocation) // ======================================================================= TopoDS_Shape ShapeView_ItemShape::GetShape (const int theRowId) const { - TopoDS_Iterator aSubShapeIt (myShape); + if (myExplodeType != TopAbs_SHAPE) + { + TopTools_IndexedMapOfShape aSubShapes; + TopExp::MapShapes(myShape, myExplodeType, aSubShapes); + + return aSubShapes(theRowId + 1); + } + + TopoDS_Iterator aSubShapeIt(myShape); for (int aCurrentIndex = 0; aSubShapeIt.More(); aSubShapeIt.Next(), aCurrentIndex++) { if (aCurrentIndex != theRowId) @@ -266,6 +277,7 @@ QVariant ShapeView_ItemShape::initValue(const int theRole) const case 19: return aCurve->IsPeriodic() ? QString::number (aCurve->Period()) : ToString (aCurve->IsPeriodic()); } } + case 20: return Row() + 1; default: break; } return QVariant(); @@ -282,8 +294,17 @@ int ShapeView_ItemShape::initRowCount() const return 0; int aRowsCount = 0; - for (TopoDS_Iterator aSubShapeIt(aShape); aSubShapeIt.More(); aSubShapeIt.Next()) - aRowsCount++; + if (myExplodeType != TopAbs_SHAPE) + { + TopTools_IndexedMapOfShape aSubShapes; + TopExp::MapShapes(aShape, myExplodeType, aSubShapes); + aRowsCount = aSubShapes.Extent(); + } + else + { + for (TopoDS_Iterator aSubShapeIt(aShape); aSubShapeIt.More(); aSubShapeIt.Next()) + aRowsCount++; + } return aRowsCount; } diff --git a/tools/ShapeView/ShapeView_ItemShape.hxx b/tools/ShapeView/ShapeView_ItemShape.hxx index b04076956e..158e1998f2 100644 --- a/tools/ShapeView/ShapeView_ItemShape.hxx +++ b/tools/ShapeView/ShapeView_ItemShape.hxx @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,13 @@ public: //! Destructor virtual ~ShapeView_ItemShape() Standard_OVERRIDE {}; + //! Sets explore type + //! \param theType type of item explode. If TopAbs_SHAPE, no expode, only iteration by shape + void SetExplodeType (const TopAbs_ShapeEnum theType) { myExplodeType = theType; } + + //! Returns expode type of the item + TopAbs_ShapeEnum GetExplodeType() const { return myExplodeType; } + //! Returns the current shape const TopoDS_Shape& GetItemShape() const { initItem(); return myShape; } @@ -108,10 +116,11 @@ protected: private: //! Constructor - ShapeView_ItemShape(TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) - : ShapeView_ItemBase(theParent, theRow, theColumn) {} + ShapeView_ItemShape (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : ShapeView_ItemBase (theParent, theRow, theColumn), myExplodeType (TopAbs_SHAPE) {} private: + TopAbs_ShapeEnum myExplodeType; //!< type of explore own shape and get children TopoDS_Shape myShape; //!< current shape QString myFileName; //!< BREP file name diff --git a/tools/ShapeView/ShapeView_Tools.cxx b/tools/ShapeView/ShapeView_Tools.cxx index afa6de4571..70e4e8f21e 100644 --- a/tools/ShapeView/ShapeView_Tools.cxx +++ b/tools/ShapeView/ShapeView_Tools.cxx @@ -19,6 +19,9 @@ #include #include + +#include + // ======================================================================= // function : ReadShape // purpose : @@ -31,3 +34,24 @@ TopoDS_Shape ShapeView_Tools::ReadShape (const TCollection_AsciiString& theFileN BRepTools::Read (aShape, theFileName.ToCString(), aBuilder); return aShape; } + +// ======================================================================= +// function : IsPossibleToExplode +// purpose : +// ======================================================================= +Standard_Boolean ShapeView_Tools::IsPossibleToExplode (const TopoDS_Shape& theShape, + NCollection_List& theExplodeTypes) +{ + TopAbs_ShapeEnum aShapeType = theShape.ShapeType(); + + TopTools_IndexedMapOfShape aSubShapes; + for (int aType = aShapeType + 1; aType <= TopAbs_SHAPE; aType++) + { + aSubShapes.Clear(); + TopExp::MapShapes(theShape, (TopAbs_ShapeEnum)aType, aSubShapes); + if (aSubShapes.Extent() > 0) + theExplodeTypes.Append((TopAbs_ShapeEnum)aType); + } + + return theExplodeTypes.Size() > 0; +} diff --git a/tools/ShapeView/ShapeView_Tools.hxx b/tools/ShapeView/ShapeView_Tools.hxx index a922e42b36..4bb36c8678 100644 --- a/tools/ShapeView/ShapeView_Tools.hxx +++ b/tools/ShapeView/ShapeView_Tools.hxx @@ -32,6 +32,12 @@ public: //! \param theFileName a file name //! \return shape or NULL Standard_EXPORT static TopoDS_Shape ReadShape (const TCollection_AsciiString& theFileName); + + //! Checks whether it is possible to expode the shape + //! \param theShape source shape object + //! \param theExplodeTypes container of possible shape types to be exploded + Standard_EXPORT static Standard_Boolean IsPossibleToExplode(const TopoDS_Shape& theShape, + NCollection_List& theExplodeTypes); }; #endif diff --git a/tools/ShapeView/ShapeView_TreeModel.cxx b/tools/ShapeView/ShapeView_TreeModel.cxx index bc29c119ae..0527d44da7 100644 --- a/tools/ShapeView/ShapeView_TreeModel.cxx +++ b/tools/ShapeView/ShapeView_TreeModel.cxx @@ -57,6 +57,7 @@ ShapeView_TreeModel::ShapeView_TreeModel (QObject* theParent) SetHeaderItem (17, TreeModel_HeaderSection ("Continuity", -1, true)); SetHeaderItem (18, TreeModel_HeaderSection ("IsClosed", -1, true)); SetHeaderItem (19, TreeModel_HeaderSection ("IsPeriodic", -1, true)); + SetHeaderItem (20, TreeModel_HeaderSection ("Index", -1, true)); } // ======================================================================= @@ -107,11 +108,9 @@ void ShapeView_TreeModel::RemoveAllShapes() // ======================================================================= QModelIndex ShapeView_TreeModel::FindIndex (const TopoDS_Shape& theShape) const { - QModelIndex aParentIndex = index (0, 0); - TreeModel_ItemBasePtr aParentItem = TreeModel_ModelBase::GetItemByIndex (aParentIndex); // application item - for (int aChildId = 0, aCount = aParentItem->rowCount(); aChildId < aCount; aChildId++) + for (int aChildId = 0, aCount = rowCount(); aChildId < aCount; aChildId++) { - QModelIndex anIndex = index (aChildId, 0, aParentIndex); + QModelIndex anIndex = index (aChildId, 0); ShapeView_ItemShapePtr anItem = itemDynamicCast (TreeModel_ModelBase::GetItemByIndex (anIndex)); if (anItem && anItem->GetItemShape() == theShape) return anIndex; diff --git a/tools/ShapeView/ShapeView_Window.cxx b/tools/ShapeView/ShapeView_Window.cxx index 76eaefa6b4..4892dbc668 100644 --- a/tools/ShapeView/ShapeView_Window.cxx +++ b/tools/ShapeView/ShapeView_Window.cxx @@ -348,15 +348,44 @@ void ShapeView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition ShapeView_ItemRootPtr aRootItem = itemDynamicCast (anItemBase); if (aRootItem) { aMenu->addAction (ViewControl_Tools::CreateAction ("Load BREP file", SLOT (onLoadFile()), myMainWindow, this)); + aMenu->addAction (ViewControl_Tools::CreateAction ("Load BREP file from a directory", SLOT (onLoadDirectory()), myMainWindow, this)); aMenu->addAction (ViewControl_Tools::CreateAction ("Remove all shape items", SLOT (onClearView()), myMainWindow, this)); } - else { + else + { if (!GetTemporaryDirectory().IsEmpty()) aMenu->addAction (ViewControl_Tools::CreateAction ("BREP view", SLOT (onBREPView()), myMainWindow, this)); aMenu->addAction (ViewControl_Tools::CreateAction ("Close All BREP views", SLOT (onCloseAllBREPViews()), myMainWindow, this)); aMenu->addAction (ViewControl_Tools::CreateAction ("BREP directory", SLOT (onBREPDirectory()), myMainWindow, this)); + + ShapeView_ItemShapePtr aShapeItem = itemDynamicCast(anItemBase); + const TopoDS_Shape& aShape = aShapeItem->GetItemShape(); + TopAbs_ShapeEnum anExplodeType = aShapeItem->GetExplodeType(); + NCollection_List anExplodeTypes; + if (ShapeView_Tools::IsPossibleToExplode (aShape, anExplodeTypes)) + { + QMenu* anExplodeMenu = aMenu->addMenu ("Explode"); + for (NCollection_List::Iterator anExpIterator (anExplodeTypes); anExpIterator.More(); + anExpIterator.Next()) + { + TopAbs_ShapeEnum aType = anExpIterator.Value(); + QAction* anAction = ViewControl_Tools::CreateAction (TopAbs::ShapeTypeToString (aType), SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addAction (anAction); + if (anExplodeType == aType) + { + anAction->setCheckable (true); + anAction->setChecked (true); + } + } + QAction* anAction = ViewControl_Tools::CreateAction ("NONE", SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addSeparator(); + anExplodeMenu->addAction (anAction); + } } + //aMenu->addAction(ViewControl_Tools::CreateAction("BREP directory", SLOT(onBREPDirectory()), myMainWindow, this)); + + QPoint aPoint = myTreeView->mapToGlobal (thePosition); aMenu->exec (aPoint); } @@ -389,6 +418,46 @@ void ShapeView_Window::onBREPDirectory() viewFile (aFileName); } +// ======================================================================= +// function : onExplode +// purpose : +// ======================================================================= +void ShapeView_Window::onExplode() +{ + 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; + + ShapeView_ItemShapePtr aShapeItem = itemDynamicCast(anItemBase); + if (!aShapeItem) + return; + + QAction* anAction = (QAction*)sender(); + if (!anAction) + return; + + QApplication::setOverrideCursor (Qt::WaitCursor); + TopAbs_ShapeEnum aShapeType; + if (anAction->text() == "NONE") + aShapeType = TopAbs_SHAPE; + else + aShapeType = TopAbs::ShapeTypeFromString(anAction->text().toStdString().c_str()); + + myViewWindow->GetDisplayer()->EraseAllPresentations(); + aShapeItem->SetExplodeType(aShapeType); + + //anItemBase->Parent()->Reset(); - TODO (update only modified sub-tree) + ShapeView_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + aTreeModel->Reset(); + aTreeModel->EmitLayoutChanged(); + QApplication::restoreOverrideCursor(); +} + // ======================================================================= // function : onLoadFile // purpose : @@ -403,6 +472,25 @@ void ShapeView_Window::onLoadFile() onOpenFile(aFileName); } +// ======================================================================= +// function : onLoadDirectory +// purpose : +// ======================================================================= +void ShapeView_Window::onLoadDirectory() +{ + QString aDirectory = QFileDialog::getExistingDirectory(0, tr("Select directory")); + + QFileInfo aFileInfo(aDirectory); + if (!aFileInfo.exists() || !aFileInfo.isReadable()) + return; + + QDir aDir(aDirectory); + QStringList aFileNames = aDir.entryList(QDir::Files, QDir::Name); + + for (int i = 0; i < aFileNames.size(); i++) + onOpenFile(aDir.absoluteFilePath(aFileNames[i])); +} + // ======================================================================= // function : onBREPView // purpose : diff --git a/tools/ShapeView/ShapeView_Window.hxx b/tools/ShapeView/ShapeView_Window.hxx index 39274f8939..6d56d0b252 100644 --- a/tools/ShapeView/ShapeView_Window.hxx +++ b/tools/ShapeView/ShapeView_Window.hxx @@ -114,12 +114,18 @@ protected slots: //! Exports shape to BREP file and view result file void onBREPDirectory(); + //! Set the shape item exploded + void onExplode(); + //! Removes all shapes in tree view void onClearView() { RemoveAllShapes(); } //! Load BREP file and updates tree model to have shape of the file void onLoadFile(); + //! Load BREP files from the selected directory and updates tree model to have shapes of the files + void onLoadDirectory(); + //! View BREP files of selected items if exist void onBREPView(); diff --git a/tools/TInspectorEXE/TInspectorEXE.cxx b/tools/TInspectorEXE/TInspectorEXE.cxx index 10dcf4b845..3256336f43 100644 --- a/tools/TInspectorEXE/TInspectorEXE.cxx +++ b/tools/TInspectorEXE/TInspectorEXE.cxx @@ -103,6 +103,9 @@ int main (int argc, char** argv) if (!strcmp (argv[anArgId], "vinspector")) aPlugins.insert ("TKVInspector"); + + if (!strcmp (argv[anArgId], "messageview")) + aPlugins.insert ("TKMessageView"); } NCollection_List aParameters; @@ -121,6 +124,7 @@ int main (int argc, char** argv) aPlugins.insert("TKDFBrowser"); aPlugins.insert("TKShapeView"); aPlugins.insert("TKVInspector"); + aPlugins.insert("TKMessageView"); anActivatedPluginName = "TKDFBrowser"; } 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/TKTreeModel/CMakeLists.txt b/tools/TKTreeModel/CMakeLists.txt index 99fc025494..de376fe964 100644 --- a/tools/TKTreeModel/CMakeLists.txt +++ b/tools/TKTreeModel/CMakeLists.txt @@ -1,5 +1,7 @@ project(TKTreeModel) +add_definitions("-D__ViewControl_DLL") + 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/ToolsDraw/ToolsDraw.cxx b/tools/ToolsDraw/ToolsDraw.cxx index 392996998f..2585e3ff8c 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; } @@ -297,6 +298,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(); } @@ -383,7 +385,7 @@ void ToolsDraw::Commands(Draw_Interpretor& theCommands) "\n\t\t: Starts tool of inspection." "\n\t\t: Options:" "\n\t\t: -plugins enters plugins that should be added in the inspector." - "\n\t\t: Available names are: dfbrowser, vinspector and shapeview." + "\n\t\t: Available names are: dfbrowser, vinspector, shapeview and messageview." "\n\t\t: Plugins order will be the same as defined in arguments." "\n\t\t: 'all' adds all available plugins in the order:" "\n\t\t: DFBrowser, VInspector and ShapeView." diff --git a/tools/TreeModel/TreeModel_ModelBase.cxx b/tools/TreeModel/TreeModel_ModelBase.cxx index 72acad8d01..90f447c641 100644 --- a/tools/TreeModel/TreeModel_ModelBase.cxx +++ b/tools/TreeModel/TreeModel_ModelBase.cxx @@ -66,10 +66,6 @@ QModelIndex TreeModel_ModelBase::index (int theRow, int theColumn, const QModelI if (!hasIndex (theRow, theColumn, theParent)) return QModelIndex(); - // to create index on the root item - if (!theParent.isValid()) - return createIndex (theRow, theColumn, getIndexValue (RootItem (theColumn))); - TreeModel_ItemBasePtr aParentItem; if (!theParent.isValid()) aParentItem = RootItem (theColumn); @@ -164,10 +160,6 @@ QVariant TreeModel_ModelBase::headerData (int theSection, Qt::Orientation theOri // ======================================================================= int TreeModel_ModelBase::rowCount (const QModelIndex& theParent) const { - // to create index on the root item - if (!theParent.isValid()) - return 1; - TreeModel_ItemBasePtr aParentItem; if (!theParent.isValid()) aParentItem = RootItem (0); @@ -207,21 +199,32 @@ void TreeModel_ModelBase::EmitDataChanged (const QModelIndex& theTopLeft, const } // ======================================================================= -// function : SingleSelected +// function : GetSelected // purpose : // ======================================================================= -QModelIndex TreeModel_ModelBase::SingleSelected (const QModelIndexList& theIndices, const int theCellId, - const Qt::Orientation theOrientation) +QModelIndexList TreeModel_ModelBase::GetSelected (const QModelIndexList& theIndices, const int theCellId, + const Qt::Orientation theOrientation) { - QModelIndexList aFirstColumnSelectedIndices; + QModelIndexList aSelected; for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++) { QModelIndex anIndex = *anIndicesIt; if ((theOrientation == Qt::Horizontal && anIndex.column() == theCellId) || (theOrientation == Qt::Vertical && anIndex.row() == theCellId)) - aFirstColumnSelectedIndices.append (anIndex); + aSelected.append (anIndex); } - return aFirstColumnSelectedIndices.size() == 1 ? aFirstColumnSelectedIndices.first() : QModelIndex(); + return aSelected; +} + +// ======================================================================= +// function : SingleSelected +// purpose : +// ======================================================================= +QModelIndex TreeModel_ModelBase::SingleSelected (const QModelIndexList& theIndices, const int theCellId, + const Qt::Orientation theOrientation) +{ + QModelIndexList aSelected = GetSelected (theIndices, theCellId, theOrientation); + return aSelected.size() == 1 ? aSelected.first() : QModelIndex(); } // ======================================================================= diff --git a/tools/TreeModel/TreeModel_ModelBase.hxx b/tools/TreeModel/TreeModel_ModelBase.hxx index d304c164e5..a86b683ef7 100644 --- a/tools/TreeModel/TreeModel_ModelBase.hxx +++ b/tools/TreeModel/TreeModel_ModelBase.hxx @@ -146,6 +146,14 @@ public: //! \return integer value static int ColumnVisibilityWidth() { return 20; } + //! Returns selected items in the cell of given orientation. + //! \param theIndices a container of selected indices + //! \param theCellId column index if orientation is horizontal, row index otherwise + //! \param theOrientation an orientation to apply the cell index + //! \return model indices from the list + Standard_EXPORT static QModelIndexList GetSelected (const QModelIndexList& theIndices, const int theCellId, + const Qt::Orientation theOrientation = Qt::Horizontal); + //! Returns single selected item in the cell of given orientation. If the orientation is Horizontal, //! in the cell id colum, one row should be selected. //! \param theIndices a container of selected indices diff --git a/tools/VInspector/VInspector_ViewModel.cxx b/tools/VInspector/VInspector_ViewModel.cxx index d8f6c026a5..efa56f2675 100644 --- a/tools/VInspector/VInspector_ViewModel.cxx +++ b/tools/VInspector/VInspector_ViewModel.cxx @@ -105,11 +105,9 @@ void VInspector_ViewModel::SetContext (const Handle(AIS_InteractiveContext)& the QModelIndexList VInspector_ViewModel::FindPointers (const QStringList& thePointers) { QModelIndexList anIndices; - QModelIndex aParentIndex = index (0, 0); - TreeModel_ItemBasePtr aParentItem = TreeModel_ModelBase::GetItemByIndex (aParentIndex); // context item - for (int aRowId = 0, aCount = aParentItem->rowCount(); aRowId < aCount; aRowId++) + for (int aRowId = 0, aCount = rowCount(); aRowId < aCount; aRowId++) { - QModelIndex anIndex = index (aRowId, 0, aParentIndex); + QModelIndex anIndex = index (aRowId, 0); TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); VInspector_ItemPresentableObjectPtr anItemPrs = itemDynamicCast(anItemBase); if (!anItemPrs) diff --git a/tools/View/View_Tools.cxx b/tools/View/View_Tools.cxx index 1699446f00..3ecb175c22 100644 --- a/tools/View/View_Tools.cxx +++ b/tools/View/View_Tools.cxx @@ -45,7 +45,11 @@ void View_Tools::SaveState (View_Window* theView, QMap& theIte { QStringList aCameraDirection; Standard_Real aVX, aVY, aVZ; - theView->GetView()->GetViewer()->GetView()->Proj (aVX, aVY, aVZ); + Handle(V3d_View) aView = theView->GetView()->GetViewer()->GetView(); + if (aView.IsNull()) + return; + + aView->Proj (aVX, aVY, aVZ); aCameraDirection << QString::number (aVX) << QString::number (aVY) << QString::number (aVZ); theItems[thePrefix + "view_camera_direction"] = aCameraDirection.join (","); diff --git a/tools/View/View_Window.cxx b/tools/View/View_Window.cxx index 98edc7485c..d697fb6dc9 100644 --- a/tools/View/View_Window.cxx +++ b/tools/View/View_Window.cxx @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -160,9 +161,9 @@ void View_Window::onViewContextMenuRequested (const QPoint& thePosition) { #if TINSPECTORAPI_VERSION_HEX > 0x070200 QMenu* aMenu = new QMenu (this); - QMenu* anOrientationSubMenu = aMenu->addMenu ("Set View Orientation"); - for (int i = 0; i < (int)V3d_XnegYnegZneg; i++) + QMenu* anOrientationSubMenu = aMenu->addMenu ("Set View Orientation"); + for (int i = 0; i <= (int)V3d_XnegYnegZneg; i++) { V3d_TypeOfOrientation anOrientationType = (V3d_TypeOfOrientation)i; anOrientationSubMenu->addAction (View_Tools::CreateAction (V3d::TypeOfOrientationToString (anOrientationType), @@ -170,6 +171,18 @@ void View_Window::onViewContextMenuRequested (const QPoint& thePosition) } aMenu->addMenu (anOrientationSubMenu); + anOrientationSubMenu = aMenu->addMenu ("Activate Selection Mode"); + for (int i = TopAbs_COMPOUND; i <= (int)TopAbs_SHAPE; i++) + { + anOrientationSubMenu->addAction (View_Tools::CreateAction (TopAbs::ShapeTypeToString((TopAbs_ShapeEnum)i), + SLOT (onActivateSelectionMode()), this, this)); + } + aMenu->addMenu (anOrientationSubMenu); + + anOrientationSubMenu->addSeparator(); + anOrientationSubMenu->addAction (View_Tools::CreateAction ("NONE", + SLOT (onActivateSelectionMode()), this, this)); + QPoint aPoint = myView->mapToGlobal (thePosition); aMenu->exec (aPoint); #else @@ -186,10 +199,9 @@ void View_Window::onSetOrientation() #if TINSPECTORAPI_VERSION_HEX > 0x070200 QAction* anAction = (QAction*)(sender()); - TCollection_AsciiString anOrientationStr (anAction->text().toStdString().c_str()); - + TCollection_AsciiString anActionText (anAction->text().toStdString().c_str()); V3d_TypeOfOrientation anOrientationType; - if (!V3d::TypeOfOrientationFromString (anOrientationStr.ToCString(), anOrientationType)) + if (!V3d::TypeOfOrientationFromString (anActionText.ToCString(), anOrientationType)) return; Handle(V3d_View) aView = myView->GetViewer()->GetView(); @@ -202,6 +214,31 @@ void View_Window::onSetOrientation() #endif } +// ======================================================================= +// function : onActivateSelectionMode +// purpose : +// ======================================================================= +void View_Window::onActivateSelectionMode() +{ + Handle(AIS_InteractiveContext) aContext = myView->GetViewer()->GetContext(); + if (aContext.IsNull()) + return; + + QAction* anAction = (QAction*)(sender()); + TCollection_AsciiString anActionText (anAction->text().toStdString().c_str()); + + if (anActionText == "NONE") + { + aContext->Deactivate(); + return; + } + + TopAbs_ShapeEnum aShapeType; + if (!TopAbs::ShapeTypeFromString (anActionText.ToCString(), aShapeType)) + return; + aContext->Activate (AIS_Shape::SelectionMode (aShapeType)); +} + // ======================================================================= // function : onDisplayModeChanged // purpose : diff --git a/tools/View/View_Window.hxx b/tools/View/View_Window.hxx index 91eb8018c1..f145e45248 100644 --- a/tools/View/View_Window.hxx +++ b/tools/View/View_Window.hxx @@ -89,6 +89,9 @@ protected slots: //! Sets the view scene orientation by the text of selected action void onSetOrientation(); + //! Activates selection mode in the viewer + void onActivateSelectionMode(); + //! Sets selected display mode in the current context void onDisplayModeChanged(); diff --git a/tools/ViewControl/FILES b/tools/ViewControl/FILES index 432c6f8adf..7cce9b5efd 100644 --- a/tools/ViewControl/FILES +++ b/tools/ViewControl/FILES @@ -1,5 +1,18 @@ +ViewControl.hxx ViewControl_MessageDialog.cxx ViewControl_MessageDialog.hxx +ViewControl_PropertyView.cxx +ViewControl_PropertyView.hxx +ViewControl_Table.cxx +ViewControl_Table.hxx +ViewControl_TableModel.cxx +ViewControl_TableModel.hxx +ViewControl_TableModelFilter.cxx +ViewControl_TableModelFilter.hxx +ViewControl_TableModelValues.cxx +ViewControl_TableModelValues.hxx +ViewControl_TableProperty.cxx +ViewControl_TableProperty.hxx ViewControl_Tools.cxx ViewControl_Tools.hxx -ViewControl_TreeView.hxx \ No newline at end of file +ViewControl_TreeView.hxx diff --git a/tools/ViewControl/ViewControl.hxx b/tools/ViewControl/ViewControl.hxx new file mode 100644 index 0000000000..1ea5334638 --- /dev/null +++ b/tools/ViewControl/ViewControl.hxx @@ -0,0 +1,33 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef VIEWCONTROL_H +#define VIEWCONTROL_H + +#ifdef __ViewControl_DLL + #ifdef _WIN32 + #define VIEWCONTROL_EXPORT __declspec(dllexport) + #else + #define VIEWCONTROL_EXPORT + #endif +#else + #ifdef _WIN32 + #define VIEWCONTROL_EXPORT __declspec(dllimport) + #else + #define VIEWCONTROL_EXPORT + #endif +#endif + +#endif diff --git a/tools/ViewControl/ViewControl_PropertyView.cxx b/tools/ViewControl/ViewControl_PropertyView.cxx new file mode 100644 index 0000000000..ff38360770 --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertyView.cxx @@ -0,0 +1,279 @@ +// 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 + +class ViewControl_Widget : public QWidget +{ +public: + //! Constructor + ViewControl_Widget (QWidget* theParent, const QSize& theSize) : QWidget (theParent) { SetPredefinedSize (theSize); } + + //! Destructor + virtual ~ViewControl_Widget() {} + + //! Sets default size of control, that is used by the first control show + //! \param theDefaultWidth the width value + //! \param theDefaultHeight the height value + void SetPredefinedSize (const QSize& theSize) { myDefaultSize = theSize;} + + //! Returns predefined size if both values are positive, otherwise parent size hint + virtual QSize sizeHint() const Standard_OVERRIDE { return myDefaultSize.isValid() ? myDefaultSize : QWidget::sizeHint(); } + +private: + QSize myDefaultSize; //! default size, empty isze if it should not be used +}; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +ViewControl_PropertyView::ViewControl_PropertyView (QWidget* theParent) +: QObject (theParent), myOwnSelectionChangeBlocked (false) +{ + myMainWidget = new ViewControl_Widget (theParent, QSize (1, 100)); + + QVBoxLayout* aLayout = new QVBoxLayout (myMainWidget); + aLayout->setContentsMargins (0, 0, 0, 0); + + QScrollArea* anArea = new QScrollArea (myMainWidget); + + myAttributesStack = new QStackedWidget (myMainWidget); + anArea->setWidget (myAttributesStack); + anArea->setWidgetResizable( true ); + aLayout->addWidget (anArea); + + myEmptyWidget = new QWidget (myAttributesStack); + myAttributesStack->addWidget (myEmptyWidget); + + myTableWidget = new QWidget (myAttributesStack); + myTableWidgetLayout = new QVBoxLayout (myTableWidget); + myTableWidgetLayout->setContentsMargins (0, 0, 0, 0); + myAttributesStack->addWidget (myTableWidget); + + myAttributesStack->setCurrentWidget (myEmptyWidget); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void ViewControl_PropertyView::Init (const QList& theTableValues) +{ + for (int aTableId = 0; aTableId < theTableValues.size(); aTableId++) + { + ViewControl_TableModelValues* aValues = theTableValues[aTableId]; + + ViewControl_Table* aTable = findTable (aTableId); + + aTable->Init (aValues); + ViewControl_Tools::SetDefaultHeaderSections (aTable->GetTableView(), Qt::Horizontal); + + aTable->SetActive (true); + } + // hide not used tables + for (int aTableId = theTableValues.size(); aTableId < myTables.size(); aTableId++) + { + ViewControl_Table* aTable = findTable (aTableId, false); + if (!aTable) + continue; + + ViewControl_TableModel* aModel = dynamic_cast (aTable->GetTableView()->model()); + aModel->SetModelValues (0); + + aTable->SetActive (false); + } + + if (theTableValues.size() > 0) + myAttributesStack->setCurrentWidget (myTableWidget); + else + myAttributesStack->setCurrentWidget (myEmptyWidget); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void ViewControl_PropertyView::Init (QWidget*) +{ +} + +// ======================================================================= +// function : GetActiveTables +// purpose : +// ======================================================================= +void ViewControl_PropertyView::GetActiveTables (QList& theTables) +{ + for (int aTableId = 0; aTableId < myTables.size(); aTableId++) + { + ViewControl_Table* aTable = findTable (aTableId, false); + if (aTable && aTable->IsActive()) + theTables.append (aTable); + } +} + +// ======================================================================= +// function : ClearActiveTablesSelection +// purpose : +// ======================================================================= +void ViewControl_PropertyView::ClearActiveTablesSelection() +{ + bool aWasBlocked = myOwnSelectionChangeBlocked; + myOwnSelectionChangeBlocked = true; + + QList aTables; + for (int aTableId = 0; aTableId < myTables.size(); aTableId++) + { + ViewControl_Table* aTable = findTable (aTableId, false); + if (aTable && aTable->IsActive()) + aTable->GetTableView()->selectionModel()->clearSelection(); + } + myOwnSelectionChangeBlocked = aWasBlocked; +} + +// ======================================================================= +// function : Clear +// purpose : +// ======================================================================= +void ViewControl_PropertyView::Clear() +{ + for (int aTableId = 0; aTableId < myTables.size(); aTableId++) + { + ViewControl_Table* aTable = findTable (aTableId, false); + if (!aTable) + continue; + + ViewControl_TableModel* aModel = dynamic_cast (aTable->GetTableView()->model()); + aModel->SetModelValues (0); + + aTable->SetActive (true); + } + myAttributesStack->setCurrentWidget (myEmptyWidget); +} + +// ======================================================================= +// function : findTable +// purpose : +// ======================================================================= +ViewControl_Table* ViewControl_PropertyView::findTable (const int theTableId, const bool isToCreate) +{ + if (!isToCreate && theTableId >= myTables.size()) + return 0; + + if (theTableId < myTables.size()) + return myTables[theTableId]; + + ViewControl_Table* aTable = new ViewControl_Table (myMainWidget); + ViewControl_TableModel* aModel = new ViewControl_TableModel(aTable->GetTableView()); + aTable->SetModel (aModel); + + + connect (aTable->GetTableView()->selectionModel(), + SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), + this, SLOT(onTableSelectionChanged (const QItemSelection&, const QItemSelection&))); + connect (aTable->GetProperty(), SIGNAL (propertyChanged()), this, SIGNAL (propertyViewSelectionChanged())); + + if (myXStepValues.size() > theTableId) + aTable->GetProperty()->SetXStep (myXStepValues[theTableId]); + + if (myDivideValues.size() > theTableId) + aTable->GetProperty()->SetDivideSize (myDivideValues[theTableId]); + + myTableWidgetLayout->addWidget (aTable->GetControl()); + + myTables.insert (theTableId, aTable); + + return myTables[theTableId]; +} + +// ======================================================================= +// function : onTableSelectionChanged +// purpose : +// ======================================================================= +void ViewControl_PropertyView::onTableSelectionChanged (const QItemSelection&, const QItemSelection&) +{ + if (myOwnSelectionChangeBlocked) + return; + + emit propertyViewSelectionChanged(); +} + +// ======================================================================= +// function : SaveState +// purpose : +// ======================================================================= +void ViewControl_PropertyView::SaveState (ViewControl_PropertyView* theView, + QMap& theItems, + const QString& thePrefix) +{ + QList anActiveTables; + theView->GetActiveTables(anActiveTables); + + if (anActiveTables.size() == 0) + return; + + anActiveTables[0]->GetProperty()->GetXStep(); + QStringList aDivideSizes, aXSteps; + for (int i = 0; i < anActiveTables.size(); i++) + { + aXSteps.append (QString::number (anActiveTables[i]->GetProperty()->GetXStep())); + aDivideSizes.append (QString::number (anActiveTables[i]->GetProperty()->GetDivideSize())); + } + theItems[thePrefix + "property_view_xstep_value"] = aXSteps.join (","); + theItems[thePrefix + "property_view_divide_value"] = aDivideSizes.join (","); +} + +// ======================================================================= +// function : RestoreState +// purpose : +// ======================================================================= +bool ViewControl_PropertyView::RestoreState (ViewControl_PropertyView* theView, + const QString& theKey, + const QString& theValue, + const QString& thePrefix) +{ + if (theKey == thePrefix + "property_view_xstep_value") + { + QList aXStepValues; + QStringList aValues = theValue.split (",", QString::SkipEmptyParts); + for (int aValueId = 0; aValueId < aValues.size(); aValueId++) + aXStepValues.append (aValues.at (aValueId).toDouble()); + theView->SetXSteps (aXStepValues); + } + else if (theKey == thePrefix + "property_view_divide_value") + { + QList aDivideValues; + QStringList aValues = theValue.split (",", QString::SkipEmptyParts); + for (int aValueId = 0; aValueId < aValues.size(); aValueId++) + aDivideValues.append (aValues.at (aValueId).toInt()); + theView->SetDivideValues (aDivideValues); + } + else + return false; + return true; +} diff --git a/tools/ViewControl/ViewControl_PropertyView.hxx b/tools/ViewControl/ViewControl_PropertyView.hxx new file mode 100644 index 0000000000..2bfdc7b6f9 --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertyView.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 TreeModel_PropertyView_H +#define TreeModel_PropertyView_H + +#include +#include + +#include + +#include +#include +#include +#include + +class QAbstractTableModel; +class QStackedWidget; +class QWidget; +class QVBoxLayout; + +class ViewControl_TableModelValues; + +//! \class ViewControl_PropertyView +//! \brief View widget where several tables are visualized in vertical layout. +class ViewControl_PropertyView : public QObject +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT ViewControl_PropertyView (QWidget* theParent); + + //! Destructor + virtual ~ViewControl_PropertyView() Standard_OVERRIDE {} + + //! Fills the view content with values. Number of visible tables is size of container, + //! Each element of container is values of the corresponded table + //! \param theTableValues values + Standard_EXPORT void Init (const QList& theTableValues); + + //! Fills the view content with the parameter custom widget. + //! \param theWidget control + Standard_EXPORT void Init (QWidget* theWidget); + + //! Clears layout of the view and tables models. + Standard_EXPORT void Clear(); + + //! \return the text edit control + QWidget* GetControl() const { return myMainWidget; } + + //! Returns container of active tables + //! \param theTables [out] modified container + Standard_EXPORT void GetActiveTables (QList& theTables); + + //! Clears selection in active tables + Standard_EXPORT void ClearActiveTablesSelection(); + + //! Sets X steps values for table properties + //! \param container of values + void SetXSteps (const QList& theValues) { myXStepValues = theValues; } + + //! Sets divide values for table properties + //! \param container of values + void SetDivideValues (const QList& theValues) { myDivideValues = theValues; } + + //! Save state of three view in a container in form: key, value. It saves: + //! - XStep of property table + //! - divide values of property table + //! \param theTreeView a view instance + //! \param theItems [out] properties + //! \param thePrefix peference item prefix + Standard_EXPORT static void SaveState (ViewControl_PropertyView* theView, QMap& theItems, + const QString& thePrefix = QString()); + //! Restore state of three view by a container + //! \param theTreeView a view instance + //! \param theKey property key + //! \param theValue property value + //! \param thePrefix peference item prefix + //! \return boolean value whether the property is applyed to the tree view + Standard_EXPORT static bool RestoreState (ViewControl_PropertyView* theView, const QString& theKey, const QString& theValue, + const QString& thePrefix = QString()); + +signals: + void propertyViewSelectionChanged(); + +protected slots: + //! Emits signal about selection is changed + //! \param theSelected container of selected table cells + //! \param theDeselected container of selected table cells + void onTableSelectionChanged (const QItemSelection& theSelected, const QItemSelection& theDeselected); + +protected: + //! Returns table instance or create if it was not created ealier + //! \param theTableId an index in internal container of tables + //! \param isToCreate if true, the table is created if not exists + ViewControl_Table* findTable (const int theTableId, const bool isToCreate = true); + +private: + bool myOwnSelectionChangeBlocked; //! blocking emit of selection changed signal + + QWidget* myMainWidget; //! parent of all controls + + QStackedWidget* myAttributesStack; //!< container of already created panes + QWidget* myEmptyWidget; //!< an empty widget when nothing is selected in tree view + + QWidget* myTableWidget; //!< widget of tables in vertical layout + QVBoxLayout* myTableWidgetLayout; //! main view layout where tables or custom widgets are presented + QList myTables; //!< table view, shown only first tables filled in Init method + QWidget* myCustomWidget; //!< custom view widget + + QList myXStepValues; //! predefined values for XStep in ViewControl_TableProperty + QList myDivideValues; //! predefined values for divide value in ViewControl_TableProperty +}; +#endif diff --git a/tools/ViewControl/ViewControl_Table.cxx b/tools/ViewControl/ViewControl_Table.cxx new file mode 100644 index 0000000000..29bd9cf04b --- /dev/null +++ b/tools/ViewControl/ViewControl_Table.cxx @@ -0,0 +1,137 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= + +ViewControl_Table::ViewControl_Table (QWidget* theParent) +: QObject (theParent), myIsUseProperty (false) +{ + myMainWidget = new QWidget (theParent); + QGridLayout* aLayout = new QGridLayout (myMainWidget); + aLayout->setContentsMargins (0, 0, 0, 0); + + myProperty = new ViewControl_TableProperty(myMainWidget, this); + aLayout->addWidget (myProperty->GetControl()); + + myTableView = new QTableView (myMainWidget); + myTableView->setVerticalScrollMode (QAbstractItemView::ScrollPerPixel); + + QHeaderView* aVHeader = myTableView->verticalHeader(); + int aDefCellSize = aVHeader->minimumSectionSize() + TreeModel_Tools::HeaderSectionMargin(); + aVHeader->setDefaultSectionSize (aDefCellSize); + + aLayout->addWidget (myTableView); + aLayout->addWidget (myProperty->GetInformationControl()); +} + +// ======================================================================= +// function : SetModel +// purpose : +// ======================================================================= + +void ViewControl_Table::SetModel (QAbstractTableModel* theModel) +{ + myTableView->setModel (theModel); + + myTableView->setSelectionMode(QAbstractItemView::ExtendedSelection); + QItemSelectionModel* aSelectionModel = new QItemSelectionModel(theModel); + myTableView->setSelectionModel (aSelectionModel); + connect(aSelectionModel, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), + this, SLOT(onTableSelectionChanged(const QItemSelection&, const QItemSelection&))); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= + +void ViewControl_Table::Init (ViewControl_TableModelValues* theModelValues) +{ + myTableView->selectionModel()->clearSelection(); + + ViewControl_TableModel* aModel = dynamic_cast (myTableView->model()); + aModel->SetModelValues (theModelValues); + + myProperty->SetActive (theModelValues->UseTableProperties()); + myProperty->Init(); + + int aSectionSize; + myTableView->horizontalHeader()->setVisible (theModelValues->IsHeaderVisible (Qt::Horizontal)); + if (theModelValues->GetDefaultSectionSize (Qt::Horizontal, aSectionSize) ) + myTableView->horizontalHeader()->setDefaultSectionSize (aSectionSize); + + myTableView->verticalHeader()->setVisible (theModelValues->IsHeaderVisible (Qt::Vertical)); + if (theModelValues->GetDefaultSectionSize (Qt::Vertical, aSectionSize) ) + { + myTableView->verticalHeader()->setDefaultSectionSize (aSectionSize); + } + else + myTableView->verticalHeader()->setDefaultSectionSize (myTableView->verticalHeader()->minimumSectionSize() + + TreeModel_Tools::HeaderSectionMargin()); + aModel->EmitLayoutChanged(); +} + +// ======================================================================= +// function : GetSelectedIndices +// purpose : +// ======================================================================= + +void ViewControl_Table::GetSelectedIndices (QMap>& theSelectedIndices) +{ + QModelIndexList aSelected = myTableView->selectionModel()->selectedIndexes(); + ViewControl_TableModel* aModel = dynamic_cast (myTableView->model()); + + int aRow, aColumn; + for (QModelIndexList::const_iterator anIt = aSelected.begin(); anIt != aSelected.end(); anIt++) + { + aModel->GetSourcePosition (*anIt, aRow, aColumn); + + if (!theSelectedIndices.contains (aRow)) + theSelectedIndices.insert (aRow, QList()); + theSelectedIndices[aRow].append (aColumn); + } +} + +// ======================================================================= +// function : onTableSelectionChanged +// purpose : +// ======================================================================= + +void ViewControl_Table::onTableSelectionChanged(const QItemSelection&, const QItemSelection&) +{ + QModelIndexList aSelected = myTableView->selectionModel()->selectedIndexes(); + + myProperty->UpdateOnTableSelectionChanged(); +} diff --git a/tools/ViewControl/ViewControl_Table.hxx b/tools/ViewControl/ViewControl_Table.hxx new file mode 100644 index 0000000000..7d11c9123c --- /dev/null +++ b/tools/ViewControl/ViewControl_Table.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 ViewControl_Table_H +#define ViewControl_Table_H + +#include +#include + +#include + +#include +#include +#include +#include +#include + +class ViewControl_TableModelValues; + +class QAbstractTableModel; +class QContextMenuEvent; +class QWidget; + +//! \class ViewControl_Table +//! \brief View to display table values with possibility to change table columns +//! if the table has 1D dimension and Horizontal orientation +class ViewControl_Table : public QObject +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT ViewControl_Table (QWidget* theParent); + + //! Destructor + virtual ~ViewControl_Table() Standard_OVERRIDE {} + + //! Set model into table view, init selection model by the given model, connect to selection change + //! \param theModel table values model + void SetModel (QAbstractTableModel* theModel); + + //! Fills table view and table size control by the model + //! \param theModel values model + Standard_EXPORT void Init (ViewControl_TableModelValues* theModelValues); + + //! Sets the table active and show the table + //! \param theState boolean value + void SetActive (const bool theState) { myIsActive = theState; GetTableView()->setVisible (theState); } + + //!< true if the table is used in property view and visible + bool IsActive() const { return myIsActive; } + + //! \return the text edit control + QWidget* GetControl() const { return myMainWidget; } + + //! \return the table view + QTableView* GetTableView() const { return myTableView; } + + //! Returns instance of table property control + //! \return property + ViewControl_TableProperty* GetProperty() const { return myProperty; } + + //! Retuns model indices of the selected cells in table view + //! \param theSelectedIndices [out] a container of indices: row to list of columns + Standard_EXPORT void GetSelectedIndices (QMap>& aSelectedIndices); + +protected slots: + + //! Updates controls by selection change in table view + //! \param theSelected container of selected table cells + //! \param theDeselected container of selected table cells + void onTableSelectionChanged(const QItemSelection& theSelected, const QItemSelection& theDeselected); + +private: + bool myIsActive; //!< true if the table is used in property view and visible + + QWidget* myMainWidget; //!< parent of all controls + bool myIsUseProperty; //!< boolean value whether the property control should be shown/hidden + QTableView* myTableView; //!< table view + + ViewControl_TableProperty* myProperty; //!< modifier of the table visual properties +}; +#endif diff --git a/tools/ViewControl/ViewControl_TableModel.cxx b/tools/ViewControl/ViewControl_TableModel.cxx new file mode 100644 index 0000000000..3e6078247c --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModel.cxx @@ -0,0 +1,83 @@ +// 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 : SetModelValues +// purpose : +// ======================================================================= +void ViewControl_TableModel::SetModelValues (ViewControl_TableModelValues* theModelValues) +{ + if (myModelValues) + delete myModelValues; + + myModelValues = theModelValues; + SetFilter(0); +} + +// ======================================================================= +// function : columnCount +// purpose : +// ======================================================================= +int ViewControl_TableModel::columnCount(const QModelIndex& theParent) const +{ + if (!myModelValues) + return 0; + + int aColumnCount = myModelValues->ColumnCount (theParent); + return isFilterActive() ? myFilter->ColumnCount (aColumnCount) : aColumnCount; +} + +// ======================================================================= +// function : rowCount +// purpose : +// ======================================================================= +int ViewControl_TableModel::rowCount(const QModelIndex& theParent ) const +{ + if (!myModelValues) + return 0; + + return isFilterActive() ? myFilter->RowCount (myModelValues->ColumnCount (theParent)) + : myModelValues->RowCount (theParent); +} + +// ======================================================================= +// function : data +// purpose : +// ======================================================================= +QVariant ViewControl_TableModel::data (const QModelIndex& theIndex, int theRole) const +{ + if (!myModelValues) + return QVariant(); + + int aRow = theIndex.row(), aColumn = theIndex.column(); + if (isFilterActive()) + myFilter->GetSourcePosition (theIndex, aRow, aColumn); + + return myModelValues->Data (aRow, aColumn, theRole); +} + +// ======================================================================= +// function : GetSourcePosition +// purpose : +// ======================================================================= +void ViewControl_TableModel::GetSourcePosition (const QModelIndex& theIndex, int& theRow, int& theColumn) +{ + if (isFilterActive()) + myFilter->GetSourcePosition (theIndex, theRow, theColumn); + else + myModelValues->GetSourcePosition (theIndex.row(), theIndex.column(), theRow, theColumn); +} diff --git a/tools/ViewControl/ViewControl_TableModel.hxx b/tools/ViewControl/ViewControl_TableModel.hxx new file mode 100644 index 0000000000..0628e22e67 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModel.hxx @@ -0,0 +1,111 @@ +// 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 ViewControl_TableModel_H +#define ViewControl_TableModel_H + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +//! \class ViewControl_TableModel +//! \brief This is an extension of table model to visualize a container of values +//! It is possible to: +//! - set orientation to interpretate the values. +//! - set table view header values. +//! Items of the view are enabled and selectable. +class ViewControl_TableModel : public QAbstractTableModel +{ +public: + + //! Constructor + ViewControl_TableModel (QObject* theParent = 0) : myModelValues (0), myFilter (0) { (void)theParent; } + + //! Destructor + virtual ~ViewControl_TableModel() {} + + //! Sets interface to table values + //! \theModelValues instance of values + Standard_EXPORT void SetModelValues (ViewControl_TableModelValues* theModelValues); + + //! Returns instance of interface for access totable values + //! \return interface or NULL + ViewControl_TableModelValues* GetModelValues() const { return myModelValues; } + + //! Sets table values filter to rearrange values presentation + //! \param filter instance + void SetFilter (ViewControl_TableModelFilter* theFilter) { myFilter = theFilter; } + + //! Emits the layoutChanged signal from outside of this class + void EmitLayoutChanged() { emit layoutChanged(); } + + //! Returns number of columns, depending on orientation: myColumnCount or size of values container + //! \param theParent an index of the parent item + //! \return an integer value + Standard_EXPORT virtual int columnCount(const QModelIndex& theParent = QModelIndex()) const Standard_OVERRIDE; + + //! 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 + Standard_EXPORT virtual int rowCount(const QModelIndex& theParent = QModelIndex()) const Standard_OVERRIDE; + + //! 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 QModelIndex& theIndex, int theRole = Qt::DisplayRole) const Standard_OVERRIDE; + + //! Returns content of the model index for the given role, it is obtainer from internal container of header values + //! It returns value only for DisplayRole. + //! \param theSection an index of value in the container + //! \param theIndex a model index + //! \param theRole a view role + //! \return value intepreted depending on the given role + virtual QVariant headerData (int theSection, Qt::Orientation theOrientation, int theRole = Qt::DisplayRole) const Standard_OVERRIDE + { return myModelValues ? myModelValues->HeaderData (theSection, theOrientation, theRole) : QVariant(); } + + //! Returns flags for the item: ItemIsEnabled | Qt::ItemIsSelectable + //! \param theIndex a model index + //! \return flags + Qt::ItemFlags flags (const QModelIndex& theIndex) const + { return myModelValues ? myModelValues->Flags (theIndex) : Qt::NoItemFlags; } + + //! Returns source row and column values peforming conversion back from filter + //! \param theIndex a model index + //! \param theRow a model row + //! \param theColumn a model column + Standard_EXPORT void GetSourcePosition (const QModelIndex& theIndex, int& theRow, int& theColumn); + +protected: + //! Returns true if the filter is not NULL and active + //! \return true if active + Standard_Boolean isFilterActive() const { return myFilter && myFilter->IsActive(); } + +private: + ViewControl_TableModelValues* myModelValues; //! interface to table values + ViewControl_TableModelFilter* myFilter; //! filter of values +}; + +#endif diff --git a/tools/ViewControl/ViewControl_TableModelFilter.cxx b/tools/ViewControl/ViewControl_TableModelFilter.cxx new file mode 100644 index 0000000000..33891475c0 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModelFilter.cxx @@ -0,0 +1,65 @@ +// 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 : ColumnCount +// purpose : +// ======================================================================= + +int ViewControl_TableModelFilter::ColumnCount (const int theSourceColumnCount) const +{ + return myColumnCount <= 0 ? theSourceColumnCount : myColumnCount; +} + +// ======================================================================= +// function : RowCount +// purpose : +// ======================================================================= + +int ViewControl_TableModelFilter::RowCount (const int theSourceColumnCount) const +{ + if (myColumnCount <= 0) + return 1; + + int aRows = (int) (theSourceColumnCount / myColumnCount); + if (myColumnCount > 0 && aRows * myColumnCount < theSourceColumnCount) + aRows++; /// row with left values, not fully filled + + return aRows; +} + +// ======================================================================= +// function : GetSourcePosition +// purpose : +// ======================================================================= + +void ViewControl_TableModelFilter::GetSourcePosition (const QModelIndex& theIndex, int& theRow, int& theColumn) const +{ + GetSourcePosition (theIndex.row(), theIndex.column(), theRow, theColumn); +} + +// ======================================================================= +// function : GetSourcePosition +// purpose : +// ======================================================================= + +void ViewControl_TableModelFilter::GetSourcePosition (const int theSourceRow, const int theSourceColumn, int& theRow, + int& theColumn) const +{ + theRow = 0; + theColumn = myColumnCount * theSourceRow + theSourceColumn; +} diff --git a/tools/ViewControl/ViewControl_TableModelFilter.hxx b/tools/ViewControl/ViewControl_TableModelFilter.hxx new file mode 100644 index 0000000000..3e3adc044c --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModelFilter.hxx @@ -0,0 +1,76 @@ +// 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 ViewControl_TableModelFilter_H +#define ViewControl_TableModelFilter_H + +#include + +#include + +//! \class ViewControl_TableModelFilter +//! \brief It provides separation of 1D container of values in 2D presentation depending on number of column value +class ViewControl_TableModelFilter +{ +public: + + //! Constructor + Standard_EXPORT ViewControl_TableModelFilter(const Standard_Integer theColumnCount = -1) + : myIsActive (Standard_True), myColumnCount (theColumnCount) {} + + //! Destructor + virtual ~ViewControl_TableModelFilter() {} + + //! Activate/Deactivate filter + //! \param theActive state is the filter to be active or not + virtual void SetActive (const Standard_Boolean theActive) { myIsActive = theActive; } + + //! Returns boolean state whether the filter is activated + //! \return true if active + virtual Standard_Boolean IsActive() const { return myIsActive; } + + //! Sets number of columns + //! \param theColumnCount a column count + void SetColumnCount (const int theColumnCount) { myColumnCount = theColumnCount; } + + //! Returns number of columns: parameter value + //! \param theSourceColumnCount number of columns in the source table + //! \return an integer value + Standard_EXPORT int ColumnCount (const int theSourceColumnCount) const; + + //! Returns number of rows: whole number of columns is divided to the current column value + //! \param theSourceColumnCount number of columns in the source table + //! \return an integer value + Standard_EXPORT int RowCount (const int theSourceColumnCount) const; + + //! Returns source row/column indices for the filtered model index + //! \param theIndex a model index + //! \param theRow [out] row number value + //! \param theColumn [out] column value + Standard_EXPORT void GetSourcePosition (const QModelIndex& theIndex, int& theRow, int& theColumn) const; + + //! Returns source row/column indices for the filtered model index + //! \param theSourceRow model row index + //! \param theSourceColumn model column index + //! \param theRow [out] row number value + //! \param theColumn [out] column value + Standard_EXPORT void GetSourcePosition (const int theSourceRow, const int theSourceColumn, int& theRow, int& theColumn) const; + +private: + Standard_Boolean myIsActive; //!< active state of the filter + Standard_Integer myColumnCount; //!< number of table columns +}; + +#endif diff --git a/tools/ViewControl/ViewControl_TableModelValues.cxx b/tools/ViewControl/ViewControl_TableModelValues.cxx new file mode 100644 index 0000000000..8ac5e59e30 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModelValues.cxx @@ -0,0 +1,91 @@ +// 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 : ColumnCount +// purpose : +// ======================================================================= + +int ViewControl_TableModelValues::ColumnCount (const QModelIndex&) const +{ + Qt::Orientation anAdditionalOrientation = myOrientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical; + if (myHeaderValues[anAdditionalOrientation].size() > 0) + return myHeaderValues[anAdditionalOrientation].size(); + + return myValues.size(); +} + +// ======================================================================= +// function : Data +// purpose : +// ======================================================================= + +QVariant ViewControl_TableModelValues::Data (const int theRow, const int theColumn, int theRole) const +{ + if (theRole == Qt::DisplayRole) + return myValues.at ((int)getPosition (theRow, theColumn)); + + if (theRole == Qt::TextAlignmentRole) // for multi-lines text, align it to the top + return Qt::AlignTop; + + if ((theRole == Qt::FontRole || theRole == Qt::ForegroundRole) && isItalicHeader (theRow, theColumn)) + { + if (theRole == Qt::FontRole) + { + QFont aFont = qApp->font(); + aFont.setItalic (true); + return aFont; + } + else + QColor (Qt::darkGray).darker (150); + } + return QVariant(); +} + +// ======================================================================= +// function : HeaderData +// purpose : +// ======================================================================= + +QVariant ViewControl_TableModelValues::HeaderData (int theSection, Qt::Orientation theOrientation, int theRole) const +{ + if (theRole == Qt::DisplayRole) + return myHeaderValues.contains (theOrientation) ? myHeaderValues[theOrientation][theSection].GetName() + : QString::number (theSection + 1); + else if (theRole == Qt::ForegroundRole) + return QColor (Qt::darkGray); + + return QVariant(); +} + +// ======================================================================= +// function : isItalicHeader +// purpose : +// ======================================================================= + +bool ViewControl_TableModelValues::isItalicHeader (const int theRow, const int theColumn) const +{ + Qt::Orientation anOrientation = myOrientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical; + int aCell = anOrientation == Qt::Horizontal ? theColumn : theRow; + + return GetHeaderItem (anOrientation, aCell).IsItalic(); +} \ No newline at end of file diff --git a/tools/ViewControl/ViewControl_TableModelValues.hxx b/tools/ViewControl/ViewControl_TableModelValues.hxx new file mode 100644 index 0000000000..0c7974eaa2 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableModelValues.hxx @@ -0,0 +1,200 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ViewControl_TableModelValues_H +#define ViewControl_TableModelValues_H + +#include + +#include + +#include +#include +#include +#include +#include +#include + +//! \class ViewControl_TableModelValues +//! \brief This is an interace for ViewControl_TableModel to give real values of the model +//! It should be filled or redefined. +class ViewControl_TableModelValues +{ +public: + + //! Constructor + Standard_EXPORT ViewControl_TableModelValues (const Qt::Orientation& theOrientation = Qt::Vertical) + : myUseTableProperties (false), myUseTableSeparateSize (true), myUseTablePropertiesXStep (false), + myUseTablePropertiesXStepValue (-1) + { SetOrientation (theOrientation); } + + //! Destructor + virtual ~ViewControl_TableModelValues() {} + + //! Sets direction of the values applying, whether it should be placed by rows or by columns + //! \param theOrientation if horizontal, the values are applyed by rows, otherwise by columns + void SetOrientation (const Qt::Orientation& theOrientation) { myOrientation = theOrientation; } + + //! Fills the model values. + //! \param theValues a container of table model values + void SetValues (const QVector& theValues) { myValues = theValues; } + + //! Fills the model header values for orientation. + //! \param theValues a container of header text values + //! \param theOrientation an orientation of header + void SetHeaderValues (const QList& theValues, const Qt::Orientation theOrientation) + { myHeaderValues.insert (theOrientation, theValues); } + + //! Returns whether the column is hidden by default + //! \param theColumnId a column index + //! \return header section values container + TreeModel_HeaderSection GetHeaderItem (const Qt::Orientation theOrientation, const int theColumnId) const + { return myHeaderValues.contains(theOrientation) ? myHeaderValues[theOrientation][theColumnId] : TreeModel_HeaderSection(); } + + //! Stores information about table view header visibility + //! \param theOrientation an orientation of header + //! \param theVisibility if true, header is visible + void SetHeaderVisible (const Qt::Orientation theOrientation, const bool theVisibility) + { myVisibleHeader.insert (theOrientation, theVisibility); } + + //! Stores information about table view header visibility + //! \param theOrientation an orientation of header + //! \param theVisibility if true, header is visible + bool IsHeaderVisible (const Qt::Orientation theOrientation) const + { return myVisibleHeader.contains(theOrientation) ? myVisibleHeader[theOrientation] : true; } + + //! Set default section size if defined + //! \param theOrientation an orientation of header + //! \param theVisibility if true, header is visible + void SetDefaultSectionSize (const Qt::Orientation theOrientation, const int& theSectionSize) + { myDefaultSectionSize.insert(theOrientation, theSectionSize); } + + //! Get default section size if defined + //! \param theOrientation an orientation of header + //! \param theVisibility if true, header is visible + bool GetDefaultSectionSize (const Qt::Orientation theOrientation, int& theSectionSize) + { + theSectionSize = myDefaultSectionSize.contains (theOrientation) ? myDefaultSectionSize[theOrientation] : -1; + return myDefaultSectionSize.contains (theOrientation); + } + + //! Stores whether the properties control of the table visible or not + //! \param theUseProperties boolean state + void SetUseTableProperties (const bool theUseProperties) { myUseTableProperties = theUseProperties; } + + //! Returns true if the properties control of the table visible or not + //! \return boolean value + bool UseTableProperties() const { return myUseTableProperties; } + + //! Stores whether the properties control of the table visible or not + //! \param theUseProperties boolean state + void SetUseTableSeparateSize (const bool theUseSize) + { myUseTableSeparateSize = theUseSize; } + + //! Returns true if the properties control of the table visible or not + //! \return boolean value + bool UseTableSeparateSize() const + { return myUseTableSeparateSize; } + + //! Stores whether the properties control of the table visible or not + //! \param theUseProperties boolean state + void SetUseTablePropertiesXStep (const bool theUseStep, const double theStep) + { myUseTablePropertiesXStep = theUseStep; myUseTablePropertiesXStepValue = theStep; } + + //! Returns true if the properties control of the table visible or not + //! \return boolean value + double UseTablePropertiesXStep(bool& theUseStep) const + { theUseStep = myUseTablePropertiesXStep; return myUseTablePropertiesXStepValue; } + + //! 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 + { return ColumnCount (theParent) > 0 ? GetValuesCount() / ColumnCount (theParent) : 0; } + + //! 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 content of the model index for the given role, it is obtainer from internal container of header values + //! It returns value only for DisplayRole. + //! \param theSection an index of value in the container + //! \param theIndex a model index + //! \param theRole a view role + //! \return value intepreted depending on the given role + Standard_EXPORT virtual QVariant HeaderData (int theSection, Qt::Orientation theOrientation, int theRole = Qt::DisplayRole) const; + + //! Returns flags for the item: ItemIsEnabled | Qt::ItemIsSelectable + //! \param theIndex a model index + //! \return flags + virtual Qt::ItemFlags Flags (const QModelIndex& theIndex) const + { return theIndex.isValid() ? Qt::ItemIsEnabled | Qt::ItemIsSelectable : Qt::NoItemFlags; } + + //! Returns minimum and maximum values of the table content + //! \param theMinValue minimum + //! \param theMaxValue maximum + virtual void GetRangeValues (QString& theMinValue, QString& theMaxValue, const QModelIndexList& theSelected) const + { (void)theMinValue; (void)theMaxValue; (void)theSelected; } + + //! Returns additional info + virtual QString AdditionalInformation() const { return QString(); } + + //! 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 GetValuesCount () const { return myValues.size(); } + + //! Returns source row/column indices for the filtered model index for the given role + //! \param theSourceRow model row index + //! \param theSourceColumn model column index + //! \param theRow [out] row number value + //! \param theColumn [out] column value + Standard_EXPORT virtual void GetSourcePosition (const int theSourceRow, const int theSourceColumn, int& theRow, int& theColumn) const + { theRow = theSourceRow; theColumn = theSourceColumn; } + +protected: + //! Finds position in internal vector of values using the table column/row count + //! \param theRow a row of a table cell + //! \param theColumn a column of a table cell + size_t getPosition (const int theRow, const int theColumn) const { return ColumnCount() * theRow + theColumn; } + + //! Returns true if the header item is italic of the parameter index + //! \param theRow a model index row + //! \param theColumn a model index column + //! \param boolean value + bool isItalicHeader (const int theRow, const int theColumn) const; + +protected: + + Qt::Orientation myOrientation; //!< orientation how the values should fill the current table view + QMap > myHeaderValues; //!< table header values + QMap myVisibleHeader; //! table header visibility + QMap myDefaultSectionSize; //! table section default size + QVector myValues; //! cached container of table values + bool myUseTableProperties; //! state whether the table property control is visible + bool myUseTableSeparateSize; //! state whether table custom column size is possible + bool myUseTablePropertiesXStep; //! true if XStep value is used + double myUseTablePropertiesXStepValue; //! value to define OX step for 1D table, Z = 0 +}; + +#endif diff --git a/tools/ViewControl/ViewControl_TableProperty.cxx b/tools/ViewControl/ViewControl_TableProperty.cxx new file mode 100644 index 0000000000..e3c3a08c59 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableProperty.cxx @@ -0,0 +1,224 @@ +// 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 + +const int DEFAULT_COLUMN_WIDTH = 60; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= + +ViewControl_TableProperty::ViewControl_TableProperty (QWidget* theParent, ViewControl_Table* theTable) +: QObject (theParent), myTable (theTable), myIsActive (false) +{ + myFilter = new ViewControl_TableModelFilter(); + + myMainWidget = new QWidget (theParent); + QGridLayout* aMainLayout = new QGridLayout (myMainWidget); + + QWidget* aProperties = new QWidget (myMainWidget); + aMainLayout->addWidget (aProperties); + QHBoxLayout* aPropertiesLayout = new QHBoxLayout (aProperties); + aPropertiesLayout->setContentsMargins (0, 0, 0, 0); + + mySize = new QLabel ("", myMainWidget); + myDivideSize = new QLabel("Divide:", myMainWidget); + mySeparateSize = new QSpinBox (myMainWidget); + mySeparateSize->setRange (0, 100000); + myVisualizedSize = new QLabel ("", myMainWidget); + + aPropertiesLayout->addWidget (mySize); + aPropertiesLayout->addWidget (myDivideSize); + aPropertiesLayout->addWidget (mySeparateSize); + aPropertiesLayout->addWidget (myVisualizedSize); + + myXStepLabel = new QLabel ("XStep:"); + myXStep = new QDoubleSpinBox (myMainWidget); + myXStep->setRange(1.e-12, 1.e+7); + myXStep->setDecimals (8); + myXStep->setValue(1.); + + setXStepActive (false); + + connect (myXStep, SIGNAL(editingFinished()), this, SIGNAL (propertyChanged())); + + aPropertiesLayout->addWidget (myXStepLabel); + aPropertiesLayout->addWidget (myXStep); + + myInformationWidget = new QWidget (theParent); + QGridLayout* anInfoLayout = new QGridLayout (myInformationWidget); + + myModelInformation = new QPlainTextEdit (myInformationWidget); + myModelInformation->setVisible (false); + anInfoLayout->addWidget (myModelInformation, 2, 0, 1, 4); + + myMinValue = new QPushButton ("Min", myInformationWidget); + myMaxValue = new QPushButton ("Max", myInformationWidget); + myMinSelectedValue = new QPushButton ("Min of selected", myInformationWidget); + myMaxSelectedValue = new QPushButton ("Max of selected", myInformationWidget); + + anInfoLayout->addWidget (myMinValue, 3, 0); + anInfoLayout->addWidget (myMinSelectedValue, 3, 1); + anInfoLayout->addWidget (myMaxValue, 4, 0); + anInfoLayout->addWidget (myMaxSelectedValue, 4, 1); + + connect (mySeparateSize, SIGNAL (valueChanged (int)), + this, SLOT (onSeparateSizeChanged (int))); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= + +void ViewControl_TableProperty::Init() +{ + ViewControl_TableModel* aViewModel = dynamic_cast(myTable->GetTableView()->model()); + ViewControl_TableModelValues* aModelValues = aViewModel->GetModelValues(); + + bool aUseXStep; + double aXStep = aModelValues->UseTablePropertiesXStep (aUseXStep); + setXStepActive (aUseXStep, aXStep); + + QString aMinValue = QString::number (DBL_MIN), aMaxValue = QString::number (DBL_MAX); + aModelValues->GetRangeValues (aMinValue, aMaxValue, QModelIndexList()); + QString anInfo = aModelValues->AdditionalInformation(); + + bool aUseSeparateSize = aModelValues->UseTableSeparateSize(); + mySize->setVisible (aUseSeparateSize); + myDivideSize->setVisible (aUseSeparateSize); + mySeparateSize->setVisible (aUseSeparateSize); + myVisualizedSize->setVisible (aUseSeparateSize); + myFilter->SetActive (aUseSeparateSize); + if (aUseSeparateSize && mySeparateSize->value() != 0) + myFilter->SetColumnCount(mySeparateSize->value()); + + mySize->setText (QString("[ %1, %2 ]").arg (aViewModel->rowCount()).arg (aViewModel->columnCount())); + + myVisualizedSize->setText (mySize->text()); + myVisualizedSize->setToolTip (QString ("sqrt: (%1, %2)").arg (sqrt (aViewModel->rowCount())).arg (sqrt (aViewModel->columnCount()))); + myModelInformation->setVisible(!anInfo.isEmpty()); + if (!anInfo.isEmpty()) + myModelInformation->setPlainText (anInfo); + + myMinValue->setText (QString ("Min: ") + aMinValue); + myMaxValue->setText (QString ("Max: ") + aMaxValue); + myMinSelectedValue->setText (QString("Min of selected: ") + QString::number(0)); + myMaxSelectedValue->setText (QString("Max of selected: ") + QString::number(0)); +} + +// ======================================================================= +// function : SetActive +// purpose : +// ======================================================================= + +void ViewControl_TableProperty::SetActive (const bool theActive) +{ + GetControl()->setVisible (theActive); + GetInformationControl()->setVisible (theActive); + + ViewControl_TableModel* aModel = dynamic_cast (myTable->GetTableView()->model()); + aModel->SetFilter (theActive ? GetFilter() : 0); +} + +// ======================================================================= +// function : onSeparateSizeChanged +// purpose : +// ======================================================================= + +void ViewControl_TableProperty::onSeparateSizeChanged (int theValue) +{ + myFilter->SetColumnCount(theValue); + + myTable->GetTableView()->selectionModel()->clearSelection(); + + ViewControl_TableModel* aViewModel = dynamic_cast(myTable->GetTableView()->model()); + aViewModel->EmitLayoutChanged(); + + myVisualizedSize->setText (QString ("[ %1, %2 ]").arg (aViewModel->rowCount()).arg (aViewModel->columnCount())); +} + +// ======================================================================= +// function : onToleranceSizeChanged +// purpose : +// ======================================================================= + +void ViewControl_TableProperty::onToleranceSizeChanged (int theValue) +{ + (void)theValue; +} + +// ======================================================================= +// function : onSeparateSizeChanged +// purpose : +// ======================================================================= + +void ViewControl_TableProperty::UpdateOnTableSelectionChanged() +{ + QModelIndexList aSelected = myTable->GetTableView()->selectionModel()->selectedIndexes(); + if (aSelected.isEmpty()) + { + myMinSelectedValue->setText(QString("Min of selected:") + QString::number(0)); + myMaxSelectedValue->setText(QString("Max of selected:") + QString::number(0)); + return; + } + + ViewControl_TableModel* aViewModel = dynamic_cast(myTable->GetTableView()->model()); + ViewControl_TableModelValues* aModelValues = aViewModel->GetModelValues(); + + QString aMinValue = QString::number (DBL_MIN), aMaxValue = QString::number (DBL_MAX); + aModelValues->GetRangeValues (aMinValue, aMaxValue, aSelected); + + myMinSelectedValue->setText (QString ("Min of selected:") + aMinValue); + myMaxSelectedValue->setText (QString ("Max of selected:") + aMaxValue); +} + +// ======================================================================= +// function : createAction +// purpose : +// ======================================================================= +void ViewControl_TableProperty::setXStepActive (const bool theState, const double theValue) +{ + myXStepActive = theState; + + myXStepLabel->setVisible (myXStepActive); + myXStep->setVisible (myXStepActive); + + if (theValue > 0) + myXStep->setValue (theValue); +} diff --git a/tools/ViewControl/ViewControl_TableProperty.hxx b/tools/ViewControl/ViewControl_TableProperty.hxx new file mode 100644 index 0000000000..fbfa98c4b4 --- /dev/null +++ b/tools/ViewControl/ViewControl_TableProperty.hxx @@ -0,0 +1,141 @@ +// 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 ViewControl_TableProperty_H +#define ViewControl_TableProperty_H + +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // conditional expression is constant +#endif + +#include +#include +#include + +class ViewControl_Table; +class ViewControl_TableModelFilter; + +class QContextMenuEvent; +class QLabel; +class QItemSelection; +class QPlainTextEdit; +class QPushButton; +class QSpinBox; +class QWidget; + +//! \class ViewControl_TableProperty +//! \brief View to display table values with possibility to change table columns +//! if the table has 1D dimension and Horizontal orientation +class ViewControl_TableProperty : public QObject +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT ViewControl_TableProperty (QWidget* theParent, ViewControl_Table* theTable); + + //! Destructor + virtual ~ViewControl_TableProperty() Standard_OVERRIDE {} + + //! Fills table view and table size control by the model + Standard_EXPORT void Init(); + + //! Sets whether the properties pane is visible or not + //! \param theUseProperty boolean state + Standard_EXPORT void SetActive (const bool theActive); + + //! Returns main control + //! \return widget + QWidget* GetControl() const { return myMainWidget; } + + //! Returns information control + //! \return widget + QWidget* GetInformationControl() { return myInformationWidget; } + + //! Returns table values filter to apply separation size + //! \return filter instance + ViewControl_TableModelFilter* GetFilter() { return myFilter; } + + //! Returns X step or -1 if it is not used + //! \return double value + double GetXStep() const { return myXStepActive ? myXStep->value() : -1;}; + + //! Sets X step + //! \param theValue value + void SetXStep(const double theValue) const { myXStep->setValue (theValue); }; + + //! Returns divide valid + //! \return control value + int GetDivideSize() const { return mySeparateSize->value(); } + + //! Sets separate size value + //! \param theValue new value + void SetDivideSize (const int theValue) { mySeparateSize->setValue (theValue); } + +signals: + //! Signals about header cell is clicked + //! \param theEvent context menu event + void headerContextMenuRequsted (QContextMenuEvent* theEvent); + + //! Signals about the following properties are changed: XStep. + void propertyChanged(); + +protected slots: + //! Reacts to the spin box value change, it divides table model values to has given number of columns + //! \param theValue a new value of spin box + void onSeparateSizeChanged (int theValue); + + //! Reacts to the tolerance value change, it sets it into table model + //! \param theValue a new value of spin box + void onToleranceSizeChanged (int theValue); + +public: + //! Updates controls by selection change in table view + //! \param theSelected container of selected table cells + //! \param theDeselected container of selected table cells + void UpdateOnTableSelectionChanged(); + +private: + //! Changes visibility of XStep control, if visible, set parameter value + //! \param theState if true, the control is visible + //! \param theValue the current for the control + void setXStepActive (const bool theState, const double theValue = -1); + +private: + bool myIsActive; //!< state whether the control is visible and used + QWidget* myMainWidget; //!< parent of all controls + QLabel* mySize; //!< control to visualize initial values size + QLabel* myDivideSize; //!< size of division table values to rows + QSpinBox* mySeparateSize; //!< control to divide table by given size if thable has only 1 dimension + QLabel* myVisualizedSize; //!< control to visualize current table size + + bool myXStepActive; //!< state whether the XStep control is visible + QLabel* myXStepLabel; //!< label of X step + QDoubleSpinBox* myXStep; //!< control to enter X step + + QWidget* myInformationWidget; //!< parent of all controls + QPlainTextEdit* myModelInformation; //!< control to visualize current table size + QPushButton* myMinValue; //!< minimum table value + QPushButton* myMaxValue; //!< maximum table value + QPushButton* myMinSelectedValue; //!< minimum value of selected table cells + QPushButton* myMaxSelectedValue; //!< maximum value of selected table cells + + ViewControl_Table* myTable; //!< table control + ViewControl_TableModelFilter* myFilter; //!< table values filter to apply separation size +}; +#endif diff --git a/tools/ViewControl/ViewControl_Tools.cxx b/tools/ViewControl/ViewControl_Tools.cxx index 99d3e441ef..5b025c2713 100644 --- a/tools/ViewControl/ViewControl_Tools.cxx +++ b/tools/ViewControl/ViewControl_Tools.cxx @@ -14,11 +14,14 @@ // commercial license or contractual agreement. #include +#include #include #include +#include #include #include +#include #include #include @@ -43,3 +46,35 @@ void ViewControl_Tools::SetWhiteBackground (QWidget* theControl) aPalette.setColor (QPalette::All, QPalette::Foreground, Qt::white); theControl->setPalette (aPalette); } + +// ======================================================================= +// function : SetDefaultHeaderSections +// purpose : +// ======================================================================= +void ViewControl_Tools::SetDefaultHeaderSections(QTableView* theTableView, const Qt::Orientation theOrientation) +{ + ViewControl_TableModel * aTableModel = dynamic_cast (theTableView->model()); + ViewControl_TableModelValues* aModelValues = aTableModel->GetModelValues(); + if (!aModelValues) + return; + + int aSectionSize; + if (aModelValues->GetDefaultSectionSize (Qt::Horizontal, aSectionSize) ) + theTableView->horizontalHeader()->setDefaultSectionSize (aSectionSize); + else { + bool isStretchLastSection = false; + for (int aColumnId = 0, aNbColumns = aTableModel->columnCount(); aColumnId < aNbColumns; aColumnId++) + { + TreeModel_HeaderSection aSection = aModelValues->GetHeaderItem (theOrientation, aColumnId); + + int aColumnWidth = aSection.GetWidth(); + if (aColumnWidth > 0) + theTableView->setColumnWidth (aColumnId, aColumnWidth); + else if (aColumnId == aNbColumns - 1) + isStretchLastSection = true; + theTableView->setColumnHidden (aColumnId, aSection.IsHidden()); + } + if (isStretchLastSection != theTableView->horizontalHeader()->stretchLastSection()) + theTableView->horizontalHeader()->setStretchLastSection (isStretchLastSection); + } +} diff --git a/tools/ViewControl/ViewControl_Tools.hxx b/tools/ViewControl/ViewControl_Tools.hxx index 7dd4bd4b39..b3f3df768d 100644 --- a/tools/ViewControl/ViewControl_Tools.hxx +++ b/tools/ViewControl/ViewControl_Tools.hxx @@ -25,6 +25,7 @@ class QAction; class QObject; +class QTableView; class QWidget; //! \class ViewControl_Tools @@ -46,6 +47,11 @@ public: //! \param theControl a widget to be modified Standard_EXPORT static void SetWhiteBackground (QWidget* theControl); + //! Fills tree view by default sections parameters obtained in view's table model + //! \param theTableView table view instance + //! \param theOrientation header orientation + Standard_EXPORT static void SetDefaultHeaderSections (QTableView* theTableView, const Qt::Orientation theOrientation); + }; #endif diff --git a/upgrade.bat b/upgrade.bat deleted file mode 100644 index db3f6dc10b..0000000000 --- a/upgrade.bat +++ /dev/null @@ -1,23 +0,0 @@ -@echo off - -rem Helper script to run procedure of automatic upgrade of application code -rem on newer version of OCCT on Windows. -rem Running it requires that Tcl should be in the PATH - -SET "OLD_PATH=%PATH%" - -if exist "%~dp0env.bat" ( - call "%~dp0env.bat" -) - -set "TCL_EXEC=tclsh.exe" - -for %%X in (%TCL_EXEC%) do (set TCL_FOUND=%%~$PATH:X) - -if defined TCL_FOUND ( - %TCL_EXEC% %~dp0adm/start.tcl upgrade %* -) else ( - echo "Error. %TCL_EXEC% is not found. Please update PATH variable" -) - -SET "PATH=%OLD_PATH%" -- 2.39.5