From 5f7c9b057b01472e96692f3e7f9e737870dc74ab Mon Sep 17 00:00:00 2001 From: nds Date: Wed, 12 Feb 2020 23:41:59 +0300 Subject: [PATCH] 0029451: Information Message Alert to debug an algorithm or object functionality --- adm/TOOLS | 2 +- src/DDocStd/DDocStd_ToolsCommands.cxx | 86 +- src/Draw/Draw.cxx | 1 + src/Draw/Draw.hxx | 3 + src/Draw/Draw_Commands.cxx | 1 + src/Draw/Draw_MessageCommands.cxx | 266 +++++ src/Draw/Draw_Printer.cxx | 10 + src/Draw/Draw_Printer.hxx | 2 + src/Draw/FILES | 1 + src/Message/FILES | 21 +- src/Message/Message.cxx | 116 ++- src/Message/Message.hxx | 55 +- src/Message/Message_Alert.hxx | 1 - src/Message/Message_AlertExtended.cxx | 91 ++ src/Message/Message_AlertExtended.hxx | 89 ++ src/Message/Message_Attribute.cxx | 28 + src/Message/Message_Attribute.hxx | 53 + src/Message/Message_AttributeMeter.cxx | 97 ++ src/Message/Message_AttributeMeter.hxx | 75 ++ src/Message/Message_AttributeObject.hxx | 44 + src/Message/Message_AttributeStream.cxx | 41 + src/Message/Message_AttributeStream.hxx | 43 + src/Message/Message_CompositeAlerts.cxx | 155 +++ src/Message/Message_CompositeAlerts.hxx | 77 ++ src/Message/Message_ExecStatus.hxx | 12 + src/Message/Message_Level.cxx | 189 ++++ src/Message/Message_Level.hxx | 103 ++ src/Message/Message_Messenger.cxx | 90 ++ src/Message/Message_Messenger.hxx | 83 +- src/Message/Message_MetricType.hxx | 32 + src/Message/Message_Printer.cxx | 44 + src/Message/Message_Printer.hxx | 17 + src/Message/Message_PrinterOStream.cxx | 10 + src/Message/Message_PrinterOStream.hxx | 3 + src/Message/Message_PrinterSystemLog.cxx | 10 + src/Message/Message_PrinterSystemLog.hxx | 3 + src/Message/Message_PrinterToReport.cxx | 128 +++ src/Message/Message_PrinterToReport.hxx | 88 ++ src/Message/Message_Report.cxx | 345 +++++-- src/Message/Message_Report.hxx | 92 +- src/Message/Message_ReportWriter.hxx | 64 ++ src/TopoDS/FILES | 2 + src/TopoDS/TopoDS_AlertAttribute.cxx | 56 ++ src/TopoDS/TopoDS_AlertAttribute.hxx | 76 ++ src/XmlDrivers/FILES | 2 + .../XmlDrivers_MessageReportStorage.cxx | 356 +++++++ .../XmlDrivers_MessageReportStorage.hxx | 70 ++ tests/basic/begin | 6 + tests/basic/end | 2 + tests/basic/grids.list | 1 + tests/basic/message/messenger | 16 + tests/basic/parse.rules | 3 + tools/Convert/Convert_Tools.cxx | 267 ++++- tools/Convert/Convert_Tools.hxx | 54 +- tools/MessageModel/FILES | 16 + tools/MessageModel/MessageModel.qrc | 6 + .../MessageModel/MessageModel_ActionType.hxx | 32 + tools/MessageModel/MessageModel_Actions.cxx | 268 +++++ tools/MessageModel/MessageModel_Actions.hxx | 98 ++ tools/MessageModel/MessageModel_ItemAlert.cxx | 331 +++++++ tools/MessageModel/MessageModel_ItemAlert.hxx | 137 +++ tools/MessageModel/MessageModel_ItemBase.cxx | 47 + tools/MessageModel/MessageModel_ItemBase.hxx | 56 ++ .../MessageModel/MessageModel_ItemReport.cxx | 227 +++++ .../MessageModel/MessageModel_ItemReport.hxx | 117 +++ tools/MessageModel/MessageModel_ItemRoot.cxx | 96 ++ tools/MessageModel/MessageModel_ItemRoot.hxx | 126 +++ tools/MessageModel/MessageModel_Tools.cxx | 59 ++ tools/MessageModel/MessageModel_Tools.hxx | 53 + tools/MessageModel/MessageModel_TreeModel.cxx | 207 ++++ tools/MessageModel/MessageModel_TreeModel.hxx | 105 ++ tools/MessageModel/icons/item_shape.png | Bin 0 -> 614 bytes tools/MessageModel/icons/item_shape.svg | 122 +++ .../MessageModel/icons/item_streamValues.png | Bin 0 -> 347 bytes .../MessageModel/icons/item_streamValues.svg | 103 ++ tools/MessageView/FILES | 8 + tools/MessageView/MessageView_ActionsTest.cxx | 474 +++++++++ tools/MessageView/MessageView_ActionsTest.hxx | 82 ++ .../MessageView/MessageView_Communicator.cxx | 26 + .../MessageView/MessageView_Communicator.hxx | 66 ++ .../MessageView_VisibilityState.cxx | 150 +++ .../MessageView_VisibilityState.hxx | 99 ++ tools/MessageView/MessageView_Window.cxx | 926 ++++++++++++++++++ tools/MessageView/MessageView_Window.hxx | 206 ++++ tools/ShapeView/ShapeView_Window.cxx | 137 ++- tools/ShapeView/ShapeView_Window.hxx | 9 + tools/TInspectorEXE/TInspectorEXE.cxx | 14 +- tools/TKMessageModel/CMakeLists.txt | 5 + tools/TKMessageModel/EXTERNLIB | 10 + tools/TKMessageModel/FILES | 2 + tools/TKMessageModel/PACKAGES | 1 + tools/TKMessageView/CMakeLists.txt | 5 + tools/TKMessageView/EXTERNLIB | 13 + tools/TKMessageView/FILES | 2 + tools/TKMessageView/PACKAGES | 1 + tools/ToolsDraw/ToolsDraw.cxx | 6 +- tools/TreeModel/TreeModel_ItemBase.hxx | 4 + tools/TreeModel/TreeModel_ItemProperties.cxx | 35 +- tools/TreeModel/TreeModel_ItemProperties.hxx | 13 +- tools/TreeModel/TreeModel_ModelBase.cxx | 35 + tools/TreeModel/TreeModel_ModelBase.hxx | 12 + tools/VInspector/VInspector_ItemBase.hxx | 5 - .../VInspector_ItemPresentableObject.hxx | 2 +- tools/VInspector/VInspector_Window.cxx | 42 +- tools/ViewControl/FILES | 2 + .../ViewControl_PropertiesDialog.cxx | 65 ++ .../ViewControl_PropertiesDialog.hxx | 54 + 107 files changed, 8120 insertions(+), 179 deletions(-) create mode 100644 src/Draw/Draw_MessageCommands.cxx create mode 100644 src/Message/Message_AlertExtended.cxx create mode 100644 src/Message/Message_AlertExtended.hxx create mode 100644 src/Message/Message_Attribute.cxx create mode 100644 src/Message/Message_Attribute.hxx create mode 100644 src/Message/Message_AttributeMeter.cxx create mode 100644 src/Message/Message_AttributeMeter.hxx create mode 100644 src/Message/Message_AttributeObject.hxx create mode 100644 src/Message/Message_AttributeStream.cxx create mode 100644 src/Message/Message_AttributeStream.hxx create mode 100644 src/Message/Message_CompositeAlerts.cxx create mode 100644 src/Message/Message_CompositeAlerts.hxx create mode 100644 src/Message/Message_Level.cxx create mode 100644 src/Message/Message_Level.hxx create mode 100644 src/Message/Message_MetricType.hxx create mode 100644 src/Message/Message_PrinterToReport.cxx create mode 100644 src/Message/Message_PrinterToReport.hxx create mode 100644 src/Message/Message_ReportWriter.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 tests/basic/begin create mode 100644 tests/basic/end create mode 100644 tests/basic/grids.list create mode 100644 tests/basic/message/messenger create mode 100644 tests/basic/parse.rules 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_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_streamValues.png create mode 100644 tools/MessageModel/icons/item_streamValues.svg create mode 100644 tools/MessageView/FILES create mode 100644 tools/MessageView/MessageView_ActionsTest.cxx create mode 100644 tools/MessageView/MessageView_ActionsTest.hxx 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_PropertiesDialog.cxx create mode 100644 tools/ViewControl/ViewControl_PropertiesDialog.hxx 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/DDocStd/DDocStd_ToolsCommands.cxx b/src/DDocStd/DDocStd_ToolsCommands.cxx index 9d925859c9..a287df8f2d 100644 --- a/src/DDocStd/DDocStd_ToolsCommands.cxx +++ b/src/DDocStd/DDocStd_ToolsCommands.cxx @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include +#include //======================================================================= @@ -147,11 +149,81 @@ static Standard_Integer DDocStd_DumpCommand (Draw_Interpretor& di, } return 0; } - di << "TDocStd_DumpCommand : Error\n"; + std::cerr << "TDocStd_DumpCommand : Error\n"; return 1; } +//======================================================================= +//function : DDocStd_ReadMessageReport +//======================================================================= +static Standard_Integer DDocStd_ReadMessageReport (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 2) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + TCollection_ExtendedString aFileName (theArgVec[1]); + Handle(Message_Report) aReport = Message::DefaultReport (Standard_False); + if (aReport.IsNull()) + { + std::cerr << "Error: Message_Report is not created.\n"; + return 0; + } + + Handle(Message_ReportWriter) aWriter = aReport->MessageWriter(); + if (aWriter.IsNull()) + { + aWriter = new XmlDrivers_MessageReportStorage(); + aWriter->SetFileName (aFileName); + aReport->SetMessageWriter (aWriter); + } + + if (!aWriter->ImportReport (aReport)) + { + std::cerr << "Error: Message_Report can not be exported in " << aFileName << ".\n"; + return 0; + } + return 0; +} + +//======================================================================= +//function : DDocStd_WriteMessageReport +//======================================================================= +static Standard_Integer DDocStd_WriteMessageReport (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 2) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + TCollection_ExtendedString aFileName (theArgVec[1]); + Handle(Message_Report) aReport = Message::DefaultReport (Standard_False); + if (aReport.IsNull()) + { + std::cerr << "Error: Message_Report is not created.\n"; + return 0; + } + + Handle(Message_ReportWriter) aWriter = aReport->MessageWriter(); + if (aWriter.IsNull()) + { + aWriter = new XmlDrivers_MessageReportStorage(); + aWriter->SetFileName (aFileName); + aReport->SetMessageWriter (aWriter); + } + + if (!aWriter->ExportReport (aReport)) + { + std::cerr << "Error: Message_Report can not be exported in " << aFileName << ".\n"; + return 0; + } + return 0; +} //======================================================================= //function : ModificationCommands @@ -174,5 +246,15 @@ void DDocStd::ToolsCommands(Draw_Interpretor& theCommands) "DumpCommand (DOC)", __FILE__, DDocStd_DumpCommand, g); -} + theCommands.Add ("ReadMessageReport", + "ReadMessageReport FileName" + "\nRestores content of the default Message_Report from the file. This file is an XML document." + "\nIt might be restored into report using ReadMessageReport." + __FILE__, DDocStd_ReadMessageReport, g); + theCommands.Add ("WriteMessageReport", + "WriteMessageReport FileName" + "\nStores the default Message_Report into a file. This is an XML document." + "\nIt might be restored into report using ReadMessageReport." + __FILE__, DDocStd_WriteMessageReport, g); +} diff --git a/src/Draw/Draw.cxx b/src/Draw/Draw.cxx index 0f83347638..937ae34d6e 100644 --- a/src/Draw/Draw.cxx +++ b/src/Draw/Draw.cxx @@ -425,6 +425,7 @@ void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli) // standard commands // ***************************************************************** Draw::BasicCommands(theCommands); + Draw::MessageCommands(theCommands); Draw::VariableCommands(theCommands); Draw::UnitCommands(theCommands); if (!Draw_Batch) Draw::GraphicCommands(theCommands); diff --git a/src/Draw/Draw.hxx b/src/Draw/Draw.hxx index e718316461..3f0f1457e4 100644 --- a/src/Draw/Draw.hxx +++ b/src/Draw/Draw.hxx @@ -132,6 +132,9 @@ public: //! Defines Draw basic commands Standard_EXPORT static void BasicCommands (Draw_Interpretor& I); + //! Defines Draw message commands + Standard_EXPORT static void MessageCommands (Draw_Interpretor& I); + //! Defines Draw variables handling commands. Standard_EXPORT static void VariableCommands (Draw_Interpretor& I); diff --git a/src/Draw/Draw_Commands.cxx b/src/Draw/Draw_Commands.cxx index c375f9eeda..cf291fb080 100644 --- a/src/Draw/Draw_Commands.cxx +++ b/src/Draw/Draw_Commands.cxx @@ -23,6 +23,7 @@ void Draw::Commands (Draw_Interpretor& theCommands) { Draw::BasicCommands(theCommands); + Draw::MessageCommands(theCommands); Draw::VariableCommands(theCommands); Draw::GraphicCommands(theCommands); Draw::PloadCommands(theCommands); diff --git a/src/Draw/Draw_MessageCommands.cxx b/src/Draw/Draw_MessageCommands.cxx new file mode 100644 index 0000000000..d2dc6dc1e3 --- /dev/null +++ b/src/Draw/Draw_MessageCommands.cxx @@ -0,0 +1,266 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +//============================================================================== +//function : printerType +//purpose : +//============================================================================== +Standard_Boolean printerType (const TCollection_AsciiString& theTypeName, + Handle(Standard_Type)& theType) +{ + if (theTypeName == "ostream") + { + theType = STANDARD_TYPE(Message_PrinterOStream); + } + else if (theTypeName == "systemlog") + { + theType = STANDARD_TYPE(Message_PrinterSystemLog); + } + else if (theTypeName == "report") + { + theType = STANDARD_TYPE(Message_PrinterToReport); + } + else if (theTypeName == "draw") + { + theType = STANDARD_TYPE(Draw_Printer); + } + else + return Standard_False; + + return Standard_True; +} + +//============================================================================== +//function : createPrinter +//purpose : +//============================================================================== +Handle(Message_Printer) createPrinter (const Handle(Standard_Type)& theType, Draw_Interpretor& theDI) +{ + const Standard_CString aTypeName = theType->Name(); + if (aTypeName == STANDARD_TYPE(Message_PrinterOStream)->Name()) + { + return new Message_PrinterOStream(); + } + else if (aTypeName == STANDARD_TYPE(Message_PrinterSystemLog)->Name()) + { + return new Message_PrinterSystemLog ("draw_messages"); + } + else if (aTypeName == STANDARD_TYPE(Message_PrinterToReport)->Name()) + { + Handle(Message_PrinterToReport) aMessagePrinter = new Message_PrinterToReport(); + const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True); + aMessagePrinter->SetReport (aReport); + return aMessagePrinter; + } + else if (aTypeName == STANDARD_TYPE(Draw_Printer)->Name()) + { + return new Draw_Printer (theDI); + } + return Handle(Message_Printer)(); +} + +//============================================================================== +//function : SendMessage +//purpose : +//============================================================================== +static Standard_Integer SendMessage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 2) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + Handle(Standard_Type) aPrinterType; + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) + { + TCollection_AsciiString anArg (theArgVec[anArgIter]); + anArg.LowerCase(); + + aMessenger->Send (anArg); + } + + return 0; +} + +//============================================================================== +//function : DumpMessenger +//purpose : +//============================================================================== +static Standard_Integer DumpMessenger (Draw_Interpretor& theDI, Standard_Integer, const char**) +{ + Standard_SStream aStream; + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + aMessenger->DumpJson (aStream); + + theDI << "Message_Messenger\n"; + theDI << Standard_Dump::FormatJson (aStream); + + return 0; +} + +//============================================================================== +//function : SetMessagePrinter +//purpose : +//============================================================================== +static Standard_Integer SetMessagePrinter (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 2) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + Handle(Standard_Type) aPrinterType; + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) + { + TCollection_AsciiString anArg (theArgVec[anArgIter]); + anArg.LowerCase(); + if (anArg == "-clear") + { + aMessenger->ChangePrinters().Clear(); + } + else if (anArg == "-type" + && anArgIter + 1 < theArgNb) + { + TCollection_AsciiString aVal (theArgVec[++anArgIter]); + if (!printerType (aVal, aPrinterType)) + { + std::cout << "Syntax error: unknown printer type '" << aVal << "'\n"; + return 1; + } + if (aMessenger->HasPrinter (aPrinterType)) + continue; + + aMessenger->AddPrinter (createPrinter (aPrinterType, theDI)); + } + else + { + std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'\n"; + return 1; + } + } + return 0; +} + +//============================================================================== +//function : SetReportMetric +//purpose : +//============================================================================== +static Standard_Integer SetReportMetric(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 1) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True); + if (aReport.IsNull()) + return 1; + + aReport->ClearMetrics(); + for (int i = 1; i < theArgNb; i++) + { + Standard_Integer aMetricId = Draw::Atoi (theArgVec[i]); + if (aMetricId < Message_MetricType_UserTimeCPU || aMetricId > Message_MetricType_MemHeapUsage) + { + std::cout << "Unrecognized message metric: " << aMetricId << std::endl; + return 1; + } + aReport->SetActiveMetric ((Message_MetricType)aMetricId, Standard_True); + } + return 0; +} + +//============================================================================== +//function : PrintReport +//purpose : +//============================================================================== +static Standard_Integer PrintReport(Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec) +{ + if (theArgNb < 1) + { + std::cout << "Error: wrong number of arguments! See usage:\n"; + theDI.PrintHelp (theArgVec[0]); + return 1; + } + + const Handle(Message_Report)& aReport = Message::DefaultReport (Standard_True); + if (aReport.IsNull()) + return 1; + + if (theArgNb > 1) // default messenger + { + aReport->SendMessages (Message::DefaultMessenger()); + } + else // stream + { + Standard_SStream aSStream; + aReport->Dump (aSStream); + theDI << aSStream; + } + + return 0; +} + +void Draw::MessageCommands(Draw_Interpretor& theCommands) +{ + static Standard_Boolean Done = Standard_False; + if (Done) return; + Done = Standard_True; + + std::ios::sync_with_stdio(); + + const char* group = "DRAW Message Commands"; + + theCommands.Add("SetMessagePrinter", + "SetMessagePrinter [-type ostream|systemlog|report|draw] [-clear]" + "\n\t\t: Sets printer into messenger or remove all printers." + "\n : Option -type set type of printer. Printers are applyed with And combination." + "\n : Option -clear remove all printers in messenger", + __FILE__, SetMessagePrinter, group); + + theCommands.Add("DumpMessenger", + "DumpMessenger" + "\n Prints DumpJson information about Messenger.\n", + __FILE__, DumpMessenger, group); + + theCommands.Add("SendMessage", + "SendMessage text [text ...]" + "\n Sends the text into the messenger.\n", + __FILE__, SendMessage, group); + + theCommands.Add("SetReportMetric", "SetReportMetric [metric...] \n Activate report metrics, deactivate all if there are no parameters.\n", + __FILE__, SetReportMetric, group); + + theCommands.Add("PrintReport", "PrintReport [messenger] \n Send report content to default messenger or stream (if parameter is absent).\n", + __FILE__, PrintReport, group); +} diff --git a/src/Draw/Draw_Printer.cxx b/src/Draw/Draw_Printer.cxx index 09e29e1e14..60fa08a3d9 100644 --- a/src/Draw/Draw_Printer.cxx +++ b/src/Draw/Draw_Printer.cxx @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -95,3 +96,12 @@ void Draw_Printer::Send (const TCollection_AsciiString& theString, (*(Draw_Interpretor*)myTcl) << "\n"; } } + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Draw_Printer::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) +} diff --git a/src/Draw/Draw_Printer.hxx b/src/Draw/Draw_Printer.hxx index 2cd649bc2b..600c8b8436 100644 --- a/src/Draw/Draw_Printer.hxx +++ b/src/Draw/Draw_Printer.hxx @@ -61,6 +61,8 @@ public: //! Default implementation calls first method Send(). Standard_EXPORT virtual void Send (const TCollection_AsciiString& theString, const Message_Gravity theGravity, const Standard_Boolean putEndl) const Standard_OVERRIDE; + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; diff --git a/src/Draw/FILES b/src/Draw/FILES index c43b33613f..479b683ce9 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 diff --git a/src/Message/FILES b/src/Message/FILES index 76f6fbebe5..9136393aff 100755 --- a/src/Message/FILES +++ b/src/Message/FILES @@ -1,16 +1,32 @@ Message.cxx Message.hxx +Message_Alert.cxx +Message_Alert.hxx +Message_AlertExtended.cxx +Message_AlertExtended.hxx Message_Algorithm.cxx Message_Algorithm.hxx Message_Algorithm.lxx Message_ConsoleColor.hxx +Message_Attribute.cxx +Message_Attribute.hxx +Message_AttributeMeter.cxx +Message_AttributeMeter.hxx +Message_AttributeObject.hxx +Message_AttributeStream.cxx +Message_AttributeStream.hxx +Message_CompositeAlerts.cxx +Message_CompositeAlerts.hxx Message_ExecStatus.hxx Message_Gravity.hxx Message_HArrayOfMsg.hxx +Message_Level.cxx +Message_Level.hxx Message_ListIteratorOfListOfMsg.hxx Message_ListOfMsg.hxx Message_Messenger.cxx Message_Messenger.hxx +Message_MetricType.hxx Message_Msg.cxx Message_Msg.hxx Message_Msg.lxx @@ -22,6 +38,8 @@ Message_PrinterOStream.cxx Message_PrinterOStream.hxx Message_PrinterSystemLog.cxx Message_PrinterSystemLog.hxx +Message_PrinterToReport.cxx +Message_PrinterToReport.hxx Message_ProgressIndicator.cxx Message_ProgressIndicator.hxx Message_ProgressIndicator.lxx @@ -35,8 +53,7 @@ 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_ReportWriter.hxx diff --git a/src/Message/Message.cxx b/src/Message/Message.cxx index b540ae5fb2..f15d8c51d4 100644 --- a/src/Message/Message.cxx +++ b/src/Message/Message.cxx @@ -17,18 +17,49 @@ #include #include +#include #include #include #include + +static Handle(Message_Messenger) MyMessenger; + //======================================================================= //function : DefaultMessenger //purpose : //======================================================================= -const Handle(Message_Messenger)& Message::DefaultMessenger () + +const Handle(Message_Messenger)& Message::DefaultMessenger() +{ + if (MyMessenger.IsNull()) + MyMessenger = new Message_Messenger; + return MyMessenger; +} + +//======================================================================= +//function : SetDefaultMessenger +//purpose : +//======================================================================= + +void Message::SetDefaultMessenger (const Handle(Message_Messenger)& theMessenger) +{ + MyMessenger = theMessenger; +} + +//======================================================================= +//function : DefaultReport +//purpose : +//======================================================================= + +const Handle(Message_Report)& Message::DefaultReport(const Standard_Boolean theToCreate) { - static Handle(Message_Messenger) aMessenger = new Message_Messenger; - return aMessenger; + static Handle(Message_Report) MyReport; + + if (MyReport.IsNull() && theToCreate) + MyReport = new Message_Report(); + + return MyReport; } //======================================================================= @@ -49,3 +80,82 @@ TCollection_AsciiString Message::FillTime (const Standard_Integer hour, Sprintf (t, "%.2fs", second); return TCollection_AsciiString (t); } + +namespace +{ + static Standard_CString Message_Table_PrintMetricTypeEnum[10] = + { + "NONE", "UserTimeCPU", "SystemTimeInfo", "MemPrivate", "MemVirtual", + "MemWorkingSet", "MemWorkingSetPeak", "MemSwapUsage", "MemSwapUsagePeak", "MemHeapUsage" + }; +} + +//======================================================================= +//function : MetricToString +//purpose : +//======================================================================= + +Standard_CString Message::MetricToString (const Message_MetricType theType) +{ + return Message_Table_PrintMetricTypeEnum[theType]; +} + +//======================================================================= +//function : MetricFromString +//purpose : +//======================================================================= + +Standard_Boolean Message::MetricFromString (const Standard_CString theString, + Message_MetricType& theGravity) +{ + TCollection_AsciiString aName (theString); + for (Standard_Integer aMetricIter = 0; aMetricIter <= Message_MetricType_MemHeapUsage; ++aMetricIter) + { + Standard_CString aMetricName = Message_Table_PrintMetricTypeEnum[aMetricIter]; + if (aName == aMetricName) + { + theGravity = Message_MetricType (aMetricIter); + return Standard_True; + } + } + return Standard_False; +} + +// ======================================================================= +// function : ToOSDMetric +// purpose : +// ======================================================================= +Standard_Boolean Message::ToOSDMetric (const Message_MetricType theMetric, OSD_MemInfo::Counter& theMemInfo) +{ + switch (theMetric) + { + case Message_MetricType_MemPrivate: theMemInfo = OSD_MemInfo::MemPrivate; break; + case Message_MetricType_MemVirtual: theMemInfo = OSD_MemInfo::MemVirtual; break; + case Message_MetricType_MemWorkingSet: theMemInfo = OSD_MemInfo::MemWorkingSet; break; + case Message_MetricType_MemWorkingSetPeak: theMemInfo = OSD_MemInfo::MemWorkingSetPeak; break; + case Message_MetricType_MemSwapUsage: theMemInfo = OSD_MemInfo::MemSwapUsage; break; + case Message_MetricType_MemSwapUsagePeak: theMemInfo = OSD_MemInfo::MemSwapUsagePeak; break; + case Message_MetricType_MemHeapUsage: theMemInfo = OSD_MemInfo::MemHeapUsage; break; + } + return Standard_True; +} + +// ======================================================================= +// function : ToMessageMetric +// purpose : +// ======================================================================= +Standard_Boolean Message::ToMessageMetric (const OSD_MemInfo::Counter theMemInfo, Message_MetricType& theMetric) +{ + switch (theMemInfo) + { + case OSD_MemInfo::MemPrivate: theMetric = Message_MetricType_MemPrivate; break; + case OSD_MemInfo::MemVirtual: theMetric = Message_MetricType_MemVirtual; break; + case OSD_MemInfo::MemWorkingSet: theMetric = Message_MetricType_MemWorkingSet; break; + case OSD_MemInfo::MemWorkingSetPeak: theMetric = Message_MetricType_MemWorkingSetPeak; break; + case OSD_MemInfo::MemSwapUsage: theMetric = Message_MetricType_MemSwapUsage; break; + case OSD_MemInfo::MemSwapUsagePeak: theMetric = Message_MetricType_MemSwapUsagePeak; break; + case OSD_MemInfo::MemHeapUsage: theMetric = Message_MetricType_MemHeapUsage; break; + default: return Standard_False; + } + return Standard_True; +} diff --git a/src/Message/Message.hxx b/src/Message/Message.hxx index 4be71135b3..4d728159e4 100644 --- a/src/Message/Message.hxx +++ b/src/Message/Message.hxx @@ -17,14 +17,20 @@ #ifndef _Message_HeaderFile #define _Message_HeaderFile +#include +#include +#include +#include + #include #include #include #include #include +#include + class Message_Messenger; -class TCollection_AsciiString; class Message_Msg; class Message_MsgFile; class Message_Messenger; @@ -34,6 +40,7 @@ class Message_PrinterOStream; class Message_ProgressIndicator; class Message_ProgressScale; class Message_ProgressSentry; +class Message_Report; //! Defines @@ -51,7 +58,15 @@ public: //! By default, it contains single printer directed to std::cout. //! It can be customized according to the application needs. Standard_EXPORT static const Handle(Message_Messenger)& DefaultMessenger(); - + + //! Sets default messenger. + Standard_EXPORT static void SetDefaultMessenger (const Handle(Message_Messenger)& theMessenger); + + //! 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 const Handle(Message_Report)& DefaultReport (const Standard_Boolean theToCreate = Standard_False); + //! Returns the string filled with values of hours, minutes and seconds. //! Example: //! 1. (5, 12, 26.3345) returns "05h:12m:26.33s", @@ -59,15 +74,45 @@ 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); - - + //! Determines the metric from the given string identifier. + //! @param theString string identifier + //! @param theType detected type of metric + //! @return TRUE if string identifier is known + Standard_EXPORT static Standard_Boolean MetricFromString (const Standard_CString theString, + Message_MetricType& theType); + + //! Returns the string name for a given metric type. + //! @param theType metric type + //! @return string identifier from the list of Message_MetricType + Standard_EXPORT static Standard_CString MetricToString (const Message_MetricType theType); + + //! Returns the metric type from the given string identifier. + //! @param theString string identifier + //! @return metric type or Message_MetricType_None if string identifier is invalid + static Message_MetricType MetricFromString (const Standard_CString theString) + { + Message_MetricType aMetric = Message_MetricType_None; + MetricFromString (theString, aMetric); + return aMetric; + } + + //! Converts message metric to OSD memory info type. + //! @param theMetric [in] message metric + //! @param theMemInfo [out] filled memory info type + //! @return true if converted + static Standard_EXPORT Standard_Boolean ToOSDMetric (const Message_MetricType theMetric, OSD_MemInfo::Counter& theMemInfo); + + //! Converts OSD memory info type to message metric. + //! @param theMemInfo [int] memory info type + //! @param theMetric [out] filled message metric + //! @return true if converted + static Standard_EXPORT Standard_Boolean ToMessageMetric (const OSD_MemInfo::Counter theMemInfo, Message_MetricType& theMetric); protected: - private: diff --git a/src/Message/Message_Alert.hxx b/src/Message/Message_Alert.hxx index 030efb0f99..a460787354 100644 --- a/src/Message/Message_Alert.hxx +++ b/src/Message/Message_Alert.hxx @@ -54,7 +54,6 @@ public: //! Base implementation always returns true. virtual Standard_EXPORT Standard_Boolean Merge (const Handle(Message_Alert)& theTarget); - // OCCT RTTI DEFINE_STANDARD_RTTIEXT(Message_Alert,Standard_Transient) }; diff --git a/src/Message/Message_AlertExtended.cxx b/src/Message/Message_AlertExtended.cxx new file mode 100644 index 0000000000..843c3b6d31 --- /dev/null +++ b/src/Message/Message_AlertExtended.cxx @@ -0,0 +1,91 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include +#include + +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_AlertExtended,Message_Alert) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_AlertExtended::GetMessageKey () const +{ + if (myAttribute.IsNull()) + return Message_Alert::GetMessageKey(); + + return myAttribute->GetMessageKey(); +} + +//======================================================================= +//function : CompositeAlerts +//purpose : +//======================================================================= +Handle(Message_CompositeAlerts) Message_AlertExtended::CompositeAlerts (const Standard_Boolean theToCreate) +{ + if (myCompositAlerts.IsNull() && theToCreate) + myCompositAlerts = new Message_CompositeAlerts(); + + return myCompositAlerts; +} + +//======================================================================= +//function : SupportsMerge +//purpose : +//======================================================================= +Standard_Boolean Message_AlertExtended::SupportsMerge () const +{ + if (myCompositAlerts.IsNull()) + return Standard_True; + + // hierarchical alerts can not be merged + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) + { + if (!myCompositAlerts->Alerts ((Message_Gravity)aGravIter).IsEmpty()) + return Standard_False; + } + + return Standard_True; +} + +//======================================================================= +//function : Merge +//purpose : +//======================================================================= +Standard_Boolean Message_AlertExtended::Merge (const Handle(Message_Alert)& /*theTarget*/) +{ + // by default, merge trivially + return Standard_False; +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= +Handle(Message_Alert) Message_AlertExtended::AddAlert (const Handle(Message_Report)& theReport, + const Handle(Message_Attribute)& theAttribute, + const Message_Gravity theGravity) +{ + Handle(Message_AlertExtended) anAlert = new Message_AlertExtended(); + anAlert->SetAttribute (theAttribute); + theReport->AddAlert (theGravity, anAlert); + + return anAlert; +} diff --git a/src/Message/Message_AlertExtended.hxx b/src/Message/Message_AlertExtended.hxx new file mode 100644 index 0000000000..8c0420836d --- /dev/null +++ b/src/Message/Message_AlertExtended.hxx @@ -0,0 +1,89 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_AlertExtended_HeaderFile +#define _Message_AlertExtended_HeaderFile + +#include +#include +#include + +class Message_Attribute; +class Message_Report; + +DEFINE_STANDARD_HANDLE(Message_AlertExtended, Message_Alert) + +class Message_CompositeAlerts; + +//! Inherited class of Message_Alert with some additional information. +//! +//! It has Message_Attributes to provide the alert name, and other custom information +//! +//! It has a container of composite alerts, if the alert might provide +//! sub-alerts collecting. +//! +class Message_AlertExtended : public Message_Alert +{ +public: + //! Empty constructor + Standard_EXPORT Message_AlertExtended() : Message_Alert() {} + + //! 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. + Standard_EXPORT virtual Standard_CString GetMessageKey () const Standard_OVERRIDE; + + //! Sets container of the alert attributes + //! @param theAttributes an attribute values + void SetAttribute (const Handle(Message_Attribute)& theAttribute) { myAttribute = theAttribute; } + + //! Returns container of the alert attributes + //! @param theAttributes an attribute values + const Handle(Message_Attribute)& Attribute() const { return myAttribute; } + + //! Returns class provided hierarchy of alerts if created or create if the parameter is true + //! @param isCreate if composite alert has not been created for this alert, it should be created + //! @return instance or NULL + Standard_EXPORT Handle(Message_CompositeAlerts) CompositeAlerts (const Standard_Boolean theToCreate = Standard_False); + + //! Return true if this type of alert can be merged with other + //! of the same type to avoid duplication. + //! Hierarchical alerts can not be merged + //! Basis implementation returns true. + virtual Standard_EXPORT Standard_Boolean SupportsMerge() const Standard_OVERRIDE; + + //! If possible, merge data contained in this alert to theTarget. + //! @return True if merged. + //! Base implementation always returns false. + virtual Standard_EXPORT Standard_Boolean Merge (const Handle(Message_Alert)& theTarget) Standard_OVERRIDE; + + //! 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 + //! @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, + const Message_Gravity theGravity); + + DEFINE_STANDARD_RTTIEXT(Message_AlertExtended, Message_Alert) + +protected: + + Handle(Message_CompositeAlerts) myCompositAlerts; //!< class provided hierarchical structure of alerts + Handle(Message_Attribute) myAttribute; //!< container of the alert attributes +}; + +#endif // _Message_Alert_HeaderFile diff --git a/src/Message/Message_Attribute.cxx b/src/Message/Message_Attribute.cxx new file mode 100644 index 0000000000..6efcd0f7ba --- /dev/null +++ b/src/Message/Message_Attribute.cxx @@ -0,0 +1,28 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient) + +//======================================================================= +//function : GetMessageKey +//purpose : +//======================================================================= + +Standard_CString Message_Attribute::GetMessageKey () const +{ + return !myName.IsEmpty() ? myName.ToCString() : ""; +} diff --git a/src/Message/Message_Attribute.hxx b/src/Message/Message_Attribute.hxx new file mode 100644 index 0000000000..cce24fd803 --- /dev/null +++ b/src/Message/Message_Attribute.hxx @@ -0,0 +1,53 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _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()) + : myName (theName) {} + + //! 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; } + + DEFINE_STANDARD_RTTIEXT(Message_Attribute, Standard_Transient) + +private: + TCollection_AsciiString myName; //!< alert name, if defined is used in GetMessageKey + +}; + +#endif // _Message_Attribute_HeaderFile diff --git a/src/Message/Message_AttributeMeter.cxx b/src/Message/Message_AttributeMeter.cxx new file mode 100644 index 0000000000..227c4b5e61 --- /dev/null +++ b/src/Message/Message_AttributeMeter.cxx @@ -0,0 +1,97 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeMeter, Message_Attribute) + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= +Message_AttributeMeter::Message_AttributeMeter (const TCollection_AsciiString& theName) +: Message_Attribute(theName) +{ +} + +//======================================================================= +//function : HasMetric +//purpose : +//======================================================================= +Standard_Boolean Message_AttributeMeter::HasMetric (const Message_MetricType& theMetric) const +{ + return myMetrics.IsBound (theMetric); +} + +//======================================================================= +//function : IsMetricValid +//purpose : +//======================================================================= +Standard_Boolean Message_AttributeMeter::IsMetricValid (const Message_MetricType& theMetric) const +{ + return Abs (StartValue (theMetric) - UndefinedMetricValue()) > Precision::Confusion() && + Abs (StopValue (theMetric) - UndefinedMetricValue()) > Precision::Confusion(); +} + +//======================================================================= +//function : StartValue +//purpose : +//======================================================================= +Standard_Real Message_AttributeMeter::StartValue (const Message_MetricType& theMetric) const +{ + if (!HasMetric (theMetric)) + return UndefinedMetricValue(); + + return myMetrics.Seek (theMetric)->first; +} + +//======================================================================= +//function : SetStartValue +//purpose : +//======================================================================= +void Message_AttributeMeter::SetStartValue (const Message_MetricType& theMetric, const Standard_Real theValue) +{ + if (!HasMetric (theMetric)) + { + myMetrics.Bind (theMetric, std::make_pair (theValue, UndefinedMetricValue())); + } + myMetrics.ChangeFind (theMetric).first = theValue; +} + +//======================================================================= +//function : StopValue +//purpose : +//======================================================================= +Standard_Real Message_AttributeMeter::StopValue (const Message_MetricType& theMetric) const +{ + if (!HasMetric (theMetric)) + return UndefinedMetricValue(); + + return myMetrics.Find (theMetric).second; +} + +//======================================================================= +//function : SetStopValue +//purpose : +//======================================================================= +void Message_AttributeMeter::SetStopValue (const Message_MetricType& theMetric, const Standard_Real theValue) +{ + if (!HasMetric (theMetric)) + { + // start value should be already set + return; + } + myMetrics.ChangeFind (theMetric).second = theValue; +} diff --git a/src/Message/Message_AttributeMeter.hxx b/src/Message/Message_AttributeMeter.hxx new file mode 100644 index 0000000000..f563c28377 --- /dev/null +++ b/src/Message/Message_AttributeMeter.hxx @@ -0,0 +1,75 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_AttributeMeter_HeaderFile +#define _Message_AttributeMeter_HeaderFile + +#include +#include + +#include + +class Message_Alert; + +//! Alert object storing alert metrics values. +//! Start and stop values for each metric. +class Message_AttributeMeter : public Message_Attribute +{ +public: + + //! Returns default value of the metric when it is not defined + //! @return undefined value + static Standard_Real UndefinedMetricValue() { return -1.0; } + +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeMeter (const TCollection_AsciiString& theName = TCollection_AsciiString()); + + //! Checks whether the attribute has values for the metric + //! @param theMetric [in] metric type + //! @return true if the metric values exist in the attribute + Standard_EXPORT Standard_Boolean HasMetric (const Message_MetricType& theMetric) const; + + //! Returns true when both values of the metric are set. + //! @param theMetric [in] metric type + //! @return true if metric values are valid + Standard_EXPORT Standard_Boolean IsMetricValid (const Message_MetricType& theMetric) const; + + //! Returns start value for the metric + //! @param theMetric [in] metric type + //! @return real value + Standard_EXPORT Standard_Real StartValue (const Message_MetricType& theMetric) const; + + //! Sets start values for the metric + //! @param theMetric [in] metric type + Standard_EXPORT void SetStartValue (const Message_MetricType& theMetric, const Standard_Real theValue); + + //! Returns stop value for the metric + //! @param theMetric [in] metric type + //! @return real value + Standard_EXPORT Standard_Real StopValue (const Message_MetricType& theMetric) const; + + //! Sets stop values for the metric + //! @param theMetric [in] metric type + Standard_EXPORT void SetStopValue (const Message_MetricType& theMetric, const Standard_Real theValue); + + DEFINE_STANDARD_RTTIEXT(Message_AttributeMeter, Message_Attribute) + +private: + + typedef std::pair StartToStopValue; + NCollection_DataMap myMetrics; //!< computed metrics +}; + +#endif // _Message_AttributeMeter_HeaderFile diff --git a/src/Message/Message_AttributeObject.hxx b/src/Message/Message_AttributeObject.hxx new file mode 100644 index 0000000000..3775685da1 --- /dev/null +++ b/src/Message/Message_AttributeObject.hxx @@ -0,0 +1,44 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_AttributeObject_HeaderFile +#define _Message_AttributeObject_HeaderFile + +#include + +class Standard_Transient; + +//! Alert object storing a transient object +class Message_AttributeObject : public Message_Attribute +{ +public: + //! Constructor with string argument + Message_AttributeObject (const Handle(Standard_Transient)& theObject, + const TCollection_AsciiString& theName = TCollection_AsciiString()) + : Message_Attribute (theName) { myObject = theObject; } + + //! Returns object + //! @return the object instance + const Handle(Standard_Transient)& Object() { return myObject; } + + //! Sets the object + //! @param theObject an instance + void SetObject (const Handle(Standard_Transient)& theObject) { myObject = theObject; } + + DEFINE_STANDARD_RTTI_INLINE(Message_AttributeObject, Message_Attribute) + +private: + Handle(Standard_Transient) myObject; //!< alert object +}; + +#endif // _Message_AttributeObject_HeaderFile diff --git a/src/Message/Message_AttributeStream.cxx b/src/Message/Message_AttributeStream.cxx new file mode 100644 index 0000000000..f0cf931415 --- /dev/null +++ b/src/Message/Message_AttributeStream.cxx @@ -0,0 +1,41 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute) + +//======================================================================= +//function : SetValues +//purpose : +//======================================================================= +Message_AttributeStream::Message_AttributeStream (const Standard_SStream& theStream, + const TCollection_AsciiString& theName) +: Message_Attribute(theName) +{ + SetStream (theStream); +} + +//======================================================================= +//function : SetStream +//purpose : +//======================================================================= + +void Message_AttributeStream::SetStream (const Standard_SStream& theStream) +{ + myStream.str (""); + + TCollection_AsciiString aStreamStr (theStream.str().c_str()); + myStream << aStreamStr; +} + diff --git a/src/Message/Message_AttributeStream.hxx b/src/Message/Message_AttributeStream.hxx new file mode 100644 index 0000000000..c4a73527fa --- /dev/null +++ b/src/Message/Message_AttributeStream.hxx @@ -0,0 +1,43 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_AttributeStream_HeaderFile +#define _Message_AttributeStream_HeaderFile + +#include + +#include +#include + +//! Alert object storing stream values +class Message_AttributeStream : public Message_Attribute +{ +public: + + //! Constructor with string argument + Standard_EXPORT Message_AttributeStream (const Standard_SStream& theStream, + const TCollection_AsciiString& theName = TCollection_AsciiString()); + + //! Returns stream value + const Standard_SStream& Stream() const { return myStream; } + + //! Sets stream value + Standard_EXPORT void SetStream (const Standard_SStream& theStream); + + DEFINE_STANDARD_RTTIEXT(Message_AttributeStream, Message_Attribute) + +private: + Standard_SStream myStream; //!< container of values +}; + +#endif // _Message_AttributeStream_HeaderFile diff --git a/src/Message/Message_CompositeAlerts.cxx b/src/Message/Message_CompositeAlerts.cxx new file mode 100644 index 0000000000..48d0e14be9 --- /dev/null +++ b/src/Message/Message_CompositeAlerts.cxx @@ -0,0 +1,155 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include +#include + +IMPLEMENT_STANDARD_RTTIEXT(Message_CompositeAlerts, Standard_Transient) + +//======================================================================= +//function : Alerts +//purpose : +//======================================================================= +const Message_ListOfAlert& Message_CompositeAlerts::Alerts (const Message_Gravity theGravity) const +{ + static const Message_ListOfAlert anEmptyList; + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Requesting alerts for gravity not in valid range", anEmptyList); + + return myAlerts[theGravity]; +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= +Standard_Boolean Message_CompositeAlerts::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert) +{ + Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert", Standard_False); + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Adding alert with gravity not in valid range", Standard_False); + + Message_ListOfAlert& aList = myAlerts[theGravity]; + if (theAlert->SupportsMerge() && ! aList.IsEmpty()) + { + // merge is performed only for alerts of exactly same type + 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 Standard_False; + } + } + + // if not merged, just add to the list + aList.Append (theAlert); + return Standard_True; +} + +//======================================================================= +//function : RemoveAlert +//purpose : +//======================================================================= +Standard_Boolean Message_CompositeAlerts::RemoveAlert (Message_Gravity theGravity, + const Handle(Message_Alert)& theAlert) +{ + Standard_ASSERT_RETURN (! theAlert.IsNull(), "Attempt to add null alert", Standard_False); + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Adding alert with gravity not in valid range", Standard_False); + + Message_ListOfAlert& anAlerts = myAlerts[theGravity]; + if (!anAlerts.Contains (theAlert)) + return Standard_False; + + return anAlerts.Remove (theAlert); +} + +//======================================================================= +//function : HasAlerts +//purpose : +//======================================================================= + +Standard_Boolean Message_CompositeAlerts::HasAlert (const Handle(Message_Alert)& theAlert) +{ + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) + { + const Message_ListOfAlert& anAlerts = Alerts ((Message_Gravity)aGravIter); + if (anAlerts.Contains (theAlert)) + return Standard_True; + } + return Standard_False; +} + +//======================================================================= +//function : HasAlerts +//purpose : +//======================================================================= +Standard_Boolean Message_CompositeAlerts::HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity) +{ + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Requesting alerts for gravity not in valid range", Standard_False); + + for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next()) + { + if (anIt.Value()->IsInstance(theType)) + return Standard_True; + } + return Standard_False; +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void Message_CompositeAlerts::Clear () +{ + for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) + { + myAlerts[i].Clear(); + } +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void Message_CompositeAlerts::Clear (Message_Gravity theGravity) +{ + Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), + "Requesting alerts for gravity not in valid range", ); + myAlerts[theGravity].Clear(); +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= +void Message_CompositeAlerts::Clear (const Handle(Standard_Type)& theType) +{ + for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) + { + for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); ) + { + if (anIt.Value().IsNull() || anIt.Value()->IsInstance (theType)) + { + myAlerts[i].Remove (anIt); + } + else + { + anIt.More(); + } + } + } +} diff --git a/src/Message/Message_CompositeAlerts.hxx b/src/Message/Message_CompositeAlerts.hxx new file mode 100644 index 0000000000..0864e05b6f --- /dev/null +++ b/src/Message/Message_CompositeAlerts.hxx @@ -0,0 +1,77 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_CompositeAlerts_HeaderFile +#define _Message_CompositeAlerts_HeaderFile + +#include +#include +#include +#include + +class Message_CompositeAlerts; +DEFINE_STANDARD_HANDLE(Message_CompositeAlerts, Standard_Transient) + +//! Class providing container of alerts +class Message_CompositeAlerts : public Standard_Transient +{ +public: + //! Empty constructor + Standard_EXPORT Message_CompositeAlerts() {} + + //! Returns list of collected alerts with specified gravity + Standard_EXPORT const Message_ListOfAlert& Alerts (const Message_Gravity theGravity) const; + + //! Add alert with specified gravity. If the alert supports merge it will be merged. + //! @param theGravity an alert gravity + //! @param theAlert an alert to be added as a child alert + //! @return true if the alert is added or merged + Standard_EXPORT Standard_Boolean AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert); + + //! Removes alert with specified gravity. + //! @param theGravity an alert gravity + //! @param theAlert an alert to be removed from the children + //! @return true if the alert is removed + Standard_EXPORT Standard_Boolean RemoveAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert); + + //! 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); + + //! Returns true if specific type of alert is recorded with specified gravity + //! @param theType an alert type + //! @param theGravity an alert gravity + //! @return true if the alert is found in a container of children + Standard_EXPORT Standard_Boolean HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity); + + //! Clears all collected alerts + Standard_EXPORT void Clear (); + + //! Clears collected alerts with specified gravity + //! @param theGravity an alert gravity + Standard_EXPORT void Clear (Message_Gravity theGravity); + + //! Clears collected alerts with specified type + //! @param theType an alert type + Standard_EXPORT void Clear (const Handle(Standard_Type)& theType); + + DEFINE_STANDARD_RTTIEXT(Message_CompositeAlerts,Standard_Transient) + +protected: + // store messages in a lists sorted by gravity; + // here we rely on knowledge that Message_Fail is the last element of the enum + Message_ListOfAlert myAlerts[Message_Fail + 1]; //!< container of child alert for each type of gravity +}; + +#endif // _Message_CompositeAlerts_HeaderFile diff --git a/src/Message/Message_ExecStatus.hxx b/src/Message/Message_ExecStatus.hxx index 42eb19c6b9..06d06b8df0 100644 --- a/src/Message/Message_ExecStatus.hxx +++ b/src/Message/Message_ExecStatus.hxx @@ -21,6 +21,8 @@ #include #include +#include + /** * Tiny class for extended handling of error / execution * status of algorithm in universal way. @@ -162,6 +164,16 @@ class Message_ExecStatus const Message_ExecStatus& operator &= ( const Message_ExecStatus& theOther ) { And ( theOther ); return *this; } + //! Dumps the content of me into the stream + virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const + { + (void)theDepth; + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDone) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myWarn) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myAlarm) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFail) + } + //@} public: diff --git a/src/Message/Message_Level.cxx b/src/Message/Message_Level.cxx new file mode 100644 index 0000000000..e012723651 --- /dev/null +++ b/src/Message/Message_Level.cxx @@ -0,0 +1,189 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +//======================================================================= +//function : Message_Level +//purpose : +//======================================================================= +Message_Level::Message_Level() +{ + const Handle(Message_Report)& aDefaultReport = Message::DefaultReport(); + if (!aDefaultReport.IsNull() && aDefaultReport->IsActiveInMessenger()) + aDefaultReport->AddLevel (this); +} + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +Message_Level::~Message_Level() +{ + Remove(); +} + +//======================================================================= +//function : SetRootAlert +//purpose : +//======================================================================= +void Message_Level::SetRootAlert (const Handle(Message_AlertExtended)& theAlert) +{ + myRootAlert = theAlert; + startAlert (myRootAlert); +} + +//======================================================================= +//function : AddAlert +//purpose : +//======================================================================= +Standard_Boolean Message_Level::AddAlert (const Message_Gravity theGravity, + const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlertExtended.IsNull()) + return Standard_False; + + if (myRootAlert.IsNull()) + return Standard_False; + + // looking for the parent of the parameter alert to release the previous alert + Handle(Message_AlertExtended) aRootAlert = myRootAlert; + Handle(Message_CompositeAlerts) aCompositeAlert = aRootAlert->CompositeAlerts (Standard_True); + + // update metrics of the previous alert + stopAlert (myLastAlert); + + myLastAlert = anAlertExtended; + + // set start metrics of the new alert + startAlert (myLastAlert); + + // add child alert + aCompositeAlert->AddAlert (theGravity, theAlert); + + return Standard_True; +} + +//======================================================================= +//function : AddLevelAlert +//purpose : +//======================================================================= +Standard_Boolean Message_Level::AddLevelAlert (const Message_Gravity theGravity, + const Handle(Message_Alert)& theAlert) +{ + Handle(Message_AlertExtended) aRootAlert = /*!myLastAlert.IsNull() ? myLastAlert :*/ myRootAlert; + if (aRootAlert.IsNull()) + return Standard_False; + + Handle(Message_CompositeAlerts) aCompositeAlert = aRootAlert->CompositeAlerts (Standard_True); + // add child alert + aCompositeAlert->AddAlert (theGravity, theAlert); + + return Standard_True; +} + +//======================================================================= +//function : Remove() +//purpose : +//======================================================================= +void Message_Level::Remove() +{ + const Handle(Message_Report)& aDefaultReport = Message::DefaultReport(); + if (aDefaultReport.IsNull() || !aDefaultReport->IsActiveInMessenger()) + return; + + stopAlert (myLastAlert); + stopAlert (myRootAlert); + + if (!Message::DefaultReport().IsNull()) + Message::DefaultReport()->RemoveLevel (this); +} + +//======================================================================= +//function : setAlertMetrics +//purpose : +//======================================================================= +void Message_Level::setAlertMetrics (const Handle(Message_AlertExtended)& theAlert, + const Standard_Boolean theStartValue) +{ + if (theAlert.IsNull()) + return; + + Handle(Message_AttributeMeter) aMeterAttribute = Handle(Message_AttributeMeter)::DownCast (theAlert->Attribute()); + if (aMeterAttribute.IsNull()) + return; + + Handle(Message_Report) aReport = Message::DefaultReport (Standard_True); + const NCollection_Map& anActiveMetrics = aReport->ActiveMetrics(); + + // time metrics + if (anActiveMetrics.Contains (Message_MetricType_UserTimeCPU) || + anActiveMetrics.Contains (Message_MetricType_SystemTimeInfo)) + { + Standard_Real aUserSeconds, aSystemSeconds; + OSD_Chronometer::GetThreadCPU (aUserSeconds, aSystemSeconds); + + if (anActiveMetrics.Contains (Message_MetricType_UserTimeCPU)) + { + if (theStartValue) + aMeterAttribute->SetStartValue (Message_MetricType_UserTimeCPU, aUserSeconds); + else + aMeterAttribute->SetStopValue (Message_MetricType_UserTimeCPU, aUserSeconds); + } + if (anActiveMetrics.Contains (Message_MetricType_SystemTimeInfo)) + { + if (theStartValue) + aMeterAttribute->SetStartValue (Message_MetricType_SystemTimeInfo, aSystemSeconds); + else + aMeterAttribute->SetStopValue (Message_MetricType_SystemTimeInfo, aSystemSeconds); + } + } + // memory metrics + NCollection_Map aCounters; + for (NCollection_Map::Iterator anIterator (anActiveMetrics); anIterator.More(); anIterator.Next()) + { + OSD_MemInfo::Counter aMemInfo; + if (!Message::ToOSDMetric (anIterator.Value(), aMemInfo)) + continue; + + aCounters.Add (aMemInfo); + } + if (aCounters.IsEmpty()) + return; + + OSD_MemInfo aMemInfo (Standard_False); + //aMemInfo.SetActiveCounters (aCounters); + aMemInfo.Update (); + Message_MetricType aMetricType; + for (NCollection_Map::Iterator anIterator (aCounters); anIterator.More(); anIterator.Next()) + { + if (!Message::ToMessageMetric (anIterator.Value(), aMetricType)) + continue; + + if (theStartValue) + aMeterAttribute->SetStartValue (aMetricType, (Standard_Real)aMemInfo.ValuePreciseMiB (anIterator.Value())); + else + aMeterAttribute->SetStopValue (aMetricType, (Standard_Real)aMemInfo.ValuePreciseMiB (anIterator.Value())); + } +} diff --git a/src/Message/Message_Level.hxx b/src/Message/Message_Level.hxx new file mode 100644 index 0000000000..03984a284e --- /dev/null +++ b/src/Message/Message_Level.hxx @@ -0,0 +1,103 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_Level_HeaderFile +#define _Message_Level_HeaderFile + +#include +#include +#include +#include +#include + +#include +#include + +//! This class is an instance of Sentry to create a level in a message report +//! Constructor of the class add new (active) level in the report, destructor removes it +//! While the level is active in the report, new alerts are added below the level root alert. +//! +//! The first added alert is a root alert, other are added below the root alert +//! +//! If alert has Message_AttributeMeter attribute, active metrics of the default report are stored in +//! the attriute: start value of metric on adding alert, stop on adding another alert or closing (delete) the level +//! in the report. +//! +//! Processing of this class is implemented in Message_Report, it is used only insided it. +//! Levels using should be only through using OCCT_ADD_MESSAGE_LEVEL_SENTRY only. No other code is required outside. +class Message_Level +{ + +public: + //! Constructor. Append + //! One string key is used for all alert meters. The perf meter is not started automatically, it will be done in + //! AddAlert method + Standard_EXPORT Message_Level(); + + //! Assures stopping upon destruction + Standard_EXPORT ~Message_Level(); + + //! Returns root alert of the level + //! @return alert instance or NULL + const Handle(Message_AlertExtended)& RootAlert() const { return myRootAlert; } + + //! Sets the root alert. Starts collects alert metrics if active. + //! @param theAlert an alert + Standard_EXPORT void SetRootAlert (const Handle(Message_AlertExtended)& theAlert); + + //! Adds new alert on the level. Stops the last alert metric, appends the alert and starts the alert metrics collecting. + //! Sets root alert beforehead this method using, if the root is NULL, it does nothing. + //! @param theGravity an alert gravity + //! @param theAlert an alert + //! @return true if alert is added + Standard_EXPORT Standard_Boolean AddAlert (const Message_Gravity theGravity, + const Handle(Message_Alert)& theAlert); + + //! Add new alert as a child of the last alert if exists or as a child of the root alert. + //! @param theGravity an alert gravity + //! @param theAlert an alert + //! @return true if alert is added + Standard_EXPORT Standard_Boolean AddLevelAlert (const Message_Gravity theGravity, + const Handle(Message_Alert)& theAlert); + + //! Remove the current level from the report. It stops metric collecting for the last and the root alerts. + Standard_EXPORT void Remove(); + +protected: + //! Sets start values of default report metrics into the alert + //! @param theAlert an alert + void startAlert (const Handle(Message_AlertExtended)& theAlert) { setAlertMetrics (theAlert, Standard_True); } + + //! Sets stop values of default report metrics into the alert + //! @param theAlert an alert + void stopAlert (const Handle(Message_AlertExtended)& theAlert) { setAlertMetrics (theAlert, Standard_True); } + + //! Sets current values of default report metrics into the alert. + //! Processed oly alert with Message_AttributeMeter attribute + //! @param theAlert an alert + //! @param theStartValue flag, if true, the start value is collected otherwise stop + Standard_EXPORT void setAlertMetrics (const Handle(Message_AlertExtended)& theAlert, + const Standard_Boolean theStartValue); + +protected: + Handle(Message_AlertExtended) myRootAlert; //!< root alert + Handle(Message_AlertExtended) myLastAlert; //!< last added alert on the root alert +}; + +//! @def MESSAGE_NEW_LEVEL +//! Creates a new level instance of Sentry. This row should be inserted before messages using in the method. +#define OCCT_ADD_MESSAGE_LEVEL_SENTRY(theMessage) \ + Message_Level aLevel; \ + Message::DefaultMessenger() << theMessage << "" << Message_EndLine; + +#endif // _Message_Level_HeaderFile diff --git a/src/Message/Message_Messenger.cxx b/src/Message/Message_Messenger.cxx index 1e44c8b220..b6c5f8ccd8 100644 --- a/src/Message/Message_Messenger.cxx +++ b/src/Message/Message_Messenger.cxx @@ -18,6 +18,8 @@ #include #include +#include + IMPLEMENT_STANDARD_RTTIEXT(Message_Messenger,Standard_Transient) //======================================================================= @@ -25,6 +27,7 @@ IMPLEMENT_STANDARD_RTTIEXT(Message_Messenger,Standard_Transient) //purpose : //======================================================================= Message_Messenger::Message_Messenger () +: myOutputGravity (Message_Info) { AddPrinter ( new Message_PrinterOStream ); } @@ -35,6 +38,7 @@ Message_Messenger::Message_Messenger () //======================================================================= Message_Messenger::Message_Messenger (const Handle(Message_Printer)& thePrinter) +: myOutputGravity (Message_Info) { AddPrinter (thePrinter); } @@ -60,6 +64,23 @@ Standard_Boolean Message_Messenger::AddPrinter (const Handle(Message_Printer)& t return Standard_True; } +//======================================================================= +//function : HasPrinters +//purpose : +//======================================================================= +Standard_Boolean Message_Messenger::HasPrinter (const Handle(Standard_Type)& theType) +{ + for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More();) + { + const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); + if (!aPrinter.IsNull() && aPrinter->IsKind (theType)) + { + return Standard_True; + } + } + return Standard_False; +} + //======================================================================= //function : RemovePrinter //purpose : @@ -114,6 +135,9 @@ void Message_Messenger::Send (const Standard_CString theString, const Message_Gravity theGravity, const Standard_Boolean putEndl) const { + if (TraceLevel() == 0) + return; + for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) { const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); @@ -133,6 +157,8 @@ void Message_Messenger::Send (const TCollection_AsciiString& theString, const Message_Gravity theGravity, const Standard_Boolean putEndl) const { + if (TraceLevel() == 0) + return; for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) { const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); @@ -152,6 +178,8 @@ void Message_Messenger::Send (const TCollection_ExtendedString& theString, const Message_Gravity theGravity, const Standard_Boolean putEndl) const { + if (TraceLevel() == 0) + return; for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) { const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); @@ -161,3 +189,65 @@ void Message_Messenger::Send (const TCollection_ExtendedString& theString, } } } + +//======================================================================= +//function : Send +//purpose : +//======================================================================= + +void Message_Messenger::Send (const Standard_SStream& theStream, + const Message_Gravity theGravity, + const Standard_Boolean putEndl) const +{ + if (TraceLevel() == 0) + return; + for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) + { + const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); + if (!aPrinter.IsNull()) + { + aPrinter->Send (theStream, theGravity, putEndl); + } + } +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= + +void Message_Messenger::Send (const Handle(Standard_Transient)& theObject, + const Message_Gravity theGravity, + const Standard_Boolean putEndl) const +{ + if (TraceLevel() == 0) + return; + for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) + { + const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); + if (!aPrinter.IsNull()) + { + aPrinter->Send (theObject, theGravity, putEndl); + } + } +} + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Message_Messenger::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) + + for (Message_SequenceOfPrinters::Iterator aPrinterIter (myPrinters); aPrinterIter.More(); aPrinterIter.Next()) + { + const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); + if (aPrinter.IsNull()) + continue; + OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aPrinter.get()) + } + + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myOutputGravity) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTraceLevel) +} diff --git a/src/Message/Message_Messenger.hxx b/src/Message/Message_Messenger.hxx index 675fba3436..27ffc1c071 100644 --- a/src/Message/Message_Messenger.hxx +++ b/src/Message/Message_Messenger.hxx @@ -16,6 +16,7 @@ #ifndef _Message_Messenger_HeaderFile #define _Message_Messenger_HeaderFile +#include #include #include #include @@ -67,6 +68,9 @@ public: //! Returns True if printer has been added. Standard_EXPORT Standard_Boolean AddPrinter (const Handle(Message_Printer)& thePrinter); + //! Returns true if messenger printers contain a printer of specified type (including derived classes) + Standard_EXPORT Standard_Boolean HasPrinter (const Handle(Standard_Type)& theType); + //! Removes specified printer from the messenger. //! Returns True if this printer has been found in the list //! and removed. @@ -76,7 +80,7 @@ public: //! from the messenger. //! Returns number of removed printers. Standard_EXPORT Standard_Integer RemovePrinters (const Handle(Standard_Type)& theType); - + //! Returns current sequence of printers const Message_SequenceOfPrinters& Printers() const { return myPrinters; } @@ -84,6 +88,22 @@ public: //! The sequence can be modified. Message_SequenceOfPrinters& ChangePrinters() { return myPrinters; } + //! Returns the output gavity used in operator << + Message_Gravity OuputGravity() const { return myOutputGravity; } + + //! Sets the output gavity used in operator << + void SetOuputGravity (const Message_Gravity theValue) { myOutputGravity = theValue; } + + //! Sets trace level used for outputting messages + //! - 0: no trace at all + //! - 1/2/3: messages of the first level are processed + //! - -1: all messages are processed + //! Default is 0 : no messages are processed + void SetTraceLevel (const Standard_Integer theTraceLevel) { myTraceLevel = theTraceLevel; } + + //! Returns trace level used for outputting messages. + Standard_Integer TraceLevel() const { return myTraceLevel; } + //! Dispatch a message to all the printers in the list. //! Three versions of string representations are accepted for //! convenience, by default all are converted to ExtendedString. @@ -98,17 +118,27 @@ public: //! See above Standard_EXPORT void Send (const TCollection_ExtendedString& theString, const Message_Gravity theGravity = Message_Warning, const Standard_Boolean putEndl = Standard_True) const; + //! See above + Standard_EXPORT void Send (const Standard_SStream& theStream, const Message_Gravity theGravity = Message_Warning, const Standard_Boolean putEndl = Standard_True) const; + + //! See above + Standard_EXPORT void Send (const Handle(Standard_Transient)& theObject, const Message_Gravity theGravity = Message_Warning, const Standard_Boolean putEndl = Standard_True) const; + + //! Dumps the content of me into the stream + Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; + private: Message_SequenceOfPrinters myPrinters; - + Message_Gravity myOutputGravity; //!< gravity used in operator << + Standard_Integer myTraceLevel; //!< leel of processed messages }; // CString inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const Standard_CString theStr) { - theMessenger->Send (theStr, Message_Info, Standard_False); + theMessenger->Send (theStr, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -116,7 +146,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const TCollection_AsciiString& theStr) { - theMessenger->Send (theStr, Message_Info, Standard_False); + theMessenger->Send (theStr, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -124,7 +154,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const Handle(TCollection_HAsciiString)& theStr) { - theMessenger->Send (theStr->String(), Message_Info, Standard_False); + theMessenger->Send (theStr->String(), theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -132,7 +162,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const TCollection_ExtendedString& theStr) { - theMessenger->Send (theStr, Message_Info, Standard_False); + theMessenger->Send (theStr, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -140,7 +170,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const Handle(TCollection_HExtendedString)& theStr) { - theMessenger->Send (theStr->String(), Message_Info, Standard_False); + theMessenger->Send (theStr->String(), theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -149,7 +179,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng const Standard_Integer theVal) { TCollection_AsciiString aStr (theVal); - theMessenger->Send (aStr, Message_Info, Standard_False); + theMessenger->Send (aStr, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -158,7 +188,7 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng const Standard_Real theVal) { TCollection_AsciiString aStr (theVal); - theMessenger->Send (aStr, Message_Info, Standard_False); + theMessenger->Send (aStr, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -166,7 +196,15 @@ inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messeng inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, const Standard_SStream& theStream) { - theMessenger->Send (theStream.str().c_str(), Message_Info, Standard_False); + theMessenger->Send (theStream, theMessenger->OuputGravity(), Standard_False); + return theMessenger; +} + +// AsciiString +inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, + const Handle(Standard_Transient)& theObject) +{ + theMessenger->Send (theObject, theMessenger->OuputGravity(), Standard_False); return theMessenger; } @@ -181,8 +219,31 @@ inline const Handle(Message_Messenger)& // Message_EndLine inline const Handle(Message_Messenger)& Message_EndLine (const Handle(Message_Messenger)& theMessenger) { - theMessenger->Send ("", Message_Info, Standard_True); + theMessenger->Send ("", theMessenger->OuputGravity(), Standard_True); return theMessenger; } +//! @def OCCT_SEND_DUMPJSON +//! Append into messenger result of DumpJson for the field +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own DumpJson implementation. +#define OCCT_SEND_DUMPJSON(theField) \ +{ \ + if ((void*)(theField) != NULL) \ + { \ + Standard_SStream aFieldStream; \ + (theField)->DumpJson (aFieldStream, Message::DefaultMessenger()->TraceLevel()); \ + Message::DefaultMessenger() << aFieldStream; \ + } \ +} + +//! @def OCCT_SEND_MESSAGE +//! Append into messenger result of DumpJson for the field +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own DumpJson implementation. +#define OCCT_SEND_MESSAGE(theMessage) \ +{ \ + Message::DefaultMessenger() << theMessage << "" << Message_EndLine; \ +} + #endif // _Message_Messenger_HeaderFile diff --git a/src/Message/Message_MetricType.hxx b/src/Message/Message_MetricType.hxx new file mode 100644 index 0000000000..a99db83399 --- /dev/null +++ b/src/Message/Message_MetricType.hxx @@ -0,0 +1,32 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_MetricType_HeaderFile +#define _Message_MetricType_HeaderFile + +//! Specifies kind of report information to collect +enum Message_MetricType +{ + Message_MetricType_None, //!< no computation + Message_MetricType_UserTimeCPU, //!< the current CPU user time in seconds + Message_MetricType_SystemTimeInfo, //!< the current CPU system time in seconds + Message_MetricType_MemPrivate, //!< OSD_MemInfo::MemPrivate + Message_MetricType_MemVirtual, //!< OSD_MemInfo::MemVirtual + Message_MetricType_MemWorkingSet, //!< OSD_MemInfo::MemWorkingSet + Message_MetricType_MemWorkingSetPeak, //!< OSD_MemInfo::MemWorkingSetPeak + Message_MetricType_MemSwapUsage, //!< OSD_MemInfo::MemSwapUsage + Message_MetricType_MemSwapUsagePeak, //!< OSD_MemInfo::MemSwapUsagePeak + Message_MetricType_MemHeapUsage //!< OSD_MemInfo::MemHeapUsage +}; + +#endif // _Message_MetricType_HeaderFile diff --git a/src/Message/Message_Printer.cxx b/src/Message/Message_Printer.cxx index 8ed2b87e6a..85c18291b8 100644 --- a/src/Message/Message_Printer.cxx +++ b/src/Message/Message_Printer.cxx @@ -15,6 +15,7 @@ #include +#include #include #include @@ -58,3 +59,46 @@ void Message_Printer::Send (const TCollection_AsciiString& theString, Send (TCollection_ExtendedString (theString), theGravity, theToOutEol); } } + +//======================================================================= +//function : Send +//purpose : +//======================================================================= + +void Message_Printer::Send (const Standard_SStream& theStream, + const Message_Gravity theGravity, + const Standard_Boolean theToOutEol) const +{ + if (theGravity >= myTraceLevel) + { + Send (TCollection_ExtendedString (theStream.str().c_str()), theGravity, theToOutEol); + } +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void Message_Printer::Send (const Handle(Standard_Transient)& theObject, + const Message_Gravity theGravity, + const Standard_Boolean theToOutEol) const +{ + if (theObject.IsNull()) + return; + + if (theGravity >= myTraceLevel) + { + TCollection_ExtendedString aString = TCollection_ExtendedString (theObject->DynamicType()->Name()) + + ": " + Standard_Dump::GetPointerInfo (theObject); + Send (aString, theGravity, theToOutEol); + } +} + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Message_Printer::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) +} diff --git a/src/Message/Message_Printer.hxx b/src/Message/Message_Printer.hxx index e7e70ddfbd..965454998d 100644 --- a/src/Message/Message_Printer.hxx +++ b/src/Message/Message_Printer.hxx @@ -23,6 +23,8 @@ #include #include #include +#include + class TCollection_ExtendedString; class TCollection_AsciiString; @@ -62,6 +64,21 @@ public: //! Default implementation calls first method Send(). Standard_EXPORT virtual void Send (const TCollection_AsciiString& theString, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const; + //! Send a string message with specified trace level. + //! Stream is converted to string value. + //! The parameter theToPutEol specified whether end-of-line should be added to the end of the message. + //! Default implementation calls first method Send(). + Standard_EXPORT virtual void Send (const Standard_SStream& theStream, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const; + + //! Send a string message with specified trace level. + //! The object is converted to string in format: : . + //! The parameter theToPutEol specified whether end-of-line should be added to the end of the message. + //! Default implementation calls first method Send(). + Standard_EXPORT virtual void Send (const Handle(Standard_Transient)& theObject, const Message_Gravity theGravity, const Standard_Boolean theToPutEol) const; + + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; + protected: //! Empty constructor with Message_Info trace level diff --git a/src/Message/Message_PrinterOStream.cxx b/src/Message/Message_PrinterOStream.cxx index ce7bb1ec35..330c5f90b8 100644 --- a/src/Message/Message_PrinterOStream.cxx +++ b/src/Message/Message_PrinterOStream.cxx @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -289,3 +290,12 @@ void Message_PrinterOStream::SetConsoleTextColor (Standard_OStream* theOStream, *theOStream << aCode; #endif } + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Message_PrinterOStream::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) +} diff --git a/src/Message/Message_PrinterOStream.hxx b/src/Message/Message_PrinterOStream.hxx index 163a2ac0ce..fe2b2055bb 100644 --- a/src/Message/Message_PrinterOStream.hxx +++ b/src/Message/Message_PrinterOStream.hxx @@ -97,6 +97,9 @@ public: //! option is set, else replaced by symbols '?' Standard_EXPORT virtual void Send (const TCollection_ExtendedString& theString, const Message_Gravity theGravity, const Standard_Boolean putEndl = Standard_True) const Standard_OVERRIDE; + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; + private: Standard_Address myStream; diff --git a/src/Message/Message_PrinterSystemLog.cxx b/src/Message/Message_PrinterSystemLog.cxx index b87d4b410d..6668b0aa26 100644 --- a/src/Message/Message_PrinterSystemLog.cxx +++ b/src/Message/Message_PrinterSystemLog.cxx @@ -17,6 +17,7 @@ #include +#include #include #if defined(OCCT_UWP) @@ -239,3 +240,12 @@ void Message_PrinterSystemLog::Send (const TCollection_ExtendedString& theString Send (TCollection_AsciiString (theString), theGravity, true); #endif } + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Message_PrinterSystemLog::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) +} diff --git a/src/Message/Message_PrinterSystemLog.hxx b/src/Message/Message_PrinterSystemLog.hxx index 309a48a250..68a0b32ea9 100644 --- a/src/Message/Message_PrinterSystemLog.hxx +++ b/src/Message/Message_PrinterSystemLog.hxx @@ -51,6 +51,9 @@ public: const Message_Gravity theGravity, const Standard_Boolean theToPutEndl) const Standard_OVERRIDE; + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; + private: TCollection_AsciiString myEventSourceName; diff --git a/src/Message/Message_PrinterToReport.cxx b/src/Message/Message_PrinterToReport.cxx new file mode 100644 index 0000000000..bdd35f2686 --- /dev/null +++ b/src/Message/Message_PrinterToReport.cxx @@ -0,0 +1,128 @@ +// Created on: 2001-01-06 +// Created by: OCC Team +// 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 + +IMPLEMENT_STANDARD_RTTIEXT(Message_PrinterToReport, Message_Printer) + +//======================================================================= +//function : Report +//purpose : +//======================================================================= +const Handle(Message_Report)& Message_PrinterToReport::Report() const +{ + if (!myReport.IsNull()) + return myReport; + + return Message::DefaultReport (Standard_True); +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void Message_PrinterToReport::Send (const TCollection_ExtendedString& theString, + const Message_Gravity theGravity, + const Standard_Boolean putEndl) const +{ + TCollection_AsciiString aString (theString/*, myUseUtf8 ? Standard_Character(0) : '?'*/); + + if (putEndl) + { + if (myValue.IsEmpty()) + return; + + const Handle(Message_Report)& aReport = Report(); + if (!aReport->ActiveMetrics().IsEmpty()) + { + sendMetricAlert (myValue, theGravity); + return; + } + Message_AlertExtended::AddAlert (aReport, new Message_Attribute (myValue), theGravity); + ((Message_PrinterToReport*)this)->Clear(); + return; + } + ((Message_PrinterToReport*)this)->myValue += aString; +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void Message_PrinterToReport::Send (const Standard_SStream& theStream, + const Message_Gravity theGravity, + const Standard_Boolean /*putEndl*/) const +{ + const Handle(Message_Report)& aReport = Report(); + if (!aReport->ActiveMetrics().IsEmpty()) + { + sendMetricAlert (myValue, theGravity); + return; + } + Message_AlertExtended::AddAlert (aReport, new Message_AttributeStream (theStream, myValue), theGravity); + ((Message_PrinterToReport*)this)->Clear(); + + return; +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void Message_PrinterToReport::Send (const Handle(Standard_Transient)& theObject, + const Message_Gravity theGravity, + const Standard_Boolean /*putEndl*/) const +{ + const Handle(Message_Report)& aReport = Report(); + if (!aReport->ActiveMetrics().IsEmpty()) + { + sendMetricAlert (myValue, theGravity); + return; + } + + Message_AlertExtended::AddAlert (aReport, new Message_AttributeObject (theObject, myValue), theGravity); + ((Message_PrinterToReport*)this)->Clear(); +} + +//======================================================================= +//function : sendMetricAlert +//purpose : +//======================================================================= +void Message_PrinterToReport::sendMetricAlert (const TCollection_AsciiString theValue, + const Message_Gravity theGravity) const +{ + Message_AlertExtended::AddAlert (Report(), new Message_AttributeMeter (theValue), theGravity); + ((Message_PrinterToReport*)this)->Clear(); +} + +//======================================================================= +//function : DumpJson +//purpose : +//======================================================================= +void Message_PrinterToReport::DumpJson (Standard_OStream& theOStream, Standard_Integer) const +{ + OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream) +} diff --git a/src/Message/Message_PrinterToReport.hxx b/src/Message/Message_PrinterToReport.hxx new file mode 100644 index 0000000000..27d45ae1f4 --- /dev/null +++ b/src/Message/Message_PrinterToReport.hxx @@ -0,0 +1,88 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_PrinterToReport_HeaderFile +#define _Message_PrinterToReport_HeaderFile + +#include +#include +#include +#include + +class Message_Report; + +class Message_PrinterToReport; +DEFINE_STANDARD_HANDLE(Message_PrinterToReport, Message_Printer) + +//! Implementation of a message printer associated with Message_Report +//! Send will create a new alert of the report. If string is sent, an alert is created by Eol only. +//! The alerts are sent into set report or default report of Message. +class Message_PrinterToReport : public Message_Printer +{ + DEFINE_STANDARD_RTTIEXT(Message_PrinterToReport, Message_Printer) + +public: + //! Create printer for redirecting messages into report. + Message_PrinterToReport() {} + + ~Message_PrinterToReport() {} + + //! Returns the current or default report + Standard_EXPORT const Handle(Message_Report)& Report() const; + + //! Sets the printer report + //! @param theReport report for messages processing, if NULL, the default report is used + Standard_EXPORT void SetReport (const Handle(Message_Report)& theReport) { myReport = theReport; } + + //!< Returns the first sent value + const TCollection_AsciiString& Value() { return myValue; } + + //! Clears current values + Standard_EXPORT void Clear() { myValue.Clear(); } + + //! Appends a new alert into message report if Endl is false or send a new extended alert with attribute on value + //! Use Message_EndLine to finalize the current alert + Standard_EXPORT virtual void Send (const TCollection_ExtendedString& theString, + const Message_Gravity theGravity, + const Standard_Boolean putEndl = Standard_True) const Standard_OVERRIDE; + + //! Send a string message with specified trace level. + //! Stream is converted to string value. + //! The parameter theToPutEol specified whether end-of-line should be added to the end of the message. + //! Default implementation calls first method Send(). + Standard_EXPORT virtual void Send (const Standard_SStream& theStream, + const Message_Gravity theGravity, + const Standard_Boolean theToPutEol) const Standard_OVERRIDE; + + //! Send a string message with specified trace level. + //! The object is converted to string in format: : . + //! The parameter theToPutEol specified whether end-of-line should be added to the end of the message. + //! Default implementation calls first method Send(). + Standard_EXPORT virtual void Send (const Handle(Standard_Transient)& theObject, + const Message_Gravity theGravity, + const Standard_Boolean theToPutEol) const Standard_OVERRIDE; + //! Dumps the content of me into the stream + Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; + +protected: + + //! Send an alert with metrics active in the current report + Standard_EXPORT void sendMetricAlert (const TCollection_AsciiString theValue, + const Message_Gravity theGravity) const; + +private: + Handle(Message_Report) myReport; //!< the report for sending alerts + TCollection_AsciiString myValue; //!< the union of sent strings until Eol +}; + +#endif // _Message_PrinterToReport_HeaderFile diff --git a/src/Message/Message_Report.cxx b/src/Message/Message_Report.cxx index 07324599d2..e094b172b2 100644 --- a/src/Message/Message_Report.cxx +++ b/src/Message/Message_Report.cxx @@ -14,9 +14,18 @@ // commercial license or contractual agreement. #include + +#include +#include +#include #include #include +#include +#include + #include +#include +#include IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) @@ -26,6 +35,7 @@ IMPLEMENT_STANDARD_RTTIEXT(Message_Report,Standard_Transient) //======================================================================= Message_Report::Message_Report () +: myLimit (-1), myWriteFileOnEachAlert (Standard_False) { } @@ -36,28 +46,54 @@ Message_Report::Message_Report () void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_Alert)& theAlert) { - 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 - Message_ListOfAlert &aList = myAlerts[theGravity]; - if (theAlert->SupportsMerge() && ! aList.IsEmpty()) + // alerts of the top level + if (myAlertLevels.IsEmpty()) { - // merge is performed only for alerts of exactly same type - const Handle(Standard_Type)& aType = theAlert->DynamicType(); - for (Message_ListOfAlert::Iterator anIt(aList); anIt.More(); anIt.Next()) + Handle (Message_CompositeAlerts) aCompositeAlert = compositeAlerts (Standard_True); + if (aCompositeAlert->AddAlert (theGravity, theAlert)) { - // if merged successfully, just return - if (aType == anIt.Value()->DynamicType() && theAlert->Merge (anIt.Value())) - return; + writeReport(); + return; } + // remove alerts under the report only + const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts (theGravity); + if (anAlerts.Extent() > myLimit) + { + aCompositeAlert->RemoveAlert (theGravity, anAlerts.First()); + } + return; + } + + // if there are some levels of alerts + // iterate by already recorded alerts and try to merge new one with one of those + Message_Level* aLevel = myAlertLevels.Last(); + + // level has root alert, the new alert will be placed below the root + if (!aLevel->RootAlert().IsNull()) + { + aLevel->AddAlert (theGravity, theAlert); + writeReport(); + return; } - // if not merged, just add to the list - aList.Append (theAlert); + Handle(Message_AlertExtended) anAlert = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlert.IsNull()) + return; + // place new alert as a root of the level, after place the level alert below the report or + // below the previous level + aLevel->SetRootAlert (anAlert); + + if (myAlertLevels.Size() == 1) // this is the first level, so root alert should be pushed in the report composite of alerts + compositeAlerts (Standard_True)->AddAlert (theGravity, theAlert); + else + { + // root alert of next levels should be pushed under the previous level + Message_Level* aPrevLevel = myAlertLevels.Value (myAlertLevels.Size() - 1); // previous level + aPrevLevel->AddLevelAlert (theGravity, theAlert); + } + writeReport(); } //======================================================================= @@ -68,9 +104,10 @@ void Message_Report::AddAlert (Message_Gravity theGravity, const Handle(Message_ const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity) const { static const Message_ListOfAlert anEmptyList; - Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), - "Requesting alerts for gravity not in valid range", anEmptyList); - return myAlerts[theGravity]; + if (myCompositAlerts.IsNull()) + return anEmptyList; + + return myCompositAlerts->Alerts (theGravity); } //======================================================================= @@ -80,9 +117,9 @@ const Message_ListOfAlert& Message_Report::GetAlerts (Message_Gravity theGravity Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType) { - for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) { - if (HasAlert (theType, (Message_Gravity)iGravity)) + if (HasAlert (theType, (Message_Gravity)aGravIter)) return Standard_True; } return Standard_False; @@ -95,26 +132,88 @@ Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType) Standard_Boolean Message_Report::HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity) { - Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), - "Requesting alerts for gravity not in valid range", Standard_False); - for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next()) + if (compositeAlerts().IsNull()) + return Standard_False; + + return compositeAlerts()->HasAlert (theType, theGravity); +} + +//======================================================================= +//function : IsActiveInMessenger +//purpose : +//======================================================================= + +Standard_Boolean Message_Report::IsActiveInMessenger (const Handle(Message_Messenger)& theMessenger) const +{ + Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger; + for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next()) { - if (anIt.Value()->IsInstance(theType)) + if (anIterator.Value()->IsKind(STANDARD_TYPE (Message_PrinterToReport)) && + Handle(Message_PrinterToReport)::DownCast (anIterator.Value())->Report() == this) return Standard_True; } return Standard_False; } //======================================================================= -//function : Clear +//function : ActivateInMessenger //purpose : //======================================================================= -void Message_Report::Clear () +void Message_Report::ActivateInMessenger (const Standard_Boolean toActivate, + const Handle(Message_Messenger)& theMessenger) const { - for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) + if (toActivate == IsActiveInMessenger()) + return; + + Handle(Message_Messenger) aMessenger = theMessenger.IsNull() ? Message::DefaultMessenger() : theMessenger; + if (toActivate) + { + Handle (Message_PrinterToReport) aPrinterToReport = new Message_PrinterToReport(); + aPrinterToReport->SetReport (this); + aMessenger->AddPrinter (aPrinterToReport); + } + else // deactivate { - myAlerts[i].Clear(); + Message_SequenceOfPrinters aPrintersToRemove; + for (Message_SequenceOfPrinters::Iterator anIterator (aMessenger->Printers()); anIterator.More(); anIterator.Next()) + { + const Handle(Message_Printer) aPrinter = anIterator.Value(); + if (aPrinter->IsKind(STANDARD_TYPE (Message_PrinterToReport)) && + Handle(Message_PrinterToReport)::DownCast (aPrinter)->Report() == this) + aPrintersToRemove.Append (aPrinter); + } + for (Message_SequenceOfPrinters::Iterator anIterator (aPrintersToRemove); anIterator.More(); anIterator.Next()) + { + aMessenger->RemovePrinter (anIterator.Value()); + } + } +} + +//======================================================================= +//function : AddLevel +//purpose : +//======================================================================= + +void Message_Report::AddLevel (Message_Level* theLevel) +{ + myAlertLevels.Append (theLevel); +} + +//======================================================================= +//function : RemoveLevel +//purpose : +//======================================================================= + +void Message_Report::RemoveLevel (Message_Level* theLevel) +{ + for (int aLevelIndex = myAlertLevels.Size(); aLevelIndex >= 1; aLevelIndex--) + { + Message_Level* aLevel = myAlertLevels.Value (aLevelIndex); + myAlertLevels.Remove (aLevelIndex); + + if (aLevel == theLevel) + return; } } @@ -123,11 +222,27 @@ void Message_Report::Clear () //purpose : //======================================================================= +void Message_Report::Clear() +{ + if (compositeAlerts().IsNull()) + return; + + compositeAlerts()->Clear(); + myAlertLevels.Clear(); +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= + void Message_Report::Clear (Message_Gravity theGravity) { - Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), - "Requesting alerts for gravity not in valid range", ); - myAlerts[theGravity].Clear(); + if (compositeAlerts().IsNull()) + return; + + compositeAlerts()->Clear (theGravity); + myAlertLevels.Clear(); } //======================================================================= @@ -137,20 +252,28 @@ void Message_Report::Clear (Message_Gravity theGravity) void Message_Report::Clear (const Handle(Standard_Type)& theType) { - for (unsigned int i = 0; i < sizeof(myAlerts)/sizeof(myAlerts[0]); ++i) - { - for (Message_ListOfAlert::Iterator anIt (myAlerts[i]); anIt.More(); ) - { - if (anIt.Value().IsNull() || anIt.Value()->IsInstance (theType)) - { - myAlerts[i].Remove (anIt); - } - else - { - anIt.More(); - } - } - } + if (compositeAlerts().IsNull()) + return; + + compositeAlerts()->Clear (theType); + myAlertLevels.Clear(); +} + +//======================================================================= +//function : SetActiveMetric +//purpose : +//======================================================================= + +void Message_Report::SetActiveMetric (const Message_MetricType theMetricType, + const Standard_Boolean theActivate) +{ + if (theActivate == myActiveMetrics.Contains (theMetricType)) + return; + + if (theActivate) + myActiveMetrics.Add (theMetricType); + else + myActiveMetrics.Remove (theMetricType); } //======================================================================= @@ -160,9 +283,9 @@ void Message_Report::Clear (const Handle(Standard_Type)& theType) void Message_Report::Dump (Standard_OStream& theOS) { - for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) { - Dump (theOS, (Message_Gravity)iGravity); + Dump (theOS, (Message_Gravity)aGravIter); } } @@ -173,19 +296,13 @@ void Message_Report::Dump (Standard_OStream& theOS) void Message_Report::Dump (Standard_OStream& theOS, Message_Gravity theGravity) { - Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), - "Requesting alerts for gravity not in valid range", ); + if (compositeAlerts().IsNull()) + return; - // report each type of warning only once - NCollection_Map aPassedAlerts; - for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next()) - { - if (aPassedAlerts.Add (anIt.Value()->DynamicType())) - { - Message_Msg aMsg (anIt.Value()->GetMessageKey()); - theOS << aMsg.Original() << std::endl; - } - } + if (compositeAlerts().IsNull()) + return; + + dumpMessages (theOS, theGravity, compositeAlerts()); } //======================================================================= @@ -195,9 +312,9 @@ void Message_Report::Dump (Standard_OStream& theOS, Message_Gravity theGravity) void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger) { - for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) { - SendMessages (theMessenger, (Message_Gravity)iGravity); + SendMessages (theMessenger, (Message_Gravity)aGravIter); } } @@ -208,19 +325,10 @@ void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity) { - Standard_ASSERT_RETURN (theGravity >= 0 && size_t(theGravity) < sizeof(myAlerts)/sizeof(myAlerts[0]), - "Requesting alerts for gravity not in valid range", ); + if (compositeAlerts().IsNull()) + return; - // report each type of warning only once - NCollection_Map aPassedAlerts; - for (Message_ListOfAlert::Iterator anIt (myAlerts[theGravity]); anIt.More(); anIt.Next()) - { - if (aPassedAlerts.Add (anIt.Value()->DynamicType())) - { - Message_Msg aMsg (anIt.Value()->GetMessageKey()); - theMessenger->Send (aMsg, theGravity); - } - } + sendMessages (theMessenger, theGravity, compositeAlerts()); } //======================================================================= @@ -230,9 +338,9 @@ void Message_Report::SendMessages (const Handle(Message_Messenger)& theMessenger void Message_Report::Merge (const Handle(Message_Report)& theOther) { - for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + for (int aGravIter = Message_Trace; aGravIter <= Message_Fail; ++aGravIter) { - Merge (theOther, (Message_Gravity)iGravity); + Merge (theOther, (Message_Gravity)aGravIter); } } @@ -248,3 +356,90 @@ void Message_Report::Merge (const Handle(Message_Report)& theOther, Message_Grav AddAlert (theGravity, anIt.Value()); } } + +//======================================================================= +//function : CompositeAlerts +//purpose : +//======================================================================= +const Handle(Message_CompositeAlerts)& Message_Report::compositeAlerts (const Standard_Boolean isCreate) +{ + if (myCompositAlerts.IsNull() && isCreate) + myCompositAlerts = new Message_CompositeAlerts(); + + return myCompositAlerts; +} + +//======================================================================= +//function : sendMessages +//purpose : +//======================================================================= + +void Message_Report::sendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity, + const Handle(Message_CompositeAlerts)& theCompositeAlert) +{ + if (theCompositeAlert.IsNull()) + return; + + const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity); + // report each type of warning only once + //NCollection_Map aPassedAlerts; + for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next()) + { + //if (aPassedAlerts.Add (anIt.Value()->DynamicType())) + { + //Message_Msg aMsg (anIt.Value()->GetMessageKey()); + //theMessenger->Send (aMsg, theGravity); + theMessenger->Send (anIt.Value()->GetMessageKey(), theGravity); + } + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value()); + if (anExtendedAlert.IsNull()) + continue; + + Handle(Message_CompositeAlerts) aCompositeAlerts = anExtendedAlert->CompositeAlerts(); + if (aCompositeAlerts.IsNull()) + continue; + + sendMessages (theMessenger, theGravity, aCompositeAlerts); + } +} + +//======================================================================= +//function : dumpMessages +//purpose : +//======================================================================= +void Message_Report::dumpMessages (Standard_OStream& theOS, Message_Gravity theGravity, + const Handle(Message_CompositeAlerts)& theCompositeAlert) +{ + if (theCompositeAlert.IsNull()) + return; + + const Message_ListOfAlert& anAlerts = theCompositeAlert->Alerts (theGravity); + // report each type of war++ning only once + //NCollection_Map aPassedAlerts; + for (Message_ListOfAlert::Iterator anIt (anAlerts); anIt.More(); anIt.Next()) + { + //if (aPassedAlerts.Add (anIt.Value()->DynamicType())) + { + //Message_Msg aMsg (anIt.Value()->GetMessageKey()); + //theOS << aMsg.Original() << std::endl; + theOS << anIt.Value()->GetMessageKey() << std::endl; + } + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (anIt.Value()); + if (anExtendedAlert.IsNull()) + continue; + dumpMessages (theOS, theGravity, anExtendedAlert->CompositeAlerts()); + } +} + +//======================================================================= +//function : writeReport +//purpose : +//======================================================================= +void Message_Report::writeReport() +{ + if (myReportWriter.IsNull() || !myWriteFileOnEachAlert) + return; + + myReportWriter->ExportReport (this); +} diff --git a/src/Message/Message_Report.hxx b/src/Message/Message_Report.hxx index 8440ba8149..be35d38a9e 100644 --- a/src/Message/Message_Report.hxx +++ b/src/Message/Message_Report.hxx @@ -17,13 +17,19 @@ #define _Message_Report_HeaderFile #include +#include #include +#include +#include +#include #include +class Message_CompositeAlerts; class Message_Messenger; - class Message_Report; -DEFINE_STANDARD_HANDLE(Message_Report, MMgt_TShared) +class Message_ReportWriter; + +DEFINE_STANDARD_HANDLE(Message_Report, Standard_Transient) //! Container for alert messages, sorted according to their gravity. //! @@ -46,6 +52,8 @@ DEFINE_STANDARD_HANDLE(Message_Report, MMgt_TShared) //! Dump() or in more advanced way, by iterating over lists returned by GetAlerts() //! //! - Report can be cleared by methods Clear() (usually after reporting) +//! +//! Message_PrinterToReport is a printer in Messenger to convert data sent to messenger into report class Message_Report : public Standard_Transient { @@ -67,6 +75,22 @@ public: //! Returns true if specific type of alert is recorded with specified gravity Standard_EXPORT Standard_Boolean HasAlert (const Handle(Standard_Type)& theType, Message_Gravity theGravity); + //! Returns true if a report printer for the current report is registered in the messenger + // @param theMessenger the messenger. If it's NULL, the default messenger is used + Standard_EXPORT Standard_Boolean IsActiveInMessenger (const Handle(Message_Messenger)& theMessenger = NULL) const; + + //! Creates an instance of Message_PrinterToReport with the current report and register it in messenger + //! @param toActivate if true, activated else deactivated + // @param theMessenger the messenger. If it's NULL, the default messenger is used + Standard_EXPORT void ActivateInMessenger (const Standard_Boolean toActivate, const Handle(Message_Messenger)& theMessenger = NULL) const; + + //! Add new level of alerts + //! @param theLevel a level + Standard_EXPORT void AddLevel (Message_Level* theLevel); + + //! Remove level of alerts + Standard_EXPORT void RemoveLevel (Message_Level* theLevel); + //! Clears all collected alerts Standard_EXPORT void Clear (); @@ -76,6 +100,41 @@ public: //! Clears collected alerts with specified type Standard_EXPORT void Clear (const Handle(Standard_Type)& theType); + //! Returns computed metrics when alerts are performed + const NCollection_Map& ActiveMetrics() const { return myActiveMetrics; } + + //! Sets metrics to compute when alerts are performed + //! @param theMetrics container of metrics + Standard_EXPORT void SetActiveMetric (const Message_MetricType theMetricType, const Standard_Boolean theActivate); + + //! Removes all activated metrics + void ClearMetrics() { myActiveMetrics.Clear(); } + + //! Returns maximum number of collecting alerts. If the limit is achieved, + //! first alert is removed, the new alert is added in the container. + //! @return the limit value + Standard_Integer Limit() const { return myLimit; } + + //! Sets maximum number of collecting alerts. + //! @param theLimit limit value + void SetLimit(const Standard_Integer theLimit) { myLimit = theLimit; } + + //! Returns the message report writer + //! @return theWriter a writer + const Handle(Message_ReportWriter)& MessageWriter() const { return myReportWriter; } + + //! Sets the message report writer + //! @param theWriter a writer + void SetMessageWriter (const Handle(Message_ReportWriter)& theWriter) { myReportWriter = theWriter; } + + //! Returns true if the report is written into an output file by a new alert adding + //! @return the boolean flag + Standard_Boolean WriteFileOnEachAlert() const { return myWriteFileOnEachAlert; } + + //! Sets state if the report should be written into an output file by a new alert adding + //! @param theToWrite boolean flag + void SetWriteFileOnEachAlert (const Standard_Boolean theToWrite) { myWriteFileOnEachAlert = theToWrite; } + //! Dumps all collected alerts to stream Standard_EXPORT void Dump (Standard_OStream& theOS); @@ -94,15 +153,36 @@ public: //! Merges alerts with specified gravity from theOther report into this Standard_EXPORT void Merge (const Handle(Message_Report)& theOther, Message_Gravity theGravity); - // OCCT RTTI DEFINE_STANDARD_RTTIEXT(Message_Report,Standard_Transient) +protected: + //! Returns class provided hierarchy of alerts if created or create if the parameter is true + //! @param isCreate if composite alert has not been created for this alert, it should be created + //! @return instance or NULL + Standard_EXPORT const Handle(Message_CompositeAlerts)& compositeAlerts (const Standard_Boolean isCreate = Standard_False); + + //! Sends alerts to messenger + Standard_EXPORT void sendMessages (const Handle(Message_Messenger)& theMessenger, Message_Gravity theGravity, + const Handle(Message_CompositeAlerts)& theCompositeAlert); + + //! Dumps collected alerts with specified gravity to stream + Standard_EXPORT void dumpMessages (Standard_OStream& theOS, Message_Gravity theGravity, + const Handle(Message_CompositeAlerts)& theCompositeAlert); + + //! Write message report if writer is not null and WriteFileOnEachAlert is true + void writeReport(); + 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]; + Handle(Message_CompositeAlerts) myCompositAlerts; //! container of alerts + Handle(Message_ReportWriter) myReportWriter; //! store/restore report + + NCollection_Sequence myAlertLevels; //! container of active levels, new alerts are added below the latest level + NCollection_Map myActiveMetrics; //! metrics to compute on alerts + + Standard_Integer myLimit; //! Maximum number of collected alerts on the top level + Standard_Boolean myWriteFileOnEachAlert; //! State if output file should be written on each alert adding }; #endif // _Message_Report_HeaderFile diff --git a/src/Message/Message_ReportWriter.hxx b/src/Message/Message_ReportWriter.hxx new file mode 100644 index 0000000000..5891ffc813 --- /dev/null +++ b/src/Message/Message_ReportWriter.hxx @@ -0,0 +1,64 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Message_ReportWriter_HeaderFile +#define _Message_ReportWriter_HeaderFile + +#include +#include +#include + +class Message_Report; +class Message_ReportWriter; +DEFINE_STANDARD_HANDLE(Message_ReportWriter, Standard_Transient) + +//! Base class to store/restore Message_Report content in XML document +class Message_ReportWriter : public Standard_Transient +{ +public: + //! Constructor + Message_ReportWriter() {} + + //! Returns the name of the output file + TCollection_AsciiString FileName() const { return myFileName; } + + //! Sets the name of the file for output report + //! \param theFileName the name + void SetFileName (const TCollection_AsciiString& theFileName) { myFileName = theFileName; } + + //! Returns the gravity of the output messages + Message_Gravity Gravity() const { return myGravity; } + + //! Sets the gravity of the output messages + void SetGravity (const Message_Gravity theGravity) { myGravity = theGravity; } + + //! Stores the report into a file. The file format is an XML document. + //! \param theReport the source report + //! \param theFileName a file name + //! \return true if success + virtual Standard_Boolean ExportReport (const Handle(Message_Report)& theReport) = 0; + + //! Restores the report from the file. The file format should be an XML document. + //! \return theReport the report to get the file content + //! \param theFileName a file name + //! \return true if success + virtual Standard_Boolean ImportReport (const Handle(Message_Report)& theReport) = 0; + + DEFINE_STANDARD_RTTI_INLINE(Message_ReportWriter, Standard_Transient) + +protected: + TCollection_AsciiString myFileName; //! file name + Message_Gravity myGravity; //! gravity level of messages +}; + +#endif // _Message_ReportWriter_HeaderFile diff --git a/src/TopoDS/FILES b/src/TopoDS/FILES index 8e17f304b6..27345a189f 100644 --- a/src/TopoDS/FILES +++ b/src/TopoDS/FILES @@ -1,5 +1,7 @@ TopoDS.hxx TopoDS.lxx +TopoDS_AlertAttribute.hxx +TopoDS_AlertAttribute.cxx TopoDS_Builder.cxx TopoDS_Builder.hxx TopoDS_Builder.lxx diff --git a/src/TopoDS/TopoDS_AlertAttribute.cxx b/src/TopoDS/TopoDS_AlertAttribute.cxx new file mode 100644 index 0000000000..a1b9c5b1ba --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.cxx @@ -0,0 +1,56 @@ +// Created on: 2018-06-10 +// Created by: Natalia Ermolaeva +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include + +IMPLEMENT_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_Attribute) + +//======================================================================= +//function : TopoDS_AlertAttribute +//purpose : +//======================================================================= +TopoDS_AlertAttribute::TopoDS_AlertAttribute (const TopoDS_Shape& theShape, + const TCollection_AsciiString& theName) +: Message_AttributeStream (Standard_SStream(), theName), myShape (theShape) +{ + Standard_SStream aStream; + theShape.DumpJson (aStream); + + SetStream (aStream); +} + +//======================================================================= +//function : Send +//purpose : +//======================================================================= +void TopoDS_AlertAttribute::Send (const Handle(Message_Messenger)& theMessenger, + const TopoDS_Shape& theShape) +{ + for (Message_SequenceOfPrinters::Iterator aPrinterIter (theMessenger->Printers()); aPrinterIter.More(); aPrinterIter.Next()) + { + const Handle(Message_Printer)& aPrinter = aPrinterIter.Value(); + if (!aPrinter->IsKind (STANDARD_TYPE (Message_PrinterToReport))) + continue; + + Handle (Message_PrinterToReport) aPrinterToReport = Handle(Message_PrinterToReport)::DownCast (aPrinter); + const Handle(Message_Report)& aReport = aPrinterToReport->Report(); + + Message_AlertExtended::AddAlert (aReport, new TopoDS_AlertAttribute (theShape, aPrinterToReport->Value()), + theMessenger->OuputGravity()); + aPrinterToReport->Clear(); + } +} diff --git a/src/TopoDS/TopoDS_AlertAttribute.hxx b/src/TopoDS/TopoDS_AlertAttribute.hxx new file mode 100644 index 0000000000..b7e5e95e1c --- /dev/null +++ b/src/TopoDS/TopoDS_AlertAttribute.hxx @@ -0,0 +1,76 @@ +// 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 +#include +#include + +#include + +class Message_Messenger; + +//! Alert attributre object storing TopoDS shape in its field +class TopoDS_AlertAttribute : public Message_AttributeStream +{ +public: + //! Constructor with shape argument + Standard_EXPORT TopoDS_AlertAttribute (const TopoDS_Shape& theShape, + const TCollection_AsciiString& theName = TCollection_AsciiString()); + + //! Returns contained shape + const TopoDS_Shape& GetShape() const { return myShape; } + + //! Push shape information into messenger + Standard_EXPORT static void Send (const Handle(Message_Messenger)& theMessenger, + const TopoDS_Shape& theShape); + + // OCCT RTTI + DEFINE_STANDARD_RTTIEXT(TopoDS_AlertAttribute, Message_AttributeStream) + +private: + TopoDS_Shape myShape; +}; + +#define MESSAGE_INFO_SHAPE(Shape, Name) \ + { \ + if (!Message::DefaultReport().IsNull()) \ + { \ + Message_AlertExtended::AddAlert (Message::DefaultReport(), \ + new TopoDS_AlertAttribute (Shape, Name), Message_Info); \ + } \ + } + +// HAsciiString +inline const Handle(Message_Messenger)& operator<< (const Handle(Message_Messenger)& theMessenger, + const TopoDS_Shape& theShape) +{ + TopoDS_AlertAttribute::Send (theMessenger, theShape); + return theMessenger; +} + +//! @def OCCT_SEND_MESSAGE +//! Append into messenger result of DumpJson for the field +//! It computes Dump of the fields. The expected field is a pointer. +//! Use this macro for fields of the dumped class which has own DumpJson implementation. +#define OCCT_SEND_SHAPE(theShape) \ +{ \ + Message::DefaultMessenger() << theShape; \ +} + +#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..facaadc34a --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.cxx @@ -0,0 +1,356 @@ +// 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 + +#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 : +// ======================================================================= +Standard_Boolean XmlDrivers_MessageReportStorage::ExportReport (const Handle(Message_Report)& theReport) +{ + + if (theReport.IsNull()) + return Standard_False; + + 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 (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); + } + } + if (GetApplication()->SaveAs (aDocument, FileName()) != PCDM_SS_OK) + return Standard_False; + + GetApplication()->Close (aDocument); + return Standard_True; +} + +// ======================================================================= +// function : ImportReport +// purpose : +// ======================================================================= +Standard_Boolean XmlDrivers_MessageReportStorage::ImportReport (const Handle(Message_Report)& theReport) +{ + Handle(TDocStd_Application) anApplication = GetApplication(); + Standard_Integer aDocumentId = anApplication->IsInSession (FileName()); + if (aDocumentId > 0) + { + Handle(TDocStd_Document) aDocument; + anApplication->GetDocument (aDocumentId, aDocument); + anApplication->Close (aDocument); + } + + Handle(TDocStd_Document) aDocument; + GetApplication()->Open (FileName(), aDocument); + if (aDocument.IsNull()) + return Standard_False; + + TDF_Label aMainLabel = aDocument->Main(); + if (aMainLabel.IsNull()) + return Standard_False; + + TDF_Label aLabel; + 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_Gravity) (TCollection_AsciiString (aGravityName).IntegerValue()); + + /// 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, theReport, Handle(Message_Alert)()); + } + } + return Standard_True; +} + +// ======================================================================= +// 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, aGravityId); + + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlertExtended.IsNull()) + continue; + Handle(Message_CompositeAlerts) aComposite = anAlertExtended->CompositeAlerts(); + if (aComposite.IsNull()) + continue; + + const Message_ListOfAlert& anAlerts = aComposite->Alerts ((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, + const 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_Gravity) (TCollection_AsciiString (aNameAttribute->Get()).IntegerValue()); + // 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); + } + } + if (theParentAlert.IsNull()) + theReport->AddAlert (theGravity, anAlert); + else + { + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("importAlert") + theReport->AddAlert (theGravity, anAlert); + } +} + +// ======================================================================= +// function : exportAlertParameters +// purpose : +// ======================================================================= +void XmlDrivers_MessageReportStorage::exportAlertParameters (const Handle(Message_Alert)& theAlert, const TDF_Label& theAlertLabel) +{ + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast (theAlert); + if (anAlertExtended.IsNull()) // name attribute is empty + return; + + // store attribute time + Handle(Message_Attribute) anAttribute = anAlertExtended->Attribute(); + + TDataStd_Name::Set (theAlertLabel, anAttribute->DynamicType()->Name()); + //TDataStd_Real::Set (theAlertLabel, anAlertExtended->CumulativeMetric()); + + TDataStd_AsciiString::Set (theAlertLabel, anAttribute->GetName()); + + if (Gravity() == Message_Trace) + return; + + + Standard_CString aDynamicTypeName = anAttribute->DynamicType()->Name(); + TCollection_AsciiString aStreamText; + if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeStream)->Name()) + { + Handle(Message_AttributeStream) aValuesArrayAlert = Handle(Message_AttributeStream)::DownCast (anAttribute); + aStreamText = Standard_Dump::Text (aValuesArrayAlert->Stream()); + } + else if (aDynamicTypeName == STANDARD_TYPE (TopoDS_AlertAttribute)->Name()) + { + Handle(TopoDS_AlertAttribute) aShapeAttribute = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute); + Standard_SStream aStream; + BinTools::Write (aShapeAttribute->GetShape(), aStream); + aStreamText = Standard_Dump::Text (aStream); + } + if (!aStreamText.IsEmpty()) + { + Handle(TDataStd_ExtStringArray) aListAttribute = TDataStd_ExtStringArray::Set (theAlertLabel, 0, 0); + aListAttribute->SetValue (0, aStreamText); + } +} + +// ======================================================================= +// 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(); + + Handle(Message_AlertExtended) anAlert = new Message_AlertExtended(); + Handle(Message_Attribute) aMessageAttribute; + if (aDynamicTypeName == STANDARD_TYPE (Message_Attribute)->Name()) + aMessageAttribute = new Message_Attribute(); + else if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeStream)->Name() || + aDynamicTypeName == STANDARD_TYPE (TopoDS_AlertAttribute)->Name()) + { + // values + NCollection_Vector anArrayValues; + if (!aParametersLabel.FindAttribute (TDataStd_ExtStringArray::GetID(), anAttribute)) + return Handle(Message_Alert)(); + + Handle(TDataStd_ExtStringArray) aValuesAttribute = Handle(TDataStd_ExtStringArray)::DownCast (anAttribute); + if (aValuesAttribute.IsNull()) + return Handle(Message_Alert)(); + + Standard_SStream aStream; + for (int aValueId = aValuesAttribute->Lower(); aValueId <= aValuesAttribute->Upper(); aValueId++) + { + aStream << aValuesAttribute->Value (aValueId); + } + + if (aDynamicTypeName == STANDARD_TYPE (Message_AttributeStream)->Name()) + { + aMessageAttribute = new Message_AttributeStream (aStream); + } + else if (aDynamicTypeName == STANDARD_TYPE (TopoDS_AlertAttribute)->Name()) + { + TopoDS_Shape aShape; + BinTools::Read (aShape, aStream); + aMessageAttribute = new TopoDS_AlertAttribute (aShape); + } + } + + 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()); + anAlert->SetAttribute (aMessageAttribute); + } + + // time + //Standard_Real aTime = -1; + //Handle(TDataStd_Real) aTimeAttribute; + //if (aParametersLabel.FindAttribute (TDataStd_Real::GetID(), aTimeAttribute)) + // aTime = aTimeAttribute->Get(); + + //anAlert->SetCumulativeMetric (aTime); + return anAlert; +} diff --git a/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx b/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx new file mode 100644 index 0000000000..a98da21eae --- /dev/null +++ b/src/XmlDrivers/XmlDrivers_MessageReportStorage.hxx @@ -0,0 +1,70 @@ +// 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 +#include + +//! Base class to store/restore Message_Report content in XML document +class XmlDrivers_MessageReportStorage : public Message_ReportWriter +{ +public: + //! Stores the report into a file. The file format is an XML document. + //! \param theReport the source report + //! \param theFileName a file name + //! \return true if success + Standard_EXPORT virtual Standard_Boolean ExportReport (const Handle(Message_Report)& theReport) Standard_OVERRIDE; + + //! Restores the report from the file. The file format should be an XML document. + //! \return theReport the report to get the file content + //! \param theFileName a file name + //! \return true if success + Standard_EXPORT virtual Standard_Boolean ImportReport (const Handle(Message_Report)& theReport) Standard_OVERRIDE; + +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 + 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 + void importAlert (const TDF_Label& theAlertLabel, + const Message_Gravity theGravity, + const 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 + 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/tests/basic/begin b/tests/basic/begin new file mode 100644 index 0000000000..a9dadf81c4 --- /dev/null +++ b/tests/basic/begin @@ -0,0 +1,6 @@ +if { [info exists imagedir] == 0 } { + set imagedir . +} +if { [info exists test_image ] == 0 } { + set test_image photo +} diff --git a/tests/basic/end b/tests/basic/end new file mode 100644 index 0000000000..504ad5983c --- /dev/null +++ b/tests/basic/end @@ -0,0 +1,2 @@ +# File : end +puts "TEST COMPLETED" diff --git a/tests/basic/grids.list b/tests/basic/grids.list new file mode 100644 index 0000000000..fea9d466f3 --- /dev/null +++ b/tests/basic/grids.list @@ -0,0 +1 @@ +001 message diff --git a/tests/basic/message/messenger b/tests/basic/message/messenger new file mode 100644 index 0000000000..94a7e4717d --- /dev/null +++ b/tests/basic/message/messenger @@ -0,0 +1,16 @@ +puts "==================================" +puts "" +puts "==================================" + +#ostream printer +SetMessagePrinter -type ostream +DumpMessenger +SendMessage "processing a text message in ostream" "information message" "error message" "warning message" + +#report printer +SetMessagePrinter -clear +SetMessagePrinter -type report +DumpMessenger +SendMessage "processing a text message in report" "information message" "error message" "warning message" + +#WriteMessageReport d:/tmp.xml diff --git a/tests/basic/parse.rules b/tests/basic/parse.rules new file mode 100644 index 0000000000..bca616b06f --- /dev/null +++ b/tests/basic/parse.rules @@ -0,0 +1,3 @@ +FAILED /\bFaulty\b/ bad shape +IGNORE /^Tcl Exception: tolerance ang : [\d.-]+/ blend failure - test will be failed as incomplete +OK /Relative error of mass computation/ message from vprops \ No newline at end of file diff --git a/tools/Convert/Convert_Tools.cxx b/tools/Convert/Convert_Tools.cxx index d422933a9c..67803f2494 100644 --- a/tools/Convert/Convert_Tools.cxx +++ b/tools/Convert/Convert_Tools.cxx @@ -1,6 +1,6 @@ -// Created on: 2020-01-25 +// Created on: 2017-06-16 // Created by: Natalia ERMOLAEVA -// Copyright (c) 2020 OPEN CASCADE SAS +// Copyright (c) 2017 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -16,8 +16,19 @@ #include #include -#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include +#include +#include // ======================================================================= // function : ReadShape @@ -33,14 +44,76 @@ TopoDS_Shape Convert_Tools::ReadShape (const TCollection_AsciiString& theFileNam } //======================================================================= -//function : ConvertStreamToPresentations +//function : CreateShape //purpose : //======================================================================= -void Convert_Tools::ConvertStreamToPresentations (const Standard_SStream&, - const Standard_Integer, - const Standard_Integer, - NCollection_List&) +void Convert_Tools::ConvertStreamToPresentations (const Standard_SStream& theSStream, + const Standard_Integer theStartPos, + const Standard_Integer /*theLastPos*/, + NCollection_List& thePresentations) { + int aStartPos = theStartPos; + + gp_XYZ aPoint; + if (aPoint.InitFromJson (theSStream, aStartPos)) + { + thePresentations.Append (new Convert_TransientShape (BRepBuilderAPI_MakeVertex (aPoint))); + return; + } + + gp_Pnt aPnt; + if (aPnt.InitFromJson (theSStream, aStartPos)) + { + thePresentations.Append (new Convert_TransientShape (BRepBuilderAPI_MakeVertex (aPnt))); + return; + } + + gp_Dir aDir; + if (aDir.InitFromJson (theSStream, aStartPos)) + { + thePresentations.Append (new Convert_TransientShape (BRepBuilderAPI_MakeEdge (gp::Origin(), aDir.XYZ()))); + return; + } + + gp_Ax2 anAx2; + if (anAx2.InitFromJson (theSStream, aStartPos)) + { + Handle(Geom_Plane) aGeomPlane = new Geom_Plane (gp_Ax3 (anAx2)); + CreatePresentation (aGeomPlane, thePresentations); + return; + } + + gp_Ax3 anAx3; // should be after gp_Ax2 + if (anAx3.InitFromJson (theSStream, aStartPos)) + { + Handle(Geom_Plane) aGeomPlane = new Geom_Plane (anAx3); + CreatePresentation (aGeomPlane, thePresentations); + return; + } + + // should be after gp_Ax3 + gp_Ax1 anAxis; + if (anAxis.InitFromJson (theSStream, aStartPos)) + { + thePresentations.Append (new Convert_TransientShape (BRepBuilderAPI_MakeEdge (anAxis.Location(), anAxis.Location().Coord() + anAxis.Direction().XYZ()))); + return; + } + + gp_Trsf aTrsf; + if (aTrsf.InitFromJson (theSStream, aStartPos)) + { + CreatePresentation (aTrsf, thePresentations); + return; + } + + Bnd_Box aBox; + if (aBox.InitFromJson (theSStream, aStartPos)) + { + TopoDS_Shape aShape; + if (Convert_Tools::CreateShape (aBox, aShape)) + thePresentations.Append (new Convert_TransientShape (aShape)); + return; + } Select3D_BndBox3d aSelectBndBox; if (aSelectBndBox.InitFromJson (theSStream, aStartPos)) @@ -59,8 +132,182 @@ void Convert_Tools::ConvertStreamToPresentations (const Standard_SStream&, //function : ConvertStreamToColor //purpose : //======================================================================= -Standard_Boolean Convert_Tools::ConvertStreamToColor (const Standard_SStream&, - Quantity_Color&) +Standard_Boolean Convert_Tools::ConvertStreamToColor (const Standard_SStream& theSStream, + Quantity_Color& theColor) { + Standard_Integer aStartPos = 1; + Quantity_ColorRGBA aColorRGBA; + if (aColorRGBA.InitFromJson (theSStream, aStartPos)) + { + theColor = aColorRGBA.GetRGB(); + return Standard_True; + } + + Quantity_Color aColor; + if (aColor.InitFromJson (theSStream, aStartPos)) + { + theColor = aColor; + return Standard_True; + } + return Standard_False; } + +//======================================================================= +//function : CreateShape +//purpose : +//======================================================================= +Standard_Boolean Convert_Tools::CreateShape (const Bnd_Box& theBoundingBox, TopoDS_Shape& theShape) +{ + if (theBoundingBox.IsVoid() || theBoundingBox.IsWhole()) + return Standard_False; + + Standard_Real aXmin, anYmin, aZmin, aXmax, anYmax, aZmax; + theBoundingBox.Get (aXmin, anYmin, aZmin, aXmax, anYmax, aZmax); + + gp_Pnt aPntMin = gp_Pnt (aXmin, anYmin, aZmin); + gp_Pnt aPntMax = gp_Pnt (aXmax, anYmax, aZmax); + + return CreateBoxShape (aPntMin, aPntMax, theShape); +} + +//======================================================================= +//function : CreateShape +//purpose : +//======================================================================= +Standard_Boolean Convert_Tools::CreateShape (const Bnd_OBB& theBoundingBox, TopoDS_Shape& theShape) +{ + if (theBoundingBox.IsVoid()) + return Standard_False; + + TColgp_Array1OfPnt anArrPnts(0, 8); + theBoundingBox.GetVertex(&anArrPnts(0)); + + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (gp_Pnt (anArrPnts.Value(0)), gp_Pnt (anArrPnts.Value(1)))); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (gp_Pnt (anArrPnts.Value(0)), gp_Pnt (anArrPnts.Value(2)))); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (gp_Pnt (anArrPnts.Value(1)), gp_Pnt (anArrPnts.Value(3)))); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (gp_Pnt (anArrPnts.Value(2)), gp_Pnt (anArrPnts.Value(3)))); + + theShape = aCompound; + return Standard_True; +} + +//======================================================================= +//function : CreateBoxShape +//purpose : +//======================================================================= +Standard_Boolean Convert_Tools::CreateBoxShape (const gp_Pnt& thePntMin, const gp_Pnt& thePntMax, TopoDS_Shape& theShape) +{ + Standard_Boolean aThinOnX = fabs (thePntMin.X() - thePntMax.X()) < Precision::Confusion(); + Standard_Boolean aThinOnY = fabs (thePntMin.Y() - thePntMax.Y()) < Precision::Confusion(); + Standard_Boolean aThinOnZ = fabs (thePntMin.Z() - thePntMax.Z()) < Precision::Confusion(); + + if (((int)aThinOnX + (int)aThinOnY + (int)aThinOnZ) > 1) // thin box in several directions is a point + { + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeVertex (thePntMin)); + theShape = aCompound; + return Standard_True; + } + + if (aThinOnX || aThinOnY || aThinOnZ) + { + gp_Pnt aPnt1, aPnt2, aPnt3, aPnt4 ; + if (aThinOnX) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMax.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMax.Z()); + } + else if (aThinOnY) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMax.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMax.Z()); + } + else if (aThinOnZ) + { + aPnt1 = gp_Pnt(thePntMin.X(), thePntMin.Y(), thePntMin.Z()); + aPnt2 = gp_Pnt(thePntMax.X(), thePntMin.Y(), thePntMin.Z()); + aPnt3 = gp_Pnt(thePntMax.X(), thePntMax.Y(), thePntMin.Z()); + aPnt4 = gp_Pnt(thePntMin.X(), thePntMax.Y(), thePntMin.Z()); + } + BRep_Builder aBuilder; + TopoDS_Compound aCompound; + aBuilder.MakeCompound (aCompound); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt1, aPnt2)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt2, aPnt3)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt3, aPnt4)); + aBuilder.Add (aCompound, BRepBuilderAPI_MakeEdge (aPnt4, aPnt1)); + + theShape = aCompound; + return Standard_True; + } + else + { + BRepPrimAPI_MakeBox aBoxBuilder (thePntMin, thePntMax); + theShape = aBoxBuilder.Shape(); + return Standard_True; + } +} + +//======================================================================= +//function : CreatePresentation +//purpose : +//======================================================================= +void Convert_Tools::CreatePresentation (const Handle(Geom_Plane)& thePlane, + NCollection_List& thePresentations) +{ + Handle(AIS_Plane) aPlanePrs = new AIS_Plane (thePlane); + + // TODO - default fields to be defined in another place + aPlanePrs->Attributes()->SetPlaneAspect (new Prs3d_PlaneAspect()); + Handle (Prs3d_PlaneAspect) aPlaneAspect = aPlanePrs->Attributes()->PlaneAspect(); + aPlaneAspect->SetPlaneLength (100, 100); + aPlaneAspect->SetDisplayCenterArrow (Standard_True); + aPlaneAspect->SetDisplayEdgesArrows (Standard_True); + aPlaneAspect->SetArrowsSize (100); + aPlaneAspect->SetArrowsLength (100); + aPlaneAspect->SetDisplayCenterArrow (Standard_True); + aPlaneAspect->SetDisplayEdges (Standard_True); + + aPlanePrs->SetColor (Quantity_NOC_WHITE); + aPlanePrs->SetTransparency (0); + + thePresentations.Append (aPlanePrs); +} + +//======================================================================= +//function : CreatePresentation +//purpose : +//======================================================================= +void Convert_Tools::CreatePresentation (const gp_Trsf& theTrsf, + NCollection_List& thePresentations) +{ + Bnd_Box aBox (gp_Pnt(), gp_Pnt(10., 10., 10)); + + TopoDS_Shape aBoxShape; + if (!Convert_Tools::CreateShape (aBox, aBoxShape)) + return; + + Handle(AIS_Shape) aSourcePrs = new AIS_Shape (aBoxShape); + // TODO - default fields to be defined in another place + aSourcePrs->SetColor (Quantity_NOC_WHITE); + aSourcePrs->SetTransparency (0.5); + thePresentations.Append (aSourcePrs); + + Handle(AIS_Shape) aTransformedPrs = new AIS_Shape (aBoxShape); + // TODO - default fields to be defined in another place + aTransformedPrs->SetColor (Quantity_NOC_TOMATO); + aTransformedPrs->SetTransparency (0.5); + aTransformedPrs->SetLocalTransformation (theTrsf); + thePresentations.Append (aTransformedPrs); +} diff --git a/tools/Convert/Convert_Tools.hxx b/tools/Convert/Convert_Tools.hxx index 3145c77cce..bdcd05c09b 100644 --- a/tools/Convert/Convert_Tools.hxx +++ b/tools/Convert/Convert_Tools.hxx @@ -1,6 +1,6 @@ -// Created on: 2020-01-25 +// Created on: 2017-06-16 // Created by: Natalia ERMOLAEVA -// Copyright (c) 2020 OPEN CASCADE SAS +// Copyright (c) 2017 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -16,16 +16,33 @@ #ifndef Convert_Tools_H #define Convert_Tools_H +#include +#include +#include +#include +#include +#include #include #include #include #include -#include +#include +#include #include +#include #include +#include + +#include +#include +#include +#include + +class Geom_Plane; +class Geom_Transformation; //! \class Convert_Tools -//! \brief The tool that gives auxiliary methods converting. +//! \brief The tool that gives auxiliary methods for qt elements manipulation class Convert_Tools { public: @@ -49,6 +66,35 @@ public: //! \returns true if done Standard_EXPORT static Standard_Boolean ConvertStreamToColor (const Standard_SStream& theSStream, Quantity_Color& theColor); + + //! Creates box shape + //! \param theBoundingBox box shape parameters + //! \return created shape + Standard_EXPORT static Standard_Boolean CreateShape (const Bnd_Box& theBoundingBox, TopoDS_Shape& theShape); + + //! Creates box shape + //! \param theBoundingBox box shape parameters + //! \return created shape + Standard_EXPORT static Standard_Boolean CreateShape (const Bnd_OBB& theBoundingBox, TopoDS_Shape& theShape); + + //! Creates box shape + //! \param thePntMin minimum point on the bounding box + //! \param thePntMax maximum point on the bounding box + //! \return created shape + Standard_EXPORT static Standard_Boolean CreateBoxShape (const gp_Pnt& thePntMin, const gp_Pnt& thePntMax, TopoDS_Shape& theShape); + + //! Creates presentation AIS_Plane + //! \param thePlane source plane + //! \param thePresentations container to collect new presentation/s + Standard_EXPORT static void CreatePresentation (const Handle(Geom_Plane)& thePlane, + NCollection_List& thePresentations); + + //! Creates two presentations base on gp_Trsf: box in initial place and transformed box + //! \param thePlane source plane + //! \param thePresentations container to collect new presentation/s + Standard_EXPORT static void CreatePresentation (const gp_Trsf& theTrsf, + NCollection_List& thePresentations); + }; #endif diff --git a/tools/MessageModel/FILES b/tools/MessageModel/FILES new file mode 100644 index 0000000000..5fbdcbc86b --- /dev/null +++ b/tools/MessageModel/FILES @@ -0,0 +1,16 @@ +MessageModel.qrc +MessageModel_Actions.cxx +MessageModel_Actions.hxx +MessageModel_ActionType.hxx +MessageModel_ItemAlert.cxx +MessageModel_ItemAlert.hxx +MessageModel_ItemBase.cxx +MessageModel_ItemBase.hxx +MessageModel_ItemReport.cxx +MessageModel_ItemReport.hxx +MessageModel_ItemRoot.cxx +MessageModel_ItemRoot.hxx +MessageModel_Tools.cxx +MessageModel_Tools.hxx +MessageModel_TreeModel.cxx +MessageModel_TreeModel.hxx diff --git a/tools/MessageModel/MessageModel.qrc b/tools/MessageModel/MessageModel.qrc new file mode 100644 index 0000000000..8b794a8599 --- /dev/null +++ b/tools/MessageModel/MessageModel.qrc @@ -0,0 +1,6 @@ + + + icons/item_shape.png + icons/item_streamValues.png + + diff --git a/tools/MessageModel/MessageModel_ActionType.hxx b/tools/MessageModel/MessageModel_ActionType.hxx new file mode 100644 index 0000000000..7df28caaba --- /dev/null +++ b/tools/MessageModel/MessageModel_ActionType.hxx @@ -0,0 +1,32 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ActionType_H +#define MessageModel_ActionType_H + +//! Kind of action type for tree view context menu item +enum MessageModel_ActionType +{ + MessageModel_ActionType_Activate, //!< set Message_Report active + MessageModel_ActionType_Deactivate, //!< set Message_Report not active + MessageModel_ActionType_Clear, //!< clear Message_Report alerts + MessageModel_ActionType_ExportToShapeView, //!< export TopoDS_Shape of selected item into TKShapeView plugin + MessageModel_ActionType_TestMetric, //!< test alerts + MessageModel_ActionType_TestProperties, //!< test alerts + MessageModel_ActionType_TestMessenger, //!< test message view on messenger printer to report + MessageModel_ActionType_TestReportTree //!< test message view on hierarchical report +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Actions.cxx b/tools/MessageModel/MessageModel_Actions.cxx new file mode 100644 index 0000000000..6308c66460 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.cxx @@ -0,0 +1,268 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_Actions::MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel) +: QObject (theParent), myTreeModel (theTreeModel), mySelectionModel (theModel) +{ + myActions.insert (MessageModel_ActionType_Activate, + ViewControl_Tools::CreateAction ("Activate", SLOT (OnActivateReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_Deactivate, + ViewControl_Tools::CreateAction ("Deactivate", SLOT (OnDeactivateReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_Clear, + ViewControl_Tools::CreateAction ("Clear", SLOT (OnClearReport()), parent(), this)); + myActions.insert (MessageModel_ActionType_ExportToShapeView, + ViewControl_Tools::CreateAction (tr ("Export to ShapeView"), SLOT (OnExportToShapeView()), parent(), this)); +} + +// ======================================================================= +// function : GetAction +// purpose : +// ======================================================================= +QAction* MessageModel_Actions::GetAction (const MessageModel_ActionType& theType) +{ + if (myActions.contains (theType)) + return myActions[theType]; + + return 0; +} + +// ======================================================================= +// function : AddMenuActions +// purpose : +// ======================================================================= +void MessageModel_Actions::AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu) +{ + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + MessageModel_ItemAlertPtr anAlertItem; + for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin(); aSelIt != theSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + + anAlertItem = itemDynamicCast (anItemBase); + if (anAlertItem) + break; + } + + if (aReportItem && !aReportItem->GetReport().IsNull()) + { + theMenu->addAction (myActions[MessageModel_ActionType_Deactivate]); + theMenu->addAction (myActions[MessageModel_ActionType_Activate]); + theMenu->addAction (myActions[MessageModel_ActionType_Clear]); + } + else if (anAlertItem) + { + theMenu->addAction (myActions[MessageModel_ActionType_ExportToShapeView]); + } + + theMenu->addSeparator(); +} + +// ======================================================================= +// function : getSelectedReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageModel_Actions::getSelectedReport (QModelIndex& theReportIndex) const +{ + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aReportItem = itemDynamicCast (anItemBase); + theReportIndex = anIndex; + if (aReportItem) + break; + } + if (!aReportItem) + return NULL; + + return aReportItem->GetReport(); +} + +// ======================================================================= +// function : OnActivateReport +// purpose : +// ======================================================================= +static Handle(Message_PrinterToReport) MyPrinterToReport; +static Message_SequenceOfPrinters MyDeactivatedPrinters; + +void MessageModel_Actions::OnActivateReport() +{ + if (MyPrinterToReport.IsNull()) + MyPrinterToReport = new Message_PrinterToReport(); + + if (MyPrinterToReport->Report()->IsActiveInMessenger()) + return; + + MyDeactivatedPrinters = Message::DefaultMessenger()->Printers(); + Message::DefaultMessenger()->ChangePrinters().Clear(); + + Message::DefaultMessenger()->AddPrinter (MyPrinterToReport); + Message::DefaultMessenger()->SetTraceLevel (1); + + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnDeactivateReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnDeactivateReport() +{ + if (MyPrinterToReport.IsNull() || !MyPrinterToReport->Report()->IsActiveInMessenger()) + return; + + Message::DefaultMessenger()->RemovePrinter (MyPrinterToReport); + Message::DefaultMessenger()->ChangePrinters().Assign (MyDeactivatedPrinters); + + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnClearReport +// purpose : +// ======================================================================= +void MessageModel_Actions::OnClearReport() +{ + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + aReport->Clear(); + myTreeModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : OnExportToShapeView +// purpose : +// ======================================================================= +void MessageModel_Actions::OnExportToShapeView() +{ + TCollection_AsciiString aPluginName ("TKShapeView"); + + NCollection_List aPluginParameters; + if (myParameters->FindParameters (aPluginName)) + aPluginParameters = myParameters->Parameters (aPluginName); + NCollection_List anItemNames; + if (myParameters->FindSelectedNames (aPluginName)) + anItemNames = myParameters->GetSelectedNames (aPluginName); + + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + QStringList anExportedPointers; + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast (anItemBase); + if (!anAlertItem) + continue; + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + continue; + + Handle(Message_AlertExtended) anExtAlert = Handle(Message_AlertExtended)::DownCast (anAlert); + if (anExtAlert.IsNull()) + continue; + + Handle(Message_Attribute) anAttribute = anExtAlert->Attribute(); + if (anAttribute.IsNull()) + continue; + + if (!anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + continue; + + const TopoDS_Shape aShape = Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape(); + if (aShape.IsNull()) + continue; + aPluginParameters.Append (aShape.TShape()); + anItemNames.Append (TInspectorAPI_PluginParameters::ParametersToString (aShape)); + + anExportedPointers.append (MessageModel_Tools::GetPointerInfo (aShape.TShape(), true).ToCString()); + } + + if (anExportedPointers.empty()) + return; + myParameters->SetSelectedNames (aPluginName, anItemNames); + myParameters->SetParameters (aPluginName, aPluginParameters); + QMessageBox::information (0, "Information", QString ("TShapes '%1' are sent to %2 tool.") + .arg (anExportedPointers.join (", ")).arg (QString (aPluginName.ToCString()))); +} diff --git a/tools/MessageModel/MessageModel_Actions.hxx b/tools/MessageModel/MessageModel_Actions.hxx new file mode 100644 index 0000000000..39eab429e2 --- /dev/null +++ b/tools/MessageModel/MessageModel_Actions.hxx @@ -0,0 +1,98 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_Actions_H +#define MessageModel_Actions_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +class Message_Report; +class MessageModel_TreeModel; + +class QAction; +class QItemSelectionModel; +class QMenu; +class QWidget; + +//! \class MessageModel_Actions +//! \brief This is a listener of popup context menu items and selection change in message model +class MessageModel_Actions : public QObject +{ + Q_OBJECT + +public: + + //! Constructor + Standard_EXPORT MessageModel_Actions (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, + QItemSelectionModel* theModel); + + //! Destructor + virtual ~MessageModel_Actions() Standard_OVERRIDE {} + + //! Returns action by the type + //! \param theType an action type + //! \return an action instance if it exists + Standard_EXPORT QAction* GetAction (const MessageModel_ActionType& theType); + + //! Fills popup menu with actions depending on the current selection + //! \param theSelectedIndices tree model selected indices + //! \param theMenu menu to be filled + Standard_EXPORT void AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu); + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) + { myParameters = theParameters; } + +public slots: + //! Set selected report active + void OnActivateReport(); + + //! Set selected report not active + void OnDeactivateReport(); + + //! Clears container of alerts of selected report + void OnClearReport(); + + //! Exports the first selected shape into ShapeViewer plugin. + void OnExportToShapeView(); + +protected: + //! Returns report of selected tree view item if a report item is selected + //! \param theReportIndex tree model index of the found report + //! \return report instance or NULL + Handle(Message_Report) getSelectedReport (QModelIndex& theReportIndex) const; + +protected: + MessageModel_TreeModel* myTreeModel; //< tree model + QItemSelectionModel* mySelectionModel; //< selection model + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + QMap myActions; //!< container of all actions +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemAlert.cxx b/tools/MessageModel/MessageModel_ItemAlert.cxx new file mode 100644 index 0000000000..31e34e0aab --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.cxx @@ -0,0 +1,331 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemAlert::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + MessageModel_ItemReportPtr aReportItem = MessageModel_ItemReport::FindReportItem (Parent()); + if (!aReportItem) + return QVariant(); + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport.IsNull()) + return QVariant(); + + if (theRole == Qt::ForegroundRole) + { + if (!aReport->IsActiveInMessenger()) + return QColor(Qt::darkGray); + + return QVariant(); + } + + Handle(Message_Alert) anAlert = getAlert(); + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + + // if the alert is composite, process the real alert + if (theRole == Qt::DecorationRole && Column() == 0) + { + if (anExtendedAlert.IsNull()) + return QVariant(); + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return QVariant(); + + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + return QIcon (":/icons/item_shape.png"); + else if (!Handle(Message_AttributeStream)::DownCast (anAttribute).IsNull()) + return QIcon (":/icons/item_streamValues.png"); + else + return QVariant(); + } + + if (theRole != Qt::DisplayRole && theRole != Qt::ToolTipRole) + return QVariant(); + + if (anAlert.IsNull()) + return QVariant(); + + if (Column() == 0) + { + if (theRole == Qt::DisplayRole) + { + TCollection_AsciiString aMessageKey = anAlert->GetMessageKey(); + if (aMessageKey.IsEmpty() && !Properties().IsNull()) + aMessageKey = Properties()->Key(); + return aMessageKey.ToCString(); + } + else + return anAlert->DynamicType()->Name(); + } + + Message_MetricType aMetricType; + int aPosition; + if (MessageModel_TreeModel::IsMetricColumn (Column(), aMetricType, aPosition)) + { + if (anExtendedAlert.IsNull()) + return QVariant(); + + Handle(Message_AttributeMeter) anAttribute = Handle(Message_AttributeMeter)::DownCast (anExtendedAlert->Attribute()); + if (anAttribute.IsNull()) + return QVariant(); + + Standard_Real aCumulativeMetric = anAttribute->StopValue (aMetricType) - anAttribute->StartValue (aMetricType); + if (fabs (aCumulativeMetric) < Precision::Confusion()) + return QVariant(); + + if (aPosition == 0) return aCumulativeMetric; + else if (aPosition == 1) + { + Standard_Real aReportCumulativeMetric = MessageModel_ItemReport::CumulativeMetric (aReport, aMetricType); + if (fabs (aReportCumulativeMetric) > Precision::Confusion()) + return 100. * aCumulativeMetric / aReportCumulativeMetric; + else + return QVariant(); + } + } + return QVariant(); +} + +// ======================================================================= +// function : initRowCount +// purpose : +// ======================================================================= +int MessageModel_ItemAlert::initRowCount() const +{ + const Handle(Message_Alert)& anAlert = getAlert(); + if (anAlert.IsNull()) + return 0; + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(anAlert); + if (anExtendedAlert.IsNull()) + return 0; + + Handle(Message_CompositeAlerts) aCompositeAlert = anExtendedAlert->CompositeAlerts(); + if (aCompositeAlert.IsNull()) + return 0; + + MessageModel_ItemAlert* aCurrentItem = (MessageModel_ItemAlert*)this; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aCompositeAlert->Alerts ((Message_Gravity)aGravityId); + { + for (Message_ListOfAlert::Iterator anIt(anAlerts); anIt.More(); anIt.Next()) + { + Message_ListOfAlert aCurAlerts; + aCurAlerts.Append (anIt.Value()); + aCurrentItem->myChildAlerts.Bind(myChildAlerts.Size(), aCurAlerts); + } + } + } + + return aCurrentItem->myChildAlerts.Size(); +} + +// ======================================================================= +// function : initStream +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::initStream (Standard_OStream& OS) const +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (getAlert()); + if (anExtendedAlert.IsNull() || anExtendedAlert->Attribute().IsNull()) + return; + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return; + + if (Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + return; + + Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + OS << anAttributeStream->Stream().str(); +} + +// ======================================================================= +// function : SetStream +// purpose : +// ======================================================================= +bool MessageModel_ItemAlert::SetStream (const Standard_SStream& theSStream, Standard_Integer& theStartPos, + Standard_Integer& theLastPos) const +{ + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast (getAlert()); + if (anExtendedAlert.IsNull() || anExtendedAlert->Attribute().IsNull()) + return false; + + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (anAttribute.IsNull()) + return false; + + if (Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + return false; + + Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + TCollection_AsciiString aStreamValue = Standard_Dump::Text (anAttributeStream->Stream()); + + TCollection_AsciiString aNewValue = Standard_Dump::Text (theSStream); + + Standard_SStream aStream; + aStream << aStreamValue.SubString (1, theStartPos - 1); + aStream << aNewValue; + if (theLastPos + 1 <= aStreamValue.Length()) + aStream << aStreamValue.SubString (theLastPos + 1, aStreamValue.Length()); + + //TCollection_AsciiString aStreamValue_debug = Standard_Dump::Text (aStream); + + anAttributeStream->SetStream (aStream); + + return true; +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemAlert::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemAlert::CreateItem (currentItem(), theRow, theColumn); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::Init() +{ + MessageModel_ItemReportPtr aReportItem = itemDynamicCast (Parent()); + MessageModel_ItemAlertPtr anAlertItem; + Handle(Message_Alert) anAlert; + if (aReportItem) + { + Message_ListOfAlert anAlerts; + if (aReportItem->GetChildAlerts (Row(), anAlerts)) + { + myAlert = anAlerts.First(); + } + } + else + { + anAlertItem = itemDynamicCast (Parent()); + if (anAlertItem) + { + Message_ListOfAlert anAlerts; + if (anAlertItem->GetChildAlerts (Row(), anAlerts)) + { + myAlert = anAlerts.First(); + } + } + } + + Handle(Message_AlertExtended) anExtendedAlert = Handle(Message_AlertExtended)::DownCast(myAlert); + if (!anExtendedAlert.IsNull() && !anExtendedAlert->Attribute().IsNull()) + { + Handle(Message_Attribute) anAttribute = anExtendedAlert->Attribute(); + if (!anAttribute.IsNull()) + { + //if (!Handle(Message_AttributeStream)::DownCast(anAttribute).IsNull()) + //{ + // if (GetProperties().IsNull()) + // { + // TreeModel_ItemBasePtr anItem = Parent()->Child (Row(), Column(), false); + // SetProperties (new MessageModel_ItemPropertiesAttributeStream (anItem)); + // } + // Handle(Message_AttributeStream) anAttributeStream = Handle(Message_AttributeStream)::DownCast (anExtendedAlert->Attribute()); + // Handle(MessageModel_ItemPropertiesAttributeStream) aProperties = Handle(MessageModel_ItemPropertiesAttributeStream)::DownCast (GetProperties()); + // aProperties->Init (anAttributeStream->GetStream()); + //} + ////if (anAttribute->IsKind (STANDARD_TYPE (Message_AttributeObject))) + //// myPresentation = Handle(Message_AttributeObject)::DownCast (anAttribute)->GetObject(); + if (anAttribute->IsKind (STANDARD_TYPE (TopoDS_AlertAttribute))) + myPresentation = new Convert_TransientShape (Handle(TopoDS_AlertAttribute)::DownCast (anAttribute)->GetShape()); + } + //TCollection_AsciiString aDescription = anExtendedAlert->Attribute()->GetDescription(); + //Bnd_Box aBox; + //if (aBox.Init (Standard_SStream (aDescription.ToCString()))) + // myPresentation =new Convert_TransientShape (Convert_Tools::CreateShape (aBox)); + } + MessageModel_ItemBase::Init(); +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::Reset() +{ + MessageModel_ItemBase::Reset(); + myAlert = Handle(Message_Alert)(); + myChildAlerts.Clear(); + myPresentation = NULL; +} + +// ======================================================================= +// function : initItem +// purpose : +// ======================================================================= +void MessageModel_ItemAlert::initItem() const +{ + if (IsInitialized()) + return; + const_cast(this)->Init(); +} + +// ======================================================================= +// function : getAlert +// purpose : +// ======================================================================= +const Handle(Message_Alert)& MessageModel_ItemAlert::getAlert() const +{ + initItem(); + return myAlert; +} diff --git a/tools/MessageModel/MessageModel_ItemAlert.hxx b/tools/MessageModel/MessageModel_ItemAlert.hxx new file mode 100644 index 0000000000..c07fbf5e58 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemAlert.hxx @@ -0,0 +1,137 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemAlert_H +#define MessageModel_ItemAlert_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +class QAbstractTableModel; + +class MessageModel_ItemAlert; +typedef QExplicitlySharedDataPointer MessageModel_ItemAlertPtr; + +//! \class MessageModel_ItemAlert +//! This item is connected to Message_Alert. +//! Parent is either MessageModel_ItemRoot or MessageModel_ItemAlert, children are MessageModel_ItemAlert or no children +class MessageModel_ItemAlert : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + //! \return the pointer to the created item + static MessageModel_ItemAlertPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemAlertPtr (new MessageModel_ItemAlert (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemAlert() Standard_OVERRIDE {}; + + //! Returns the current shape + const Handle(Message_Alert)& GetAlert() const { return myAlert; } + + //! Returns alert of the report for the parameter row + Standard_Boolean GetChildAlerts (const int theRow, Message_ListOfAlert& theAlerts) const { return myChildAlerts.Find(theRow, theAlerts); } + + //! Inits the item, fills internal containers + Standard_EXPORT virtual void Init() Standard_OVERRIDE; + + //! Resets cached values + Standard_EXPORT virtual void Reset() Standard_OVERRIDE; + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + Standard_EXPORT virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + Standard_EXPORT virtual int initRowCount() const Standard_OVERRIDE; + + //! Returns stream value of the item to fulfill property panel. + //! \return stream value or dummy + Standard_EXPORT virtual bool SetStream (const Standard_SStream& theSStream, Standard_Integer& theStartPos, + Standard_Integer& theLastPos) const Standard_OVERRIDE; + + //! Sets some shape to present the item + //! \param theShape shape instance + void SetCustomShape (const TopoDS_Shape& theShape) { myCustomShape = theShape; } + + //! Returns custom shape to present the item + //! \return instance of the shape + const TopoDS_Shape& GetCustomShape() const { return myCustomShape; } + + //! Returns presentation of the attribute to be visualized in the view + //! \param theRow a model index row + //! \param theColumn a model index column + //! \thePresentations [out] container of presentation handles to be visualized + virtual void Presentations (NCollection_List& thePresentations) Standard_OVERRIDE + { thePresentations.Append (myPresentation); } + + + ////! Returns summ of children alert elapsed times. The method is recusive. + ////! \param theAlert a message alert + ////! \return double value + //Standard_EXPORT static double CumulativeMetric (const Handle(Message_Alert)& theAlert); + +protected: + + //! Initialize the current item. It is empty because Reset() is also empty. + virtual void initItem() const Standard_OVERRIDE; + + //! Returns stream value of the item to fulfill property panel. + //! \return stream value or dummy + Standard_EXPORT virtual void initStream (Standard_OStream& OS) const Standard_OVERRIDE; + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + + //! Returns current alert, initialized item if it has not been initialized yet + //! \return alert value + const Handle(Message_Alert)& getAlert() const; + +private: + + //! Constructor + MessageModel_ItemAlert (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn) {} + +private: + Handle(Message_Alert) myAlert; + + NCollection_DataMap myChildAlerts; //!< container of child alerts + + TopoDS_Shape myCustomShape; + Handle(Standard_Transient) myPresentation; +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemBase.cxx b/tools/MessageModel/MessageModel_ItemBase.cxx new file mode 100644 index 0000000000..de74f85a3c --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.cxx @@ -0,0 +1,47 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include + +// ======================================================================= +// function : isReversed +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemBase::isReversed() const +{ + TreeModel_ItemBasePtr aParentItem = GetRootItem(); + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (aParentItem); + return aRootItem ? aRootItem->IsReversed() : Standard_False; +} + +// ======================================================================= +// function : GetRootItem +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemBase::GetRootItem() const +{ + TreeModel_ItemBasePtr anItem = Parent(); + while (anItem) + { + if (MessageModel_ItemRootPtr aThisRootItem = itemDynamicCast (anItem)) + { + return aThisRootItem; + } + anItem = anItem->Parent(); + } + return TreeModel_ItemBasePtr(); +} diff --git a/tools/MessageModel/MessageModel_ItemBase.hxx b/tools/MessageModel/MessageModel_ItemBase.hxx new file mode 100644 index 0000000000..dfd9e7fb61 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemBase.hxx @@ -0,0 +1,56 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemBase_H +#define MessageModel_ItemBase_H + +#include +#include +#include + +class MessageModel_ItemBase; +typedef QExplicitlySharedDataPointer MessageModel_ItemBasePtr; + +//! \class MessageModel_ItemBase +// \brief Declaration of the tree model base item. +class MessageModel_ItemBase : public TreeModel_ItemBase +{ +public: + + //! Resets cached values + virtual void Reset() Standard_OVERRIDE { TreeModel_ItemBase::Reset(); } + +protected: + + //! Initialize the current item. It creates a backup of the specific item information + virtual void initItem() const {}; + + //! Constructor + //! param theParent a parent item + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + MessageModel_ItemBase (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : TreeModel_ItemBase (theParent, theRow, theColumn) {} + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean isReversed() const; + + //! Return root item + //! \return an item instance + TreeModel_ItemBasePtr GetRootItem() const; +}; + +#endif \ No newline at end of file diff --git a/tools/MessageModel/MessageModel_ItemReport.cxx b/tools/MessageModel/MessageModel_ItemReport.cxx new file mode 100644 index 0000000000..575de32fe4 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.cxx @@ -0,0 +1,227 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemReport::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + const Handle(Message_Report)& aReport = getReport(); + if (aReport.IsNull()) + return QVariant(); + + if (theRole == Qt::ForegroundRole) + { + if (!aReport->IsActiveInMessenger()) + return QColor(Qt::darkGray); + + return QVariant(); + } + if (theRole == Qt::ToolTipRole && !myDescription.IsEmpty() && Column() == 0) // display the exported file name in tool tip + { + OSD_Path aPath(myDescription); + return QString ("%1%2").arg (aPath.Name().ToCString()).arg (aPath.Extension().ToCString()); + } + + if (theRole != Qt::DisplayRole) + return QVariant(); + + if (Column() == 0) + return aReport->DynamicType()->Name(); + + Message_MetricType aMetricType; + int aPosition; + if (MessageModel_TreeModel::IsMetricColumn (Column(), aMetricType, aPosition)) + { + if (aPosition == 0) return CumulativeMetric (aReport, aMetricType); + else if (aPosition == 1) return "100"; + } + return QVariant(); +} + +// ======================================================================= +// function : initRowCount +// purpose : +// ======================================================================= +int MessageModel_ItemReport::initRowCount() const +{ + const Handle(Message_Report)& aReport = getReport(); + if (aReport.IsNull()) + return 0; + + MessageModel_ItemReport* aCurrentItem = (MessageModel_ItemReport*)this; + for (int aGravityId = Message_Trace; aGravityId <= Message_Fail; aGravityId++) + { + const Message_ListOfAlert& anAlerts = aReport->GetAlerts ((Message_Gravity)aGravityId); + for (Message_ListOfAlert::Iterator anIt(anAlerts); anIt.More(); anIt.Next()) + { + Message_ListOfAlert aCurAlerts; + aCurAlerts.Append (anIt.Value()); + aCurrentItem->myChildAlerts.Bind(myChildAlerts.Size(), aCurAlerts); + } + } + return aCurrentItem->myChildAlerts.Size(); +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemReport::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemAlert::CreateItem (currentItem(), theRow, theColumn); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageModel_ItemReport::Init() +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (Parent()); + myReport = aRootItem ? aRootItem->GetReport (Row(), myDescription) : Handle(Message_Report)(); + + MessageModel_ItemBase::Init(); +} + +// ======================================================================= +// function : getReport +// purpose : +// ======================================================================= +const Handle(Message_Report)& MessageModel_ItemReport::getReport() const +{ + initItem(); + return myReport; +} + +// ======================================================================= +// function : Reset +// purpose : +// ======================================================================= +void MessageModel_ItemReport::Reset() +{ + MessageModel_ItemBase::Reset(); + myReport = Handle(Message_Report)(); + myChildAlerts.Clear(); +} + +// ======================================================================= +// function : initItem +// purpose : +// ======================================================================= +void MessageModel_ItemReport::initItem() const +{ + if (IsInitialized()) + return; + const_cast(this)->Init(); +} + +// ======================================================================= +// function : FindReportItem +// purpose : +// ======================================================================= +MessageModel_ItemReportPtr MessageModel_ItemReport::FindReportItem (const TreeModel_ItemBasePtr& theItem) +{ + TreeModel_ItemBasePtr anItem = theItem; + while (anItem) + { + if (MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItem)) + return aReportItem; + + anItem = anItem->Parent(); + } + return MessageModel_ItemReportPtr(); +} + +// ======================================================================= +// function : FindReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageModel_ItemReport::FindReport (const MessageModel_ItemBasePtr& theItem) +{ + Handle(Message_Report) aReport; + + MessageModel_ItemBasePtr anItem = theItem; + while (anItem) + { + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItem); + + if (aReportItem) + return aReportItem->GetReport(); + + anItem = itemDynamicCast(anItem->Parent()); + } + return NULL; +} + +// ======================================================================= +// function : CumulativeMetric +// purpose : +// ======================================================================= +Standard_Real MessageModel_ItemReport::CumulativeMetric (const Handle(Message_Report)& theReport, const Message_MetricType theMetricType) +{ + if (!theReport->ActiveMetrics().Contains (theMetricType)) + return 0; + + Standard_Real aMetric = 0; + for (int iGravity = Message_Trace; iGravity <= Message_Fail; ++iGravity) + { + const Message_ListOfAlert& anAlerts = theReport->GetAlerts ((Message_Gravity)iGravity); + Handle(Message_AttributeMeter) aFirstAttribute, aLastAttribute; + for (Message_ListOfAlert::Iterator anAlertsIterator (anAlerts); anAlertsIterator.More(); anAlertsIterator.Next()) + { + Handle(Message_AlertExtended) anAlert = Handle(Message_AlertExtended)::DownCast (anAlertsIterator.Value()); + if (anAlert.IsNull()) + continue; + Handle(Message_AttributeMeter) anAttribute = Handle(Message_AttributeMeter)::DownCast (anAlert->Attribute()); + if (anAttribute.IsNull()) + continue; + if (aFirstAttribute.IsNull()) + aFirstAttribute = anAttribute; + else + aLastAttribute = anAttribute; + } + if (aFirstAttribute.IsNull()) + continue; + if (aLastAttribute.IsNull()) + aLastAttribute = aFirstAttribute; + + aMetric += aLastAttribute->StopValue (theMetricType) - aFirstAttribute->StartValue (theMetricType); + } + return aMetric; +} diff --git a/tools/MessageModel/MessageModel_ItemReport.hxx b/tools/MessageModel/MessageModel_ItemReport.hxx new file mode 100644 index 0000000000..f03d98e58d --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemReport.hxx @@ -0,0 +1,117 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemReport_H +#define MessageModel_ItemReport_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class MessageModel_ItemReport; +typedef QExplicitlySharedDataPointer MessageModel_ItemReportPtr; + +//! \class MessageModel_ItemReport +//! This item is connected to Message_Alert. +//! Parent is MessageModel_ItemRoot, children are MessageModel_ItemAlert or no children +class MessageModel_ItemReport : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + //! \param theRow the item row positition in the parent item + //! \param theColumn the item column positition in the parent item + //! \return the pointer to the created item + static MessageModel_ItemReportPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemReportPtr (new MessageModel_ItemReport (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemReport() Standard_OVERRIDE {}; + + //! Returns the current shape + const Handle(Message_Report)& GetReport() const { return myReport; } + + //! Returns alert of the report for the parameter row + Standard_Boolean GetChildAlerts (const int theRow, Message_ListOfAlert& theAlerts) const { return myChildAlerts.Find(theRow, theAlerts); } + + //! Returns the report description or NULL + const TCollection_AsciiString& GetDescription() const { return myDescription; } + + //! Inits the item, fills internal containers + Standard_EXPORT virtual void Init() Standard_OVERRIDE; + + //! Resets cached values + Standard_EXPORT virtual void Reset() Standard_OVERRIDE; + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + Standard_EXPORT virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + Standard_EXPORT virtual int initRowCount() const Standard_OVERRIDE; + + //! Returns report of the tree model item. Iterates up by parents intil the report item is found. + //! \return an item or NULL + Standard_EXPORT static MessageModel_ItemReportPtr FindReportItem (const TreeModel_ItemBasePtr& theItem); + + //! Returns report of the item + static Handle(Message_Report) FindReport (const MessageModel_ItemBasePtr& thetItem); + + //! Returns report cumulative metric as stop time of the last alert minus start time of the first alert + Standard_EXPORT static Standard_Real CumulativeMetric (const Handle(Message_Report)& theReport, const Message_MetricType theMetricType); + +protected: + + //! Initialize the current item. It is empty because Reset() is also empty. + virtual void initItem() const Standard_OVERRIDE; + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + + //! Returns number of child shapes. Init item if it is not initialized + //! \return integer value + int getRowCount() const; + + //! Returns current shape, initialized item if it has not been initialized yet + //! \return shape value + const Handle(Message_Report)& getReport() const; + +private: + + //! Constructor + MessageModel_ItemReport (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn) {} + +private: + + NCollection_DataMap myChildAlerts; //!< container of child alerts + + Handle(Message_Report) myReport; //!< current report + TCollection_AsciiString myDescription; //!< description +}; + +#endif diff --git a/tools/MessageModel/MessageModel_ItemRoot.cxx b/tools/MessageModel/MessageModel_ItemRoot.cxx new file mode 100644 index 0000000000..b42dcc8864 --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.cxx @@ -0,0 +1,96 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + + +#include +#include + +// ======================================================================= +// function : SetReport +// purpose : +// ======================================================================= +void MessageModel_ItemRoot::SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aRowId == theRowId) + break; + } + aReportsIt.Value().myReport = theReport; + aReportsIt.Value().myDescription = theReportDescription; +} + +// ======================================================================= +// function : GetReport +// purpose : +// ======================================================================= +const Handle(Message_Report)& MessageModel_ItemRoot::GetReport (const int theRowId, + TCollection_AsciiString& theReportDescription) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aRowId == theRowId) + break; + } + theReportDescription = aReportsIt.Value().myDescription; + return aReportsIt.Value().myReport; +} + +// ======================================================================= +// function : HasReport +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_ItemRoot::HasReport (const Handle(Message_Report)& theReport) +{ + NCollection_List::Iterator aReportsIt (myReports); + for (int aRowId = 0; aReportsIt.More(); aReportsIt.Next(), aRowId++) + { + if (aReportsIt.Value().myReport == theReport) + return Standard_True; + } + return Standard_False; +} + +// ======================================================================= +// function : initValue +// purpose : +// ======================================================================= +QVariant MessageModel_ItemRoot::initValue (const int theRole) const +{ + QVariant aParentValue = MessageModel_ItemBase::initValue (theRole); + if (aParentValue.isValid()) + return aParentValue; + + if (Column() != 0) + return QVariant(); + + if (theRole == Qt::DisplayRole) + return myName.IsEmpty() ? "Message_Reports" : myName.ToCString(); + + return QVariant(); +} + +// ======================================================================= +// function : createChild +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_ItemRoot::createChild (int theRow, int theColumn) +{ + return MessageModel_ItemReport::CreateItem (currentItem(), theRow, theColumn); +} + diff --git a/tools/MessageModel/MessageModel_ItemRoot.hxx b/tools/MessageModel/MessageModel_ItemRoot.hxx new file mode 100644 index 0000000000..197bd1eb9a --- /dev/null +++ b/tools/MessageModel/MessageModel_ItemRoot.hxx @@ -0,0 +1,126 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_ItemRoot_H +#define MessageModel_ItemRoot_H + +#include +#include +#include +#include +#include + +#include + +class MessageModel_ItemRoot; +typedef QExplicitlySharedDataPointer MessageModel_ItemRootPtr; + +//! \struct to extend report by description +struct MessageModel_ReportInformation +{ + //! Constructor + MessageModel_ReportInformation (Handle(Message_Report) theReport, const TCollection_AsciiString& theDescription) + : myReport (theReport), myDescription (theDescription) {} + + Handle(Message_Report) myReport; //! report + TCollection_AsciiString myDescription; //! report description +}; + +//! \class MessageModel_ItemRoot +//! Collects message reports that should be visualized in tree view. Reports are cached and if reports are not needed, +//! cache should be cleared using RemoveAllReports +//! Parent is NULL, children are MessageModel_ItemReport items. +class MessageModel_ItemRoot : public MessageModel_ItemBase +{ +public: + + //! Creates an item wrapped by a shared pointer + static MessageModel_ItemRootPtr CreateItem (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + { return MessageModel_ItemRootPtr (new MessageModel_ItemRoot (theParent, theRow, theColumn)); } + + //! Destructor + virtual ~MessageModel_ItemRoot() Standard_OVERRIDE {}; + + //! Appends new report + //! \param theReport a report instance + //! \param theReportDescription an additional report information + void AddReport (const Handle(Message_Report)& theReport, const TCollection_AsciiString& theReportDescription) + { myReports.Append (MessageModel_ReportInformation (theReport, theReportDescription)); } + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Returns true if report exists is in the list of the current reports + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //!< Returns processed reports + const NCollection_List& Reports() const { return myReports; } + + //! Clears internal container of added reports + void RemoveAllReports() { myReports.Clear(); } + + //! Returns report by the number + //! \param theRowId an index of the report in the internal container. + Standard_EXPORT const Handle(Message_Report)& GetReport (const int theRowId, TCollection_AsciiString& theReportDescription); + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void SetReversed (const Standard_Boolean& theReversed) { myIsReversed = theReversed; } + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + void SetName (const TCollection_AsciiString& theName) { myName = theName; } + +protected: + + //! Return data value for the role. + //! \param theRole a value role + //! \return the value + virtual QVariant initValue (const int theRole) const Standard_OVERRIDE; + + //! \return number of children. + virtual int initRowCount() const Standard_OVERRIDE { return myReports.Size(); } + + //! Creates a child item in the given position. + //! \param theRow the child row position + //! \param theColumn the child column position + //! \return the created item + virtual TreeModel_ItemBasePtr createChild (int theRow, int theColumn) Standard_OVERRIDE; + +private: + + //! Constructor + //! param theParent a parent item + MessageModel_ItemRoot (TreeModel_ItemBasePtr theParent, const int theRow, const int theColumn) + : MessageModel_ItemBase (theParent, theRow, theColumn), myIsReversed (Standard_False) {} + +private: + + NCollection_List myReports; //!< reports sent by algorithms + Standard_Boolean myIsReversed; //!< state if the model is reversed + TCollection_AsciiString myName; //!< DisplayRole data, if defined +}; + +#endif diff --git a/tools/MessageModel/MessageModel_Tools.cxx b/tools/MessageModel/MessageModel_Tools.cxx new file mode 100644 index 0000000000..5348d47ca8 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.cxx @@ -0,0 +1,59 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ======================================================================= +// function : GetPointerInfo +// purpose : +// ======================================================================= +TCollection_AsciiString MessageModel_Tools::GetPointerInfo (const Handle(Standard_Transient)& thePointer, const bool isShortInfo) +{ + if (thePointer.IsNull()) + return TCollection_AsciiString(); + + std::ostringstream aPtrStr; + aPtrStr << thePointer.operator->(); + if (!isShortInfo) + return aPtrStr.str().c_str(); + + TCollection_AsciiString anInfoPtr (aPtrStr.str().c_str()); + for (int aSymbolId = 1; aSymbolId < anInfoPtr.Length(); aSymbolId++) + { + if (anInfoPtr.Value(aSymbolId) != '0') + { + anInfoPtr = anInfoPtr.SubString (aSymbolId, anInfoPtr.Length()); + anInfoPtr.Prepend("0x"); + return anInfoPtr; + } + } + return aPtrStr.str().c_str(); +} diff --git a/tools/MessageModel/MessageModel_Tools.hxx b/tools/MessageModel/MessageModel_Tools.hxx new file mode 100644 index 0000000000..c83922aed6 --- /dev/null +++ b/tools/MessageModel/MessageModel_Tools.hxx @@ -0,0 +1,53 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_Tools_H +#define MessageModel_Tools_H + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +class Message_Alert; +class ViewControl_TableModelValues; + +class ViewControl_Table; + +//! \class MessageModel_Tools +//! It gives auxiliary methods for Message classes manipulation +class MessageModel_Tools +{ +public: + + //! Convert pointer to string value + //! \param thePointer a pointer + //! \param isShortInfo if true, all '0' symbols in the beginning of the pointer are skipped + //! \return the string value + Standard_EXPORT static TCollection_AsciiString GetPointerInfo (const Handle(Standard_Transient)& thePointer, + const bool isShortInfo = true); +}; + +#endif diff --git a/tools/MessageModel/MessageModel_TreeModel.cxx b/tools/MessageModel/MessageModel_TreeModel.cxx new file mode 100644 index 0000000000..85b539817b --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.cxx @@ -0,0 +1,207 @@ +// 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 + +const int COLUMN_REAL_VALUE_WIDTH = 115; +const int COLUMN_PERCENT_VALUE_WIDTH = 40; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageModel_TreeModel::MessageModel_TreeModel (QObject* theParent) +: TreeModel_ModelBase (theParent), myIsReversed (Standard_False) +{ +} + +// ======================================================================= +// function : InitColumns +// purpose : +// ======================================================================= +void MessageModel_TreeModel::InitColumns() +{ + TreeModel_ModelBase::InitColumns(); + // 0 - Name, 1 - visibility, 2 - Row + + int aNextIndex = 3; + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + OSD_MemInfo::Counter aMemInfo; + bool isMemInfo = Message::ToOSDMetric (aMetricType, aMemInfo); + + SetHeaderItem (aNextIndex++, + TreeModel_HeaderSection (QString("%1 [%2]").arg (Message::MetricToString (aMetricType)).arg(isMemInfo ? "Mb" : "s"), + COLUMN_REAL_VALUE_WIDTH)); + SetHeaderItem (aNextIndex++, TreeModel_HeaderSection ("%", COLUMN_PERCENT_VALUE_WIDTH)); + } +} + +// ======================================================================= +// function : GetMetricColumns +// purpose : +// ======================================================================= +void MessageModel_TreeModel::GetMetricColumns (const Message_MetricType theMetricType, QList& theMetricColumns) +{ + theMetricColumns.clear(); + int aNextIndex = 3; // after default parent columns, see InitColumns + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + if (theMetricType != (Message_MetricType)aMetricId) + { + aNextIndex += 2; + continue; + } + theMetricColumns.append (aNextIndex++); + theMetricColumns.append (aNextIndex++); + } +} + +// ======================================================================= +// function : IsMetricColumn +// purpose : +// ======================================================================= +bool MessageModel_TreeModel::IsMetricColumn (const int theColumnId, Message_MetricType& theMetricType, int& thePosition) +{ + int aNextIndex = 3; // after default parent columns, see InitColumns + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + if (theColumnId == aNextIndex || theColumnId == aNextIndex + 1) + { + theMetricType = (Message_MetricType)aMetricId; + thePosition = theColumnId - aNextIndex; + return true; + } + aNextIndex += 2; + } + return false; +} + +// ======================================================================= +// function : createRootItem +// purpose : +// ======================================================================= +TreeModel_ItemBasePtr MessageModel_TreeModel::createRootItem (const int theColumnId) +{ + return MessageModel_ItemRoot::CreateItem (TreeModel_ItemBasePtr(), 0, theColumnId); +} + +// ======================================================================= +// function : HasShape +// purpose : +// ======================================================================= +Standard_Boolean MessageModel_TreeModel::HasReport (const Handle(Message_Report)& theReport) +{ + if (columnCount() == 0) + return Standard_False; + + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + return aRootItem && aRootItem->HasReport (theReport); +} + +// ======================================================================= +// function : AddShape +// purpose : +// ======================================================================= +void MessageModel_TreeModel::AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (!aRootItem) + continue; + aRootItem->AddReport (theReport, theReportDescription); + aRootItem->SetReversed (myIsReversed); + } + + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : SetReport +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (!aRootItem) + continue; + aRootItem->SetReport (theRowId, theReport, theReportDescription); + } + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : Reports +// purpose : +// ======================================================================= +const NCollection_List& MessageModel_TreeModel::Reports() const +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + return aRootItem->Reports(); +} + +// ======================================================================= +// function : SetReversed +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetReversed (const Standard_Boolean& theReversed) +{ + myIsReversed = theReversed; + + for (int aColId = 0, aNbColumns = columnCount(); aColId < aNbColumns; aColId++) + { + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (aColId)); + if (aRootItem) + aRootItem->SetReversed (myIsReversed); + } + + Reset(); + EmitLayoutChanged(); +} + +// ======================================================================= +// function : UpdateTreeModel +// purpose : +// ======================================================================= +void MessageModel_TreeModel::SetRootItemName (const TCollection_AsciiString& theName) +{ + MessageModel_ItemRootPtr aRootItem = itemDynamicCast (RootItem (0)); + if (aRootItem) + aRootItem->SetName (theName); +} + +// ======================================================================= +// function : UpdateTreeModel +// purpose : +// ======================================================================= +void MessageModel_TreeModel::UpdateTreeModel() +{ + Reset(); + EmitLayoutChanged(); +} diff --git a/tools/MessageModel/MessageModel_TreeModel.hxx b/tools/MessageModel/MessageModel_TreeModel.hxx new file mode 100644 index 0000000000..01eeba4144 --- /dev/null +++ b/tools/MessageModel/MessageModel_TreeModel.hxx @@ -0,0 +1,105 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageModel_TreeModel_H +#define MessageModel_TreeModel_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +class MessageModel_TreeModel; + +//! \class MessageModel_TreeModel +//! View model to visualize MessageReport/s content +class MessageModel_TreeModel : public TreeModel_ModelBase +{ +public: + + //! Constructor + Standard_EXPORT MessageModel_TreeModel (QObject* theParent); + + //! Destructor + virtual ~MessageModel_TreeModel() Standard_OVERRIDE {}; + + //! Creates model columns and root items. + Standard_EXPORT virtual void InitColumns() Standard_OVERRIDE; + + //!< Returns columns of the model for the metric + //!< \param theMetricType metric + //!< \param theMetricColumns [out] container of metric columns + static Standard_EXPORT void GetMetricColumns (const Message_MetricType theMetricType, QList& theMetricColumns); + + //!< Returns metric type for the column + //!< \param theColumnId [in] index of the tree column + //!< \param theMetricType [out] metric type if found + //!< \param thePosition [out] index of the metric column, 0 - is metric, 1 - is delta + //!< \return true if the column has metric parameters + static Standard_EXPORT bool IsMetricColumn (const int theColumnId, Message_MetricType& theMetricType, int& thePosition); + + //! Returns true if parameter report was added into the model + //! \param theReport a report instance + //! \return boolen value + Standard_EXPORT Standard_Boolean HasReport (const Handle(Message_Report)& theReport); + + //! Add shape, append it to the model root item + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void AddReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //! Set report, se it into the given row index + //! \param theRowId a report child row + //! \param theReport a report instance + //! \param theReportDescription an additional report information + Standard_EXPORT void SetReport (const int theRowId, const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + + //!< Returns processed reports + Standard_EXPORT const NCollection_List& Reports() const; + + //! Set the view reversed. If reversed, the last report alert is upper item in the tree view + //! \param theReversed boolean flag + Standard_EXPORT void SetReversed (const Standard_Boolean& theReversed); + + //! Return whether the view is reversed or not + //! \return boolean value + Standard_Boolean IsReversed() const { return myIsReversed; }; + + //! Sets the text value of the Root item, only "Name" column accepts the parameter value + //! \theName visulized text of root item + Standard_EXPORT void SetRootItemName (const TCollection_AsciiString& theName); + + //! Updates tree model + Standard_EXPORT void UpdateTreeModel(); + +protected: + //! Creates root item + //! \param theColumnId index of a column + virtual TreeModel_ItemBasePtr createRootItem (const int theColumnId) Standard_OVERRIDE; + +private: + Standard_Boolean myIsReversed; //!< state if the model is reversed +}; + +#endif diff --git a/tools/MessageModel/icons/item_shape.png b/tools/MessageModel/icons/item_shape.png new file mode 100644 index 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_streamValues.png b/tools/MessageModel/icons/item_streamValues.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_streamValues.svg b/tools/MessageModel/icons/item_streamValues.svg new file mode 100644 index 0000000000..38b1032701 --- /dev/null +++ b/tools/MessageModel/icons/item_streamValues.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/tools/MessageView/FILES b/tools/MessageView/FILES new file mode 100644 index 0000000000..5fe2f52661 --- /dev/null +++ b/tools/MessageView/FILES @@ -0,0 +1,8 @@ +MessageView_ActionsTest.cxx +MessageView_ActionsTest.hxx +MessageView_Communicator.cxx +MessageView_Communicator.hxx +MessageView_VisibilityState.cxx +MessageView_VisibilityState.hxx +MessageView_Window.cxx +MessageView_Window.hxx diff --git a/tools/MessageView/MessageView_ActionsTest.cxx b/tools/MessageView/MessageView_ActionsTest.cxx new file mode 100644 index 0000000000..26274672a7 --- /dev/null +++ b/tools/MessageView/MessageView_ActionsTest.cxx @@ -0,0 +1,474 @@ +// 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 + +//#define DEBUG_ALERTS + +#ifdef DEBUG_ALERTS +#include +#include +#endif + +#include + + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageView_ActionsTest::MessageView_ActionsTest (QWidget* theParent, + MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel) +: QObject (theParent), myTreeModel (theTreeModel), mySelectionModel (theModel) +{ + myActions.insert (MessageModel_ActionType_TestMetric, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestMetric()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestProperties, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestPropertyPanel()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestMessenger, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestMessenger()), parent(), this)); + myActions.insert (MessageModel_ActionType_TestReportTree, + ViewControl_Tools::CreateAction ("Test ", SLOT (OnTestReportTree()), parent(), this)); +} + +// ======================================================================= +// function : AddMenuActions +// purpose : +// ======================================================================= +void MessageView_ActionsTest::AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu) +{ + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + MessageModel_ItemAlertPtr anAlertItem; + for (QModelIndexList::const_iterator aSelIt = theSelectedIndices.begin(); aSelIt != theSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + + anAlertItem = itemDynamicCast (anItemBase); + if (anAlertItem) + break; + } + + if (aReportItem && !aReportItem->GetReport().IsNull()) + { + theMenu->addAction (myActions[MessageModel_ActionType_TestMetric]); + theMenu->addAction (myActions[MessageModel_ActionType_TestProperties]); + theMenu->addAction (myActions[MessageModel_ActionType_TestMessenger]); + theMenu->addAction (myActions[MessageModel_ActionType_TestReportTree]); + + bool isReportEnabled = aReportItem->GetReport()->IsActiveInMessenger(); + + myActions[MessageModel_ActionType_TestMetric]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestProperties]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestMessenger]->setEnabled (isReportEnabled); + myActions[MessageModel_ActionType_TestReportTree]->setEnabled (isReportEnabled); + } + theMenu->addSeparator(); +} + +// ======================================================================= +// function : getSelectedReport +// purpose : +// ======================================================================= +Handle(Message_Report) MessageView_ActionsTest::getSelectedReport (QModelIndex& theReportIndex) const +{ + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = mySelectionModel->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aReportItem = itemDynamicCast (anItemBase); + theReportIndex = anIndex; + if (aReportItem) + break; + } + if (!aReportItem) + return NULL; + + return aReportItem->GetReport(); +} + +// ======================================================================= +// function : OnTestMetric +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestMetric() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestMetric()"); + unsigned int start_time = clock(); + //Standard_Real aSystemSeconds, aCurrentSeconds; + //OSD_Chronometer::GetThreadCPU (aCurrentSeconds, aSystemSeconds); + + Standard_Integer aCounter = 1500;//0; + Standard_Real aValue = 0., aValue2 = 0.1; + + double* aMemValue; + for (int aTopIt = 0; aTopIt < 4; aTopIt++) + { + MESSAGE_INFO ("Calculate"); + for (int j = 0; j < aCounter; j++) + { + for (int i = 0; i < aCounter; i++) + { + aValue = (aValue * 2. + 3.) * 0.5 - 0.3 * 0.5; + + Standard_Real aValue3 = aValue + aValue2 * 0.2; + (void)aValue3; + + aMemValue = new double; + } + } + } + + //((MessageModel_TreeModel*)mySelectionModel->model())->EmitLayoutChanged(); + + myTreeModel->UpdateTreeModel(); + + //Standard_Real aSystemSeconds1, aCurrentSeconds1; + //OSD_Chronometer::GetThreadCPU (aCurrentSeconds1, aSystemSeconds1); + + //std::cout << aValue << std::endl; + //std::cout << "user time = " << aCurrentSeconds1 - aCurrentSeconds + // << ", system time = " << aSystemSeconds1 - aSystemSeconds << std::endl; + + unsigned int end_time = clock(); + std::cout << "clock() = " << end_time - start_time << std::endl; +#endif +} + +// ======================================================================= +// function : OnTestPropertyPanel +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestPropertyPanel() +{ +#ifdef DEBUG_ALERTS + QModelIndex aReportIndex; + Handle(Message_Report) aReport = getSelectedReport (aReportIndex); + if (aReport.IsNull()) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestPropertyPanel()"); + + // gp_XYZ + { + gp_XYZ aCoords (1.3, 2.3, 3.4); + Standard_SStream aStream; + aCoords.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_XYZ"); + } + // gp_Dir + { + gp_Dir aDir (0.3, 0.3, 0.4); + Standard_SStream aStream; + aDir.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_Dir"); + } + // gp_Ax1 + { + gp_Ax1 aCoords (gp_Pnt (1.3, 2.3, 3.4), gp_Dir (0.3, 0.3, 0.4)); + Standard_SStream aStream; + aCoords.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_Ax1"); + } + // gp_Ax2 + { + gp_Ax2 aCoords (gp_Pnt (10.3, 20.3, 30.4), gp_Dir (0.3, 0.3, 0.4)); + Standard_SStream aStream; + aCoords.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_Ax2"); + } + // gp_Ax3 + { + gp_Ax3 aPln (gp_Pnt (10., 20., 15.), gp_Dir (0., 0., 1.), gp_Dir (1., 0., 0.)); + Standard_SStream aStream; + aPln.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_Ax3"); + } + // gp_Trsf + { + gp_Trsf aTrsf; + aTrsf.SetRotation (gp::OZ(), 0.3); + aTrsf.SetTranslationPart (gp_Vec (15., 15., 15.)); + aTrsf.SetScaleFactor (3.); + + Standard_SStream aStream; + aTrsf.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "gp_Trsf"); + } + // Bnd_Box + { + Bnd_Box aBox (gp_Pnt (20., 15., 10.), gp_Pnt (25., 20., 15.)); + Standard_SStream aStream; + aBox.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Bnd_Box"); + } + // Bnd_OBB + { + Bnd_OBB anOBB (gp_Pnt (-10., -15., -10.), gp_Dir (1., 0., 0.), gp_Dir (0., 1., 0.), gp_Dir (0., 0., 1.), + 5., 10., 5.); + Standard_SStream aStream; + anOBB.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Bnd_OBB"); + } + // Quantity_ColorRGBA + { + Quantity_ColorRGBA aColor (0.2f, 0.8f, 0.8f, 0.2f); + Standard_SStream aStream; + aColor.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Quantity_ColorRGBA"); + } + // Quantity_Color + { + Quantity_Color aColor (0.8, 0.8, 0.8, Quantity_TOC_RGB); + Standard_SStream aStream; + aColor.DumpJson (aStream); + MESSAGE_INFO_STREAM(aStream, "Quantity_Color"); + } + + // stream of some table values + { + Standard_SStream aStream; + OCCT_DUMP_FIELD_VALUES_NUMERICAL (aStream, "value_1", 1, 100); + OCCT_DUMP_FIELD_VALUES_STRING (aStream, "value_2", 2, "value_1", "value_2"); + + MESSAGE_INFO_STREAM(aStream, "Table: Name to value"); + } + + // SHAPE messages + { + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + } + + myTreeModel->UpdateTreeModel(); +#endif +} + +// ======================================================================= +// function : createShapeOnLevel +// purpose : +// ======================================================================= +void createShapeOnLevel() +{ + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("createShapeOnLevel") + + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge ON LEVEL"); + + aMessenger << "Shape message edge" << aShape; +} + +// ======================================================================= +// function : createShape +// purpose : +// ======================================================================= +void createShape() +{ + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + + aMessenger << "Shape message edge" << aShape; + + createShapeOnLevel(); +} + +// ======================================================================= +// function : OnTestMessenger +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestMessenger() +{ + // string messages + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + Standard_Integer aTraceLevel_prev = Message::DefaultMessenger()->TraceLevel(); + Message::DefaultMessenger()->SetTraceLevel (1); + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestMessenger()") + + aMessenger << "IGESBasic_Hierarchy" << Message_EndLine; + aMessenger << "Number of property valueaMessenger : " << 15 << Message_EndLine; + aMessenger << "Line Font : " << 1 << Message_EndLine << "View Number : " << 3 << Message_EndLine; + aMessenger << "Entity level : " << 1 << Message_EndLine; + aMessenger << "Blank statuaMessenger : " << 0 << Message_EndLine; + aMessenger << "Line weight : " << 14 << Message_EndLine; + aMessenger << "Color number : " << 5 << Message_EndLine; + + // stream messages + // gp_XYZ + { + gp_XYZ aCoords (1.3, 2.3, 3.4); + Standard_SStream aStream; + aCoords.DumpJson (aStream); + aMessenger << "gp_XYZ" << aStream << Message_EndLine; + } + // Bnd_Box + { + Bnd_Box aBox (gp_Pnt (20., 15., 10.), gp_Pnt (25., 20., 15.)); + Standard_SStream aStream; + aBox.DumpJson (aStream); + aMessenger << "Bnd_Box" << aStream; + } + + // object messages + Handle(Standard_Transient) anObject = new Message_AlertExtended(); + aMessenger << "Message_AlertExtended" << anObject; + + // shape messages + { + BRepBuilderAPI_MakeEdge aBuilder (gp_Pnt (0., 0., 0.), gp_Pnt (20., 10., 20.)); + TopoDS_Shape aShape = aBuilder.Shape(); + + MESSAGE_INFO_SHAPE (aShape, "Shape message edge"); + + aMessenger << "Shape message edge" << aShape; + + createShape(); + } + myTreeModel->UpdateTreeModel(); + Message::DefaultMessenger()->SetTraceLevel (aTraceLevel_prev); +} + +// ======================================================================= +// function : levelAlerts +// purpose : +// ======================================================================= +void levelAlerts (const int theCurrentLevel, const int theTopLevel) +{ + if (theTopLevel - theCurrentLevel <= 0) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY (TCollection_AsciiString ("Level: " ) + theCurrentLevel) + + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + aMessenger << "Alert: " << 1 << ", " << 2 << Message_EndLine; + aMessenger << "Alert: " << 3 << ", " << 4 << Message_EndLine; + + for (int i = 0; i < 2; i++) + levelAlerts (theCurrentLevel + 1, theTopLevel); + + aMessenger << "Alert: " << 4 << ", " << 5 << Message_EndLine; +} + +// ======================================================================= +// function : levelAlert +// purpose : +// ======================================================================= +void levelAlert (const int theCurrentLevel, const int theTopLevel) +{ + if (theTopLevel - theCurrentLevel <= 0) + return; + + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("levelAlert") + + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + aMessenger << "Level: " << theCurrentLevel << "(Single, no alerts on the level)" << Message_EndLine; + + for (int i = 0; i < 2; i++) + levelAlerts (theCurrentLevel + 1, theTopLevel); +} + +// ======================================================================= +// function : OnTestMessenger +// purpose : +// ======================================================================= +void MessageView_ActionsTest::OnTestReportTree() +{ + OCCT_ADD_MESSAGE_LEVEL_SENTRY ("MessageModel_Actions::OnTestReportTree()") + const Handle(Message_Messenger)& aMessenger = Message::DefaultMessenger(); + + // string messages + //aMessenger << "Alert: " << 1 << Message_EndLine; + //aMessenger << "Alert: " << 2 << Message_EndLine; + + int aTopLevel = 3; + levelAlerts (1, aTopLevel); + + //aMessenger << "Alert: " << 3 << Message_EndLine; + //levelAlerts (1, aTopLevel); + + aMessenger << "Alert: " << 4 << Message_EndLine; + levelAlert (1, aTopLevel); + + myTreeModel->UpdateTreeModel(); +} + diff --git a/tools/MessageView/MessageView_ActionsTest.hxx b/tools/MessageView/MessageView_ActionsTest.hxx new file mode 100644 index 0000000000..54943819e6 --- /dev/null +++ b/tools/MessageView/MessageView_ActionsTest.hxx @@ -0,0 +1,82 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_ActionsTest_H +#define MessageView_ActionsTest_H + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +class Message_Report; +class MessageModel_TreeModel; +class QItemSelectionModel; + +class QAction; +class QWidget; +class QMenu; + +//! \class MessageView_ActionsTest +//! Window that unites all MessageView controls. +class MessageView_ActionsTest : public QObject +{ + Q_OBJECT +public: + + //! Constructor + MessageView_ActionsTest (QWidget* theParent, MessageModel_TreeModel* theTreeModel, QItemSelectionModel* theModel); + + //! Destructor + virtual ~MessageView_ActionsTest() {} + + //! Fills popup menu with actions depending on the current selection + //! \param theSelectedIndices tree model selected indices + //! \param theMenu menu to be filled + Standard_EXPORT void AddMenuActions (const QModelIndexList& theSelectedIndices, QMenu* theMenu); + +public slots: + //! Sending several alerts to check metric of message-alert-tool mechanizm + void OnTestMetric(); + + //! Sending several alerts to check property panel/presentations of message-alert-tool mechanizm + void OnTestPropertyPanel(); + + //! Sending several alerts to check property panel/presentations of messenger-alert-tool mechanizm + void OnTestMessenger(); + + //! Check tree of alerts + void OnTestReportTree(); + +protected: + //! Returns report of selected tree view item if a report item is selected + //! \param theReportIndex tree model index of the found report + //! \return report instance or NULL + Handle(Message_Report) getSelectedReport (QModelIndex& theReportIndex) const; + +protected: + MessageModel_TreeModel* myTreeModel; //< tree model + QItemSelectionModel* mySelectionModel; //< selection model + QMap myActions; //!< container of all actions +}; + +#endif diff --git a/tools/MessageView/MessageView_Communicator.cxx b/tools/MessageView/MessageView_Communicator.cxx new file mode 100644 index 0000000000..10b95480f7 --- /dev/null +++ b/tools/MessageView/MessageView_Communicator.cxx @@ -0,0 +1,26 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + + +// ======================================================================= +// function : CreateCommunicator +// purpose : Creates a communicator by the library loading +// ======================================================================= +Standard_EXPORTEXTERNC TInspectorAPI_Communicator* CreateCommunicator() +{ + return new MessageView_Communicator(); +} diff --git a/tools/MessageView/MessageView_Communicator.hxx b/tools/MessageView/MessageView_Communicator.hxx new file mode 100644 index 0000000000..7d93c21b55 --- /dev/null +++ b/tools/MessageView/MessageView_Communicator.hxx @@ -0,0 +1,66 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_Communicator_H +#define MessageView_Communicator_H + +#include +#include + +//! \class MessageView_Communicator. +//! \brief This is a connector from TInspector application to MessageView window +class MessageView_Communicator : public TInspectorAPI_Communicator +{ +public: + + //! Constructor + MessageView_Communicator() : TInspectorAPI_Communicator(), myWindow (new MessageView_Window (0)) {} + + //! Destructor + virtual ~MessageView_Communicator() Standard_OVERRIDE {} + + //! Provides the container with a parent where this container should be inserted. + //! If Qt implementation, it should be QWidget with QLayout set inside + //! \param theParent a parent class + virtual void SetParent (void* theParent) Standard_OVERRIDE { myWindow->SetParent (theParent); } + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + virtual void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) Standard_OVERRIDE + { myWindow->SetParameters (theParameters); } + + //! Provide container for actions available in inspector on general level + //! \param theMenu if Qt implementation, it is QMenu object + virtual void FillActionsMenu(void* theMenu) Standard_OVERRIDE { myWindow->FillActionsMenu (theMenu); } + + //! Returns plugin preferences, empty implementation by default + //! \param theItem container of preference elements + virtual void GetPreferences (TInspectorAPI_PreferencesDataMap& theItem) Standard_OVERRIDE + { myWindow->GetPreferences (theItem); } + + //! Stores plugin preferences, empty implementation by default + //! \param theItem container of preference elements + virtual void SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem) Standard_OVERRIDE + { myWindow->SetPreferences (theItem); } + + //! Calls update of the plugin's content + virtual void UpdateContent() Standard_OVERRIDE { myWindow->UpdateContent(); } + +private: + + MessageView_Window* myWindow; //!< current window +}; + +#endif diff --git a/tools/MessageView/MessageView_VisibilityState.cxx b/tools/MessageView/MessageView_VisibilityState.cxx new file mode 100644 index 0000000000..9b7993528a --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.cxx @@ -0,0 +1,150 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include +#include + +#include +#include + +#include + +// ======================================================================= +// function : CanBeVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::CanBeVisible (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (anAlertItem) + { + NCollection_List aPresentations; + anAlertItem->Presentations (aPresentations); + if (!aPresentations.IsEmpty()) + return true; + } + + return !Shape (theIndex).IsNull();// || hasTableValues (theIndex); +} + +// ======================================================================= +// function : SetVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::SetVisible (const QModelIndex& theIndex, const bool theState, const bool toEmitDataChanged) +{ + TopoDS_Shape aShape = Shape (theIndex); + if (aShape.IsNull()) + return false; + + myDisplayer->SetVisible (aShape, theState, myPresentationType); + + if (!theState) { + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (anAlertItem && !anAlertItem->GetCustomShape().IsNull()) + anAlertItem->SetCustomShape (TopoDS_Shape()); + } + + if (toEmitDataChanged) + { + QModelIndex anIndex = theIndex; + if (theIndex.column() != TreeModel_ColumnType_Visibility) + anIndex = theIndex.model()->index(theIndex.row(), TreeModel_ColumnType_Visibility, theIndex.parent()); + + getModel()->EmitDataChanged (anIndex, anIndex); + } + return true; +} + +// ======================================================================= +// function : IsVisible +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::IsVisible (const QModelIndex& theIndex) const +{ + return myDisplayer->IsVisible (Shape (theIndex), myPresentationType); +} + +// ======================================================================= +// function : OnClicked +// purpose : +// ======================================================================= +void MessageView_VisibilityState::OnClicked (const QModelIndex& theIndex) +{ + processClicked (theIndex); + emit itemClicked (theIndex); +} + +// ======================================================================= +// function : getAlertItem +// purpose : +// ======================================================================= +MessageModel_ItemAlertPtr MessageView_VisibilityState::getAlertItem (const QModelIndex& theIndex) const +{ + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (theIndex); + if (!anItemBase) + return MessageModel_ItemAlertPtr(); + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + return anAlertItem; +} + +// ======================================================================= +// function : Shape +// purpose : +// ======================================================================= +TopoDS_Shape MessageView_VisibilityState::Shape (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (!anAlertItem) + return TopoDS_Shape(); + + /*if (!anAlertItem->GetCustomShape().IsNull()) + return anAlertItem->GetCustomShape(); + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + return TopoDS_Shape(); + + Handle(Message_AlertExtended) anAlertExtended = Handle(Message_AlertExtended)::DownCast(anAlert); + if (anAlertExtended.IsNull()) + return TopoDS_Shape(); + + Handle(TopoDS_AlertAttribute) aShapeAttribute = Handle(TopoDS_AlertAttribute)::DownCast (anAlertExtended->Attribute()); + if (!aShapeAttribute.IsNull()) + return aShapeAttribute->GetShape(); + */ + return TopoDS_Shape(); +} + +// ======================================================================= +// function : hasTableValues +// purpose : +// ======================================================================= +bool MessageView_VisibilityState::hasTableValues (const QModelIndex& theIndex) const +{ + MessageModel_ItemAlertPtr anAlertItem = getAlertItem (theIndex); + if (!anAlertItem) + return false; + + Handle(Message_Alert) anAlert = anAlertItem->GetAlert(); + if (anAlert.IsNull()) + return false; + + if (anAlert->IsKind (STANDARD_TYPE (Message_AttributeStream))) + return true; + + return false; +} \ No newline at end of file diff --git a/tools/MessageView/MessageView_VisibilityState.hxx b/tools/MessageView/MessageView_VisibilityState.hxx new file mode 100644 index 0000000000..b26e73f4ef --- /dev/null +++ b/tools/MessageView/MessageView_VisibilityState.hxx @@ -0,0 +1,99 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_VisibilityState_H +#define MessageView_VisibilityState_H + +#include + +#include + +#include + +#include +#include +#include + +class TreeModel_ModelBase; + +//! \class MessageView_VisibilityState +//! \brief Class provides connection between model and visualization control +class MessageView_VisibilityState : public QObject, public TreeModel_VisibilityState +{ + Q_OBJECT +public: + //! Constructor + MessageView_VisibilityState (TreeModel_ModelBase* theModel) + : TreeModel_VisibilityState (theModel), myPresentationType (View_PresentationType_Main) {} + + //! Destructor + ~MessageView_VisibilityState() {} + + //! Sets current displayer + //! \theDisplayer class that provides connection to visualized objects + void SetDisplayer (View_Displayer* theDisplayer) { myDisplayer = theDisplayer; } + + //! Sets presentation type for displayer + //! \param theType type value + void SetPresentationType (const View_PresentationType theType) { myPresentationType = theType; } + + //! Returns true if visibility of the item can be changed + //! \param theIndex tree model index + //! \return boolean value + Standard_EXPORT virtual bool CanBeVisible (const QModelIndex& theIndex) const Standard_OVERRIDE; + + //! Sets visibility state + //! \theIndex tree model index + //! \param theState visibility state + //! \param toEmitDataChanged boolean flag whether emit of the model should be done immediatelly + //! \return true if state is changed + Standard_EXPORT virtual bool SetVisible (const QModelIndex& theIndex, const bool theState, const bool toEmitDataChanged) Standard_OVERRIDE; + + //! Returns visibility state value + Standard_EXPORT virtual bool IsVisible (const QModelIndex& theIndex) const Standard_OVERRIDE; + +public slots: + //! Processes the mouse clicked on the index. + //! It changes the item visibility if model allows to change it. + //! \theIndex tree model index + void OnClicked (const QModelIndex& theIndex); + +signals: + //! Signal after OnClicked is performed + //! \theIndex tree model index + void itemClicked (const QModelIndex& theIndex); + +protected: + //! Gets the alert item + //! \theIndex tree model index + //! \return item or NULL + MessageModel_ItemAlertPtr getAlertItem (const QModelIndex& theIndex) const; + + //! Gets shape of the view model by the parameter index if it has a shape + //! \param theIndex tree model index + //! \return shape instance + TopoDS_Shape Shape (const QModelIndex& theIndex) const; + + //! Returns true if alert of the item has table values + //! \param theIndex tree model index + //! \return boolean result + bool hasTableValues (const QModelIndex& theIndex) const; + +private: + View_Displayer* myDisplayer; //! view displayer + View_PresentationType myPresentationType; //! presentation type +}; + +#endif diff --git a/tools/MessageView/MessageView_Window.cxx b/tools/MessageView/MessageView_Window.cxx new file mode 100644 index 0000000000..ac6e0d063b --- /dev/null +++ b/tools/MessageView/MessageView_Window.cxx @@ -0,0 +1,926 @@ +// 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 + +#define DEBUG_ALERTS + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int DEFAULT_TEXT_VIEW_WIDTH = 400;// 800; +const int DEFAULT_TEXT_VIEW_HEIGHT = 700; +const int DEFAULT_TEXT_VIEW_POSITION_X = 430; +const int DEFAULT_TEXT_VIEW_POSITION_Y = 30; +const int DEFAULT_TEXT_VIEW_DELTA = 100; + +const int DEFAULT_SHAPE_VIEW_WIDTH = 400;// 900; +const int DEFAULT_SHAPE_VIEW_HEIGHT = 450; +const int DEFAULT_SHAPE_VIEW_POSITION_X = 60; +const int DEFAULT_SHAPE_VIEW_POSITION_Y = 60; + +const int DEFAULT_DETACH_POSITION_X = 5; +const int DEFAULT_DETACH_POSITION_Y = 450; + +const int MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH = 950; //600 +const int MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT = 500; + +const int MESSAGEVIEW_DEFAULT_VIEW_WIDTH = 200;// 400; +const int MESSAGEVIEW_DEFAULT_VIEW_HEIGHT = 300;// 1000; + +#include +#include +Handle(Prs3d_Drawer) GetPreviewAttributes (const Handle(AIS_InteractiveContext)& theContext) +{ + Handle(Prs3d_Drawer) myDrawer = new Prs3d_Drawer(); + myDrawer->Link (theContext->DefaultDrawer()); + + Quantity_Color aColor(Quantity_NOC_TOMATO);//Quantity_NOC_GREENYELLOW));//Quantity_NOC_BLUE1)); + Standard_ShortReal aTransparency = 0.8; + + // point parameters + myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_O_PLUS, aColor, 3.0)); + + // shading parameters + Graphic3d_MaterialAspect aShadingMaterial; + aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR); + aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT); + + myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); + myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID); + myDrawer->ShadingAspect()->SetColor (aColor); + myDrawer->ShadingAspect()->SetMaterial (aShadingMaterial); + + myDrawer->ShadingAspect()->Aspect()->ChangeFrontMaterial().SetTransparency (aTransparency); + myDrawer->ShadingAspect()->Aspect()->ChangeBackMaterial() .SetTransparency (aTransparency); + myDrawer->SetTransparency (aTransparency); + + // common parameters + myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost); + + return myDrawer; +} + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +MessageView_Window::MessageView_Window (QWidget* theParent) +: QObject (theParent) +{ + myMainWindow = new QMainWindow (theParent); + + myTreeView = new ViewControl_TreeView (myMainWindow); + ((ViewControl_TreeView*)myTreeView)->SetPredefinedSize (QSize (MESSAGEVIEW_DEFAULT_TREE_VIEW_WIDTH, + MESSAGEVIEW_DEFAULT_TREE_VIEW_HEIGHT)); + MessageModel_TreeModel* aModel = new MessageModel_TreeModel (myTreeView); + aModel->InitColumns(); + //aModel->SetReversed (Standard_True); + + 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); + myTestViewActions = new MessageView_ActionsTest (myMainWindow, aModel, aSelectionModel); + + myTreeView->setContextMenuPolicy (Qt::CustomContextMenu); + connect (myTreeView, SIGNAL (customContextMenuRequested (const QPoint&)), + this, SLOT (onTreeViewContextMenuRequested (const QPoint&))); + //new TreeModel_ContextMenu (myTreeView); + + QModelIndex aParentIndex = myTreeView->model()->index (0, 0); + myTreeView->setExpanded (aParentIndex, true); + + myMainWindow->setCentralWidget (myTreeView); + + // property view + myPropertyView = new ViewControl_PropertyView (myMainWindow); + myPropertyPanelWidget = new QDockWidget (tr ("PropertyPanel"), myMainWindow); + myPropertyPanelWidget->setObjectName (myPropertyPanelWidget->windowTitle()); + myPropertyPanelWidget->setTitleBarWidget (new QWidget(myMainWindow)); + myPropertyPanelWidget->setWidget (myPropertyView->GetControl()); + myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myPropertyPanelWidget); + connect (myPropertyPanelWidget->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT (onPropertyPanelShown (bool))); + connect (myPropertyView, SIGNAL (propertyViewDataChanged()), this, SLOT (onPropertyViewDataChanged())); + + + // view + myViewWindow = new View_Window (myMainWindow, false); + connect (myViewWindow, SIGNAL(eraseAllPerformed()), this, SLOT(onEraseAllPerformed())); + aVisibilityState->SetDisplayer (myViewWindow->Displayer()); + aVisibilityState->SetPresentationType (View_PresentationType_Main); + myViewWindow->ViewWidget()->SetPredefinedSize (MESSAGEVIEW_DEFAULT_VIEW_WIDTH, MESSAGEVIEW_DEFAULT_VIEW_HEIGHT); + + myViewDockWidget = new QDockWidget (tr ("View"), myMainWindow); + myViewDockWidget->setObjectName (myViewDockWidget->windowTitle()); + myViewDockWidget->setWidget (myViewWindow); + myMainWindow->addDockWidget (Qt::RightDockWidgetArea, myViewDockWidget); + + myMainWindow->resize (DEFAULT_SHAPE_VIEW_WIDTH, DEFAULT_SHAPE_VIEW_HEIGHT); + myMainWindow->move (DEFAULT_SHAPE_VIEW_POSITION_X, DEFAULT_SHAPE_VIEW_POSITION_Y); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : SetParent +// purpose : +// ======================================================================= +void MessageView_Window::SetParent (void* theParent) +{ + QWidget* aParent = (QWidget*)theParent; + if (aParent) + { + QLayout* aLayout = aParent->layout(); + if (aLayout) + aLayout->addWidget (GetMainWindow()); + } + else + { + GetMainWindow()->setParent (0); + GetMainWindow()->setVisible (true); + } +} + +// ======================================================================= +// function : FillActionsMenu +// purpose : +// ======================================================================= +void MessageView_Window::FillActionsMenu (void* theMenu) +{ + QMenu* aMenu = (QMenu*)theMenu; + QList aDockwidgets = myMainWindow->findChildren(); + for (QList::iterator it = aDockwidgets.begin(); it != aDockwidgets.end(); ++it) + { + QDockWidget* aDockWidget = *it; + if (aDockWidget->parentWidget() == myMainWindow) + aMenu->addAction (aDockWidget->toggleViewAction()); + } +} + +// ======================================================================= +// function : GetPreferences +// purpose : +// ======================================================================= +void MessageView_Window::GetPreferences (TInspectorAPI_PreferencesDataMap& theItem) +{ + theItem.Clear(); + theItem.Bind ("geometry", TreeModel_Tools::ToString (myMainWindow->saveState()).toStdString().c_str()); + + QMap anItems; + //TreeModel_Tools::SaveState (myTreeView, anItems); + + anItems.clear(); + View_Window::SaveState(myViewWindow, anItems); + for (QMap::const_iterator anItemsIt = anItems.begin(); anItemsIt != anItems.end(); anItemsIt++) + theItem.Bind (anItemsIt.key().toStdString().c_str(), anItemsIt.value().toStdString().c_str()); + + 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 (myViewWindow && View_Window::RestoreState(myViewWindow, anItemIt.Key().ToCString(), anItemIt.Value().ToCString())) + continue; + } +} + +// ======================================================================= +// function : UpdateContent +// purpose : +// ======================================================================= +void MessageView_Window::UpdateContent() +{ + bool isUpdated = false; + TCollection_AsciiString aName = "TKMessageView"; + if (myParameters->FindParameters (aName)) + { + NCollection_List aParameters = myParameters->Parameters (aName); + // Init will remove from parameters those, that are processed only one time (TShape) + Init (aParameters); + myParameters->SetParameters (aName, aParameters); + isUpdated = true; + } + if (myParameters->FindFileNames (aName)) + { + for (NCollection_List::Iterator aFilesIt (myParameters->FileNames (aName)); + aFilesIt.More(); aFilesIt.Next()) + openFile (aFilesIt.Value()); + + NCollection_List aNames; + myParameters->SetFileNames (aName, aNames); + isUpdated = true; + } + Handle(Message_Report) aDefaultReport = Message::DefaultReport (Standard_False); + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aDefaultReport.IsNull() && !aViewModel->HasReport (aDefaultReport)) + { + addReport (aDefaultReport); + } + // reload report of selected item + //onReloadReport(); + + updateTreeModel(); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void MessageView_Window::Init (NCollection_List& theParameters) +{ + Handle(AIS_InteractiveContext) aContext; + NCollection_List aParameters; + + Handle(Graphic3d_Camera) aViewCamera; + + for (NCollection_List::Iterator aParamsIt (theParameters); + aParamsIt.More(); aParamsIt.Next()) + { + Handle(Standard_Transient) anObject = aParamsIt.Value(); + Handle(Message_Report) aMessageReport = Handle(Message_Report)::DownCast (anObject); + if (!aMessageReport.IsNull()) + { + addReport (aMessageReport); + } + else if (!Handle(AIS_InteractiveContext)::DownCast (anObject).IsNull()) + { + aParameters.Append (anObject); + if (aContext.IsNull()) + aContext = Handle(AIS_InteractiveContext)::DownCast (anObject); + } + else if (!Handle(Graphic3d_Camera)::DownCast (anObject).IsNull()) + { + aViewCamera = Handle(Graphic3d_Camera)::DownCast (anObject); + } + } + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + if (!aTreeModel) + return; + + aTreeModel->EmitLayoutChanged(); + + if (!aContext.IsNull()) + { + myViewWindow->SetContext (View_ContextType_External, aContext); + //myViewWindow->GetViewToolBar()->SetCurrentContextType (View_ContextType_External); + } + + //if (!aViewCamera.IsNull()) + // myViewWindow->View()->Viewer()->View()->Camera()->Copy (aViewCamera); + + theParameters = aParameters; +} + +// ======================================================================= +// function : openFile +// purpose : +// ======================================================================= +void MessageView_Window::openFile(const TCollection_AsciiString& theFileName) +{ + const Handle(Message_Report)& aReport = Message::DefaultReport(); + + //Handle(Message_Report) aReport = new Message_Report(); + if (aReport->MessageWriter().IsNull()) + aReport->SetMessageWriter (new XmlDrivers_MessageReportStorage()); + + aReport->MessageWriter()->SetFileName (TCollection_AsciiString (theFileName)); + aReport->MessageWriter()->ImportReport (aReport); + + addReport (aReport, theFileName); +} + +// ======================================================================= +// function : updateTreeModel +// purpose : +// ======================================================================= +void MessageView_Window::updateTreeModel() +{ + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + if (!aViewModel) + return; + + aViewModel->UpdateTreeModel(); +} + +// ======================================================================= +// function : addReport +// purpose : +// ======================================================================= +void MessageView_Window::addReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription) +{ + MessageModel_TreeModel* aModel = dynamic_cast (myTreeView->model()); + aModel->AddReport (theReport, theReportDescription); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : onTreeViewVisibilityClicked +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewVisibilityClicked(const QModelIndex& theIndex) +{ + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + TreeModel_VisibilityState* aVisibilityState = aTreeModel->GetVisibilityState(); + if (!aVisibilityState->IsVisible (theIndex)) + myPropertyView->ClearActiveTablesSelection(); +} + +// ======================================================================= +// function : onTreeViewSelectionChanged +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&) +{ + if (!myPropertyPanelWidget->toggleViewAction()->isChecked()) + return; + + updatePropertyPanelBySelection(); + updatePreviewPresentation(); +} + +// ======================================================================= +// function : onTreeViewContextMenuRequested +// purpose : +// ======================================================================= +void MessageView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition) +{ + QMenu* aMenu = new QMenu (GetMainWindow()); + + MessageModel_ItemRootPtr aRootItem; + MessageModel_ItemReportPtr aReportItem; + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + aRootItem = itemDynamicCast (anItemBase); + if (aRootItem) + break; + aReportItem = itemDynamicCast (anItemBase); + if (aReportItem) + break; + } + if (aRootItem) + { + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Import Report"), SLOT (onImportReport()), myMainWindow, this)); + // unite + //MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + //aMenu->addAction (ViewControl_Tools::CreateAction (aTreeModel->IsUniteAlerts() ? tr ("SetUniteAlerts - OFF") : tr ("SetUniteAlerts - ON"), + // SLOT (onUniteAlerts()), myMainWindow, this)); + // reversed + //aMenu->addAction (ViewControl_Tools::CreateAction (aTreeModel->IsReversed() ? tr ("SetReversed - OFF") : tr ("SetReversed - ON"), + // SLOT (onSetReversedAlerts()), myMainWindow, this)); + } + else if (aReportItem) + { + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Export Report"), SLOT (onExportReport()), myMainWindow, this)); + const TCollection_AsciiString& aDescription = aReportItem->GetDescription(); + if (!aDescription.IsEmpty()) + { + OSD_Path aPath(aDescription); + OSD_File aDescriptionFile (aPath); + if (aDescriptionFile.IsReadable()) + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Reload"), SLOT (onReloadReport()), myMainWindow, this)); + } + Handle(Message_Report) aReport = aReportItem->GetReport(); + QAction* anAction = ViewControl_Tools::CreateAction (tr ("Export by alert"), SLOT (onAutoExportActivate()), myMainWindow, this); + anAction->setCheckable (true); + anAction->setChecked (aReport->WriteFileOnEachAlert()); + aMenu->addAction (anAction); + + anAction = ViewControl_Tools::CreateAction (tr ("Export trace only"), SLOT (onExportTraceOnly()), myMainWindow, this); + anAction->setCheckable (true); + bool isTraceOnly = aReport->MessageWriter().IsNull() ? false : aReport->MessageWriter()->Gravity() == Message_Trace; + anAction->setChecked (isTraceOnly); + aMenu->addAction (anAction); + } + aMenu->addSeparator(); + + aMenu->addAction (ViewControl_Tools::CreateAction (tr ("Preview children presentations"), SLOT (onPreviewChildren()), myMainWindow, this)); + aMenu->addSeparator(); + + myTreeViewActions->AddMenuActions (aSelectedIndices, aMenu); + addActivateMetricActions (aMenu); + +#ifdef DEBUG_ALERTS + aMenu->addSeparator(); + myTestViewActions->AddMenuActions (aSelectedIndices, aMenu); +#endif + + QPoint aPoint = myTreeView->mapToGlobal (thePosition); + aMenu->exec (aPoint); +} + +// ======================================================================= +// function : onPropertyPanelShown +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyPanelShown (bool isToggled) +{ + if (!isToggled) + return; + + updatePropertyPanelBySelection(); +} + +// ======================================================================= +// function : onPropertyViewDataChanged +// purpose : +// ======================================================================= +void MessageView_Window::onPropertyViewDataChanged() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + + updatePropertyPanelBySelection(); + updatePreviewPresentation(); +} + +// ======================================================================= +// function : 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); + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport->MessageWriter().IsNull()) + aReport->SetMessageWriter (new XmlDrivers_MessageReportStorage()); + + aReport->MessageWriter()->SetFileName (TCollection_AsciiString (aFileName.toStdString().c_str())); + aReport->MessageWriter()->ExportReport (aReport); +} + +// ======================================================================= +// function : onImportReport +// purpose : +// ======================================================================= +void MessageView_Window::onImportReport() +{ + QString aFilter (tr ("Document file (*.cbf *)")); + QString aSelectedFilter; + + QItemSelectionModel* aSelectionModel = myTreeView->selectionModel(); + aSelectionModel->clear(); + + QString aFileName = QFileDialog::getOpenFileName (0, tr("Import report"), QString(), aSelectedFilter); + openFile (TCollection_AsciiString (aFileName.toStdString().c_str())); +} + +// ======================================================================= +// function : onImportReport +// purpose : +// ======================================================================= +//void MessageView_Window::onUniteAlerts() +//{ + //MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + //Standard_Boolean isUniteAlerts = aTreeModel->IsUniteAlerts(); + + //aTreeModel->SetUniteAlerts (!isUniteAlerts); +//} + +// ======================================================================= +// function : onSetReversedAlerts +// purpose : +// ======================================================================= +void MessageView_Window::onSetReversedAlerts() +{ + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + Standard_Boolean isReversed = aTreeModel->IsReversed(); + + aTreeModel->SetReversed (!isReversed); +} + +// ======================================================================= +// function : onReloadReport +// purpose : +// ======================================================================= +void MessageView_Window::onReloadReport() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + const TCollection_AsciiString aDescription = aReportItem->GetDescription(); + if (aDescription.IsEmpty()) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + aReport->Clear(); + if (aReport->MessageWriter().IsNull()) + aReport->SetMessageWriter (new XmlDrivers_MessageReportStorage()); + + aReport->MessageWriter()->SetFileName (TCollection_AsciiString (aDescription)); + if (!aReport->MessageWriter()->ImportReport (aReport)) + return; + + MessageModel_TreeModel* aTreeModel = dynamic_cast (myTreeView->model()); + aModel->clearSelection(); + aTreeModel->SetReport (aReportItem->Row(), aReport, aDescription); +} + +// ======================================================================= +// function : onAutoExportActivate +// purpose : +// ======================================================================= +void MessageView_Window::onAutoExportActivate() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + QAction* anAction = (QAction*)(sender()); + aReport->SetWriteFileOnEachAlert (anAction->isChecked()); +} + +// ======================================================================= +// function : onExportTraceOnly +// purpose : +// ======================================================================= +void MessageView_Window::onExportTraceOnly() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + MessageModel_ItemReportPtr aReportItem = itemDynamicCast(anItemBase); + if (!aReportItem) + aReportItem = MessageModel_ItemReport::FindReportItem (anItemBase); + + if (!aReportItem) + return; + + Handle(Message_Report) aReport = aReportItem->GetReport(); + if (aReport->MessageWriter().IsNull()) + return; + + QAction* anAction = (QAction*)(sender()); + aReport->MessageWriter()->SetGravity (anAction->isChecked() ? Message_Trace : Message_Info); +} + +// ======================================================================= +// function : onPreviewChildren +// purpose : +// ======================================================================= +void MessageView_Window::onPreviewChildren() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + NCollection_List aPresentations; + TreeModel_ModelBase::SubItemsPresentations (aSelectedIndices, aPresentations); + + displayer()->DisplayPreview()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations, myViewWindow->ViewWidget()->DisplayMode()); +} + +// ======================================================================= +// function : addActivateMetricActions +// purpose : +// ======================================================================= +void MessageView_Window::addActivateMetricActions (QMenu* theMenu) +{ + QMenu* aSubMenu = new QMenu ("Activate metric"); + + Handle(Message_Report) aReport = Message::DefaultReport (Standard_True); + + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + QAction* anAction = ViewControl_Tools::CreateAction (Message::MetricToString (aMetricType), + SLOT (OnActivateMetric()), parent(), this); + anAction->setCheckable (true); + anAction->setChecked (aReport->ActiveMetrics().Contains (aMetricType)); + aSubMenu->addAction (anAction); + } + aSubMenu->addSeparator(); + aSubMenu->addAction (ViewControl_Tools::CreateAction ("Deactivate all", SLOT (OnDeactivateAllMetrics()), parent(), this)); + + theMenu->addMenu (aSubMenu); +} + +// ======================================================================= +// function : OnActivateMetric +// purpose : +// ======================================================================= +void MessageView_Window::OnActivateMetric() +{ + QAction* anAction = (QAction*)(sender()); + + Message_MetricType aMetricType; + if (!Message::MetricFromString (anAction->text().toStdString().c_str(), aMetricType)) + return; + + Handle(Message_Report) aReport = Message::DefaultReport (Standard_True); + const NCollection_Map& anActiveMetrics = aReport->ActiveMetrics(); + + aReport->SetActiveMetric (aMetricType, !anActiveMetrics.Contains (aMetricType)); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : OnDeactivateAllMetrics +// purpose : +// ======================================================================= +void MessageView_Window::OnDeactivateAllMetrics() +{ + Handle(Message_Report) aReport = Message::DefaultReport(); + if (aReport.IsNull()) + return; + aReport->ClearMetrics(); + + updateVisibleColumns(); +} + +// ======================================================================= +// function : displayer +// purpose : +// ======================================================================= +View_Displayer* MessageView_Window::displayer() +{ + return myViewWindow->Displayer(); +} + +// ======================================================================= +// function : updatePropertyPanelBySelection +// purpose : +// ======================================================================= +void MessageView_Window::updatePropertyPanelBySelection() +{ + /*QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + return; + + QList aTableValues; + MessageModel_Tools::GetPropertyTableValues (anItemBase, aTableValues); + + myPropertyView->Init (aTableValues);*/ + ViewControl_TableModelValues* aTableValues = 0; + + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + + QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (anItemBase) + { + Handle(TreeModel_ItemProperties) anItemProperties = anItemBase->Properties (); + if (!anItemProperties.IsNull()) + { + aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (anItemProperties); + } + } + myPropertyView->Init (aTableValues); +} + +// ======================================================================= +// function : updatePreviewPresentation +// purpose : +// ======================================================================= +void MessageView_Window::updatePreviewPresentation() +{ + Handle(AIS_InteractiveContext) aContext = myViewWindow->ViewToolBar()->CurrentContext(); + if (aContext.IsNull()) + return; + + NCollection_List aPresentations; + QModelIndexList aSelectedIndices = myTreeView->selectionModel()->selectedIndexes(); + for (QModelIndexList::const_iterator aSelIt = aSelectedIndices.begin(); aSelIt != aSelectedIndices.end(); aSelIt++) + { + QModelIndex anIndex = *aSelIt; + if (anIndex.column() != 0) + continue; + + TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); + if (!anItemBase) + continue; + + Handle(TreeModel_ItemProperties) anItemProperties = anItemBase->Properties(); + if (anItemProperties) + { + anItemProperties->Presentations (aPresentations); + } + + MessageModel_ItemAlertPtr anAlertItem = itemDynamicCast(anItemBase); + if (anAlertItem) + { + anAlertItem->Presentations (aPresentations); + } + } + + displayer()->DisplayPreview()->UpdatePreview (View_DisplayActionType_DisplayId, aPresentations, myViewWindow->ViewWidget()->DisplayMode()); +} + +// ======================================================================= +// function : updateVisibleColumns +// purpose : +// ======================================================================= +void MessageView_Window::updateVisibleColumns() +{ + MessageModel_TreeModel* aViewModel = dynamic_cast (myTreeView->model()); + const NCollection_List& aReports = aViewModel->Reports(); + + NCollection_Map anActiveMetrics; + for (NCollection_List::Iterator anIterator (aViewModel->Reports()); anIterator.More(); anIterator.Next()) + { + Handle(Message_Report) aReport = anIterator.Value().myReport; + for (NCollection_Map::Iterator aMetricsIterator (aReport->ActiveMetrics()); aMetricsIterator.More(); aMetricsIterator.Next()) + { + if (anActiveMetrics.Contains (aMetricsIterator.Value())) + continue; + anActiveMetrics.Add (aMetricsIterator.Value()); + } + } + + for (int aMetricId = (int)Message_MetricType_None + 1; aMetricId <= (int)Message_MetricType_MemHeapUsage; aMetricId++) + { + Message_MetricType aMetricType = (Message_MetricType)aMetricId; + QList aMetricColumns; + aViewModel->GetMetricColumns (aMetricType, aMetricColumns); + bool isColumnHidden = !anActiveMetrics.Contains (aMetricType); + for (int i = 0; i < aMetricColumns.size(); i++) + { + int aColumnId = aMetricColumns[i]; + myTreeView->setColumnHidden (aColumnId, isColumnHidden); + TreeModel_HeaderSection aSection = aViewModel->GetHeaderItem (aColumnId); + aSection.SetIsHidden (isColumnHidden); + aViewModel->SetHeaderItem (aColumnId, aSection); + } + } +} diff --git a/tools/MessageView/MessageView_Window.hxx b/tools/MessageView/MessageView_Window.hxx new file mode 100644 index 0000000000..dbaf64c6af --- /dev/null +++ b/tools/MessageView/MessageView_Window.hxx @@ -0,0 +1,206 @@ +// Created on: 2017-06-16 +// Created by: Natalia ERMOLAEVA +// Copyright (c) 2017 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef MessageView_Window_H +#define MessageView_Window_H + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(disable : 4127) // conditional expression is constant +#endif +#include +#include +#include +#include +#include +#include +#include + +class View_Displayer; +class View_Window; + +class ViewControl_PropertyView; + +class MessageView_ActionsTest; + +class QDockWidget; +class QMainWindow; +class QMenu; +class QWidget; + +//! \class MessageView_Window +//! Window that unites all MessageView controls. +class MessageView_Window : public QObject +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT MessageView_Window (QWidget* theParent); + + //! Destructor + virtual ~MessageView_Window() {} + + //! Provides the container with a parent where this container should be inserted. + //! If Qt implementation, it should be QWidget with QLayout set inside + //! \param theParent a parent class + Standard_EXPORT void SetParent (void* theParent); + + //! Sets parameters container, it should be used when the plugin is initialized or in update content + //! \param theParameters a parameters container + void SetParameters (const Handle(TInspectorAPI_PluginParameters)& theParameters) + { myParameters = theParameters; myTreeViewActions->SetParameters (theParameters); } + + //! Provide container for actions available in inspector on general level + //! \param theMenu if Qt implementation, it is QMenu object + Standard_EXPORT virtual void FillActionsMenu (void* theMenu); + + //! Returns plugin preferences: dock widgets state, tree view columns. + //! \param theItem container of preference elements + Standard_EXPORT void GetPreferences (TInspectorAPI_PreferencesDataMap& theItem); + + //! Applies plugin preferences + //! \param theItem container of preference elements + Standard_EXPORT void SetPreferences (const TInspectorAPI_PreferencesDataMap& theItem); + + //! Applyes parameters to Init controls, opens files if there are in parameters, updates OCAF tree view model + Standard_EXPORT void UpdateContent(); + + //! Returns main control + QMainWindow* GetMainWindow() const { return myMainWindow; } + + //! Returns current tree view + QTreeView* GetTreeView() const { return myTreeView; } + +protected: + //! Appends shape into tree view model + //! \param theShape a shape instance + //! \param theReportDescription an additional report information + void addReport (const Handle(Message_Report)& theReport, + const TCollection_AsciiString& theReportDescription = ""); + +private: + + //! Fills controls of the plugin by parameters: + //! - Fine AIS_InteractiveObject and fills View if it if it differs from the current context + //! \param theParameters a parameters container + void Init (NCollection_List& theParameters); + + //! Read Shape from the file name, add Shape into tree view + //! \param theFileName BREP file name + void openFile (const TCollection_AsciiString& theFileName); + + //! Updates tree model + void updateTreeModel(); + +protected slots: + //! Updates property view selection in table if the item is hidden + //! \param theIndex tree view model index + void onTreeViewVisibilityClicked(const QModelIndex& theIndex); + + //! Udpates all controls by changed selection in OCAF tree view + //! \param theSelected list of selected tree view items + //! \param theDeselected list of deselected tree view items + void onTreeViewSelectionChanged (const QItemSelection& theSelected, const QItemSelection& theDeselected); + + //! Shows context menu for tree view selected item. It contains expand/collapse actions. + //! \param thePosition a clicked point + void onTreeViewContextMenuRequested (const QPoint& thePosition); + + //! Display content of selected tree view item if isToggled is true + //! \param isToggled true if the property dock widget is shown + void onPropertyPanelShown (bool isToggled); + + //! Update tree view item, preview presentation by item value change + void onPropertyViewDataChanged(); + + //! Updates visibility states by erase all in context + void onEraseAllPerformed(); + + //! Export report into document + void onExportReport(); + + //! Import report into document + void onImportReport(); + + //! Unite alerts in view model + //void onUniteAlerts(); + + //! Sets report reversed + void onSetReversedAlerts(); + + //! Reads if possible report of a selected item and updates this report in tree view + void onReloadReport(); + + //! Sets report state to write it by each message alert + void onAutoExportActivate(); + + //! Sets report writer state to write only trace information of alerts + void onExportTraceOnly(); + + //! Iterates by children items of selected items and display its presentations if found + void onPreviewChildren(); + + //! Switch active state in report for clicked type of metric + void OnActivateMetric(); + + //! Deactivate all types of metrics for the current report + void OnDeactivateAllMetrics(); + +protected: + //! Appends items to activate report metrics + void addActivateMetricActions (QMenu* theMenu); + + //! Returns displayer where the presentations/preview should be shown/erased + //! If default view is created, it returns displayer of this view + Standard_EXPORT View_Displayer* displayer(); + + //! Updates property panel content by item selected in tree view. + void updatePropertyPanelBySelection(); + + //!< Updates presentation of preview for parameter shapes. Creates a compound of the shapes + void updatePreviewPresentation(); + + //!< Sets reports metric columns visible if used + void updateVisibleColumns(); + +private: + QMainWindow* myMainWindow; //!< main control, parent for all MessageView controls + QDockWidget* myViewDockWidget; //!< view dock widget to hide/show + + QDockWidget* myPropertyPanelWidget; //!< property pane dockable widget + ViewControl_PropertyView* myPropertyView; //!< property control to display model item values if exist + + View_Window* myViewWindow; //!< OCC 3d view to visualize presentations + QTreeView* myTreeView; //!< tree view visualized shapes + MessageModel_Actions* myTreeViewActions; //!< processing history view actions + MessageView_ActionsTest* myTestViewActions; //!< check view actions + + Handle(TInspectorAPI_PluginParameters) myParameters; //!< plugins parameters container + + Handle(AIS_InteractiveObject) myPreviewPresentation; //!< presentation of preview for a selected object +}; + +#endif diff --git a/tools/ShapeView/ShapeView_Window.cxx b/tools/ShapeView/ShapeView_Window.cxx index bfe8d34eca..7ae4fb55c4 100644 --- a/tools/ShapeView/ShapeView_Window.cxx +++ b/tools/ShapeView/ShapeView_Window.cxx @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -39,8 +40,15 @@ #include #include +#include +#include #include #include +#include +#include +#include +#include +#include #include #include @@ -107,6 +115,7 @@ ShapeView_Window::ShapeView_Window (QWidget* theParent) aVisibilityState, SLOT (OnClicked(const QModelIndex&))); QItemSelectionModel* aSelModel = new QItemSelectionModel (myTreeView->model(), myTreeView); + myTreeView->setSelectionMode (QAbstractItemView::ExtendedSelection); myTreeView->setSelectionModel (aSelModel); connect (aSelModel, SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), this, SLOT (onTreeViewSelectionChanged (const QItemSelection&, const QItemSelection&))); @@ -360,42 +369,47 @@ void ShapeView_Window::onTreeViewContextMenuRequested (const QPoint& thePosition QModelIndex anIndex = TreeModel_ModelBase::SingleSelected (aModel->selectedIndexes(), 0); TreeModel_ItemBasePtr anItemBase = TreeModel_ModelBase::GetItemByIndex (anIndex); - if (!anItemBase) - return; - QMenu* aMenu = new QMenu(myMainWindow); + ShapeView_ItemRootPtr aRootItem = itemDynamicCast (anItemBase); if (aRootItem) { aMenu->addAction (ViewControl_Tools::CreateAction ("Load BREP file", SLOT (onLoadFile()), myMainWindow, this)); aMenu->addAction (ViewControl_Tools::CreateAction ("Remove all shape items", SLOT (onClearView()), myMainWindow, this)); } - else { + else if (anItemBase) { // single selection aMenu->addAction (ViewControl_Tools::CreateAction ("Export to BREP", SLOT (onExportToBREP()), myMainWindow, this)); + ShapeView_ItemShapePtr aShapeItem = itemDynamicCast(anItemBase); - const TopoDS_Shape& aShape = aShapeItem->GetItemShape(); - TopAbs_ShapeEnum anExplodeType = aShapeItem->ExplodeType(); - NCollection_List anExplodeTypes; - ShapeView_Tools::IsPossibleToExplode (aShape, anExplodeTypes); - if (anExplodeTypes.Size() > 0) + if (aShapeItem) { - QMenu* anExplodeMenu = aMenu->addMenu ("Explode"); - for (NCollection_List::Iterator anExpIterator (anExplodeTypes); anExpIterator.More(); - anExpIterator.Next()) + const TopoDS_Shape& aShape = aShapeItem->GetItemShape(); + TopAbs_ShapeEnum anExplodeType = aShapeItem->ExplodeType(); + NCollection_List anExplodeTypes; + ShapeView_Tools::IsPossibleToExplode (aShape, anExplodeTypes); + if (anExplodeTypes.Size() > 0) { - TopAbs_ShapeEnum aType = anExpIterator.Value(); - QAction* anAction = ViewControl_Tools::CreateAction (TopAbs::ShapeTypeToString (aType), SLOT (onExplode()), myMainWindow, this); - anExplodeMenu->addAction (anAction); - if (anExplodeType == aType) + QMenu* anExplodeMenu = aMenu->addMenu ("Explode"); + for (NCollection_List::Iterator anExpIterator (anExplodeTypes); anExpIterator.More(); + anExpIterator.Next()) { - anAction->setCheckable (true); - anAction->setChecked (true); + TopAbs_ShapeEnum aType = anExpIterator.Value(); + QAction* anAction = ViewControl_Tools::CreateAction (TopAbs::ShapeTypeToString (aType), SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addAction (anAction); + if (anExplodeType == aType) + { + anAction->setCheckable (true); + anAction->setChecked (true); + } } + QAction* anAction = ViewControl_Tools::CreateAction ("NONE", SLOT (onExplode()), myMainWindow, this); + anExplodeMenu->addSeparator(); + anExplodeMenu->addAction (anAction); } - QAction* anAction = ViewControl_Tools::CreateAction ("NONE", SLOT (onExplode()), myMainWindow, this); - anExplodeMenu->addSeparator(); - anExplodeMenu->addAction (anAction); } } + aMenu->addAction (ViewControl_Tools::CreateAction ("Create Face", SLOT (onCreateFace()), myMainWindow, this)); + aMenu->addAction (ViewControl_Tools::CreateAction ("Create Compound", SLOT (onCreateCompound()), myMainWindow, this)); + aMenu->addAction (ViewControl_Tools::CreateAction ("Algo: Incremental Mesh", SLOT (onIncrementalMesh()), myMainWindow, this)); QPoint aPoint = myTreeView->mapToGlobal (thePosition); aMenu->exec (aPoint); @@ -521,3 +535,84 @@ void ShapeView_Window::onExportToBREP() anItem->SetFileName (aFileNameIndiced.ToCString()); aFileName = aFileNameIndiced.ToCString(); } + +// ======================================================================= +// function : onCreateFace +// purpose : +// ======================================================================= +void ShapeView_Window::onCreateFace() +{ + /*QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QList anItems = TreeModel_ModelBase::SelectedItems (aModel->selectedIndexes()); + + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + NCollection_List anItemPresentations; + + BRepBuilderAPI_MakeWire aWireBuilder; + for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + { + ShapeView_ItemShapePtr anItem = itemDynamicCast(*anItemIt); + if (!anItem) + continue; + + const TopoDS_Shape& aShape = anItem->GetItemShape(); + if (aShape.ShapeType() != TopAbs_EDGE) + continue; + + const TopoDS_Edge& aSourceEdge = TopoDS::Edge (aShape); + const TopoDS_Edge& anEdgeCopied = TopoDS::Edge (aSourceEdge.EmptyCopied()); + + aWireBuilder.Add (anEdgeCopied);//aSourceEdge); + } + if (!aWireBuilder.IsDone()) + return; + + BRepBuilderAPI_MakeFace aFaceBuilder; + + const TopoDS_Wire& aWire = aWireBuilder.Wire(); + const TopoDS_Wire& aWireCopied = TopoDS::Wire (aWire.EmptyCopied()); + + aFaceBuilder.Add (aWireCopied); + + addShape (aFaceBuilder.Face()); + */ +} + +// ======================================================================= +// function : onCreateCompound +// purpose : +// ======================================================================= +void ShapeView_Window::onCreateCompound() +{ + QItemSelectionModel* aModel = myTreeView->selectionModel(); + if (!aModel) + return; + QList anItems = TreeModel_ModelBase::SelectedItems (aModel->selectedIndexes()); + + QList aSelectedIds; // Remember of selected address in order to avoid duplicates + NCollection_List anItemPresentations; + + BRep_Builder aBB; + TopoDS_Compound aC; + aBB.MakeCompound(aC); + + for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + { + ShapeView_ItemShapePtr anItem = itemDynamicCast(*anItemIt); + if (!anItem) + return; + + aBB.Add(aC, anItem->GetItemShape()); + } + addShape (aC); +} + +// ======================================================================= +// function : onIncrementalMesh +// purpose : +// ======================================================================= +void ShapeView_Window::onIncrementalMesh() +{ +} diff --git a/tools/ShapeView/ShapeView_Window.hxx b/tools/ShapeView/ShapeView_Window.hxx index 950119326e..5119fd9039 100644 --- a/tools/ShapeView/ShapeView_Window.hxx +++ b/tools/ShapeView/ShapeView_Window.hxx @@ -129,6 +129,15 @@ protected slots: //! Views BREP files of selected items if exist void onExportToBREP(); + //! Create a wire of selected edges + void onCreateFace(); + + //! Create a compound of selected shapes + void onCreateCompound(); + + //! Perform BRepMesh_IncrementalMesh on the selected shape + void onIncrementalMesh(); + //! Convers file name to Ascii String and perform opeging file //! \param theFileName a file name to be opened void onOpenFile(const QString& theFileName) { OpenFile (TCollection_AsciiString (theFileName.toUtf8().data())); } diff --git a/tools/TInspectorEXE/TInspectorEXE.cxx b/tools/TInspectorEXE/TInspectorEXE.cxx index b22e57eb81..2c1aac570a 100644 --- a/tools/TInspectorEXE/TInspectorEXE.cxx +++ b/tools/TInspectorEXE/TInspectorEXE.cxx @@ -19,6 +19,8 @@ #include +#include +#include #include #include @@ -104,6 +106,9 @@ int main (int argc, char** argv) if (!strcmp (argv[anArgId], "vinspector")) aPlugins.insert ("TKVInspector"); + + if (!strcmp (argv[anArgId], "messageview")) + aPlugins.insert ("TKMessageView"); } NCollection_List aParameters; @@ -123,7 +128,14 @@ int main (int argc, char** argv) aPlugins.insert("TKShapeView"); aPlugins.insert("TKVInspector"); - anActivatedPluginName = "TKDFBrowser"; + Handle(Message_Report) aReport = Message::DefaultReport (Standard_True); + aReport->SetLimit (100);//30); + aPlugins.insert("TKMessageView"); + + //anActivatedPluginName = "TKVInspector"; + //anActivatedPluginName = "TKMessageView"; + //anActivatedPluginName = "TKDFBrowser"; + anActivatedPluginName = "TKShapeView"; } else anActivatedPluginName = *aPlugins.rbegin(); diff --git a/tools/TKMessageModel/CMakeLists.txt b/tools/TKMessageModel/CMakeLists.txt new file mode 100644 index 0000000000..911ffb1fbe --- /dev/null +++ b/tools/TKMessageModel/CMakeLists.txt @@ -0,0 +1,5 @@ +project(TKMessageModel) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) diff --git a/tools/TKMessageModel/EXTERNLIB b/tools/TKMessageModel/EXTERNLIB new file mode 100644 index 0000000000..54b02742af --- /dev/null +++ b/tools/TKMessageModel/EXTERNLIB @@ -0,0 +1,10 @@ +TKMath +TKBin +TKBRep +TKGeomBase +TKG3d +TKTInspectorAPI +TKService +TKTopAlgo +TKTreeModel +CSF_QT diff --git a/tools/TKMessageModel/FILES b/tools/TKMessageModel/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/tools/TKMessageModel/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/tools/TKMessageModel/PACKAGES b/tools/TKMessageModel/PACKAGES new file mode 100644 index 0000000000..9021fbf297 --- /dev/null +++ b/tools/TKMessageModel/PACKAGES @@ -0,0 +1 @@ +MessageModel diff --git a/tools/TKMessageView/CMakeLists.txt b/tools/TKMessageView/CMakeLists.txt new file mode 100644 index 0000000000..9b3c1aaec7 --- /dev/null +++ b/tools/TKMessageView/CMakeLists.txt @@ -0,0 +1,5 @@ +project(TKMessageView) + +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit) +OCCT_INCLUDE_CMAKE_FILE (adm/cmake/occt_toolkit_prepare_tool) diff --git a/tools/TKMessageView/EXTERNLIB b/tools/TKMessageView/EXTERNLIB new file mode 100644 index 0000000000..84e5b5d8b5 --- /dev/null +++ b/tools/TKMessageView/EXTERNLIB @@ -0,0 +1,13 @@ +TKTInspectorAPI +TKMath +TKMessageModel +TKBin +TKBRep +TKGeomBase +TKG3d +TKService +TKTopAlgo +TKTreeModel +TKView +TKXml +CSF_QT diff --git a/tools/TKMessageView/FILES b/tools/TKMessageView/FILES new file mode 100644 index 0000000000..ca4f0e567b --- /dev/null +++ b/tools/TKMessageView/FILES @@ -0,0 +1,2 @@ +EXTERNLIB +PACKAGES diff --git a/tools/TKMessageView/PACKAGES b/tools/TKMessageView/PACKAGES new file mode 100644 index 0000000000..46a67b229d --- /dev/null +++ b/tools/TKMessageView/PACKAGES @@ -0,0 +1 @@ +MessageView diff --git a/tools/ToolsDraw/ToolsDraw.cxx b/tools/ToolsDraw/ToolsDraw.cxx index c0abd7766a..104bda3336 100644 --- a/tools/ToolsDraw/ToolsDraw.cxx +++ b/tools/ToolsDraw/ToolsDraw.cxx @@ -62,6 +62,7 @@ Standard_Boolean convertToPluginName (const TCollection_AsciiString& theArgument if (anArgument == "dfbrowser") { thePluginName = "TKDFBrowser"; return Standard_True; } else if (anArgument == "shapeview") { thePluginName = "TKShapeView"; return Standard_True; } else if (anArgument == "vinspector") { thePluginName = "TKVInspector"; return Standard_True; } + else if (anArgument == "messageview") { thePluginName = "TKMessageView"; return Standard_True; } return Standard_False; } @@ -305,6 +306,7 @@ static int tinspector (Draw_Interpretor& di, Standard_Integer theArgsNb, const c aPlugins.Append ("TKDFBrowser"); aPlugins.Append ("TKShapeView"); aPlugins.Append ("TKVInspector"); + aPlugins.Append ("TKMessageView"); } aPluginNameToActivate = !aPluginNameToActivate.IsEmpty() ? aPluginNameToActivate : aPlugins.First(); } @@ -391,10 +393,10 @@ void ToolsDraw::Commands(Draw_Interpretor& theCommands) "\n\t\t: Starts tool of inspection." "\n\t\t: Options:" "\n\t\t: -plugins enters plugins that should be added in the inspector." - "\n\t\t: Available names are: dfbrowser, vinspector and shapeview." + "\n\t\t: Available names are: dfbrowser, vinspector, shapeview and messageview." "\n\t\t: Plugins order will be the same as defined in arguments." "\n\t\t: 'all' adds all available plugins in the order:" - "\n\t\t: DFBrowser, VInspector and ShapeView." + "\n\t\t: DFBrowser, VInspector, ShapeView and MessageView." "\n\t\t: If at the first call this option is not used, 'all' option is applied;" "\n\t\t: -activate activates the plugin in the tool view." "\n\t\t: If at the first call this option is not used, the first plugin is activated;" diff --git a/tools/TreeModel/TreeModel_ItemBase.hxx b/tools/TreeModel/TreeModel_ItemBase.hxx index 752da3922a..8654b06876 100644 --- a/tools/TreeModel/TreeModel_ItemBase.hxx +++ b/tools/TreeModel/TreeModel_ItemBase.hxx @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -149,7 +150,10 @@ public: //! Returns the item properties const Handle(TreeModel_ItemProperties)& Properties() const { return myProperties; } + //! Returns presentation of the attribute to be visualized in the view + //! \thePresentations [out] container of presentation handles to be visualized Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + protected: //! \param theParent the parent item diff --git a/tools/TreeModel/TreeModel_ItemProperties.cxx b/tools/TreeModel/TreeModel_ItemProperties.cxx index 631d2f2c18..8aa7a0d81d 100644 --- a/tools/TreeModel/TreeModel_ItemProperties.cxx +++ b/tools/TreeModel/TreeModel_ItemProperties.cxx @@ -39,6 +39,15 @@ void TreeModel_ItemProperties::Init () const Standard_SStream& aStream = Item()->Stream(); + InitByStream (aStream); +} + +// ======================================================================= +// function : InitByStream +// purpose : +// ======================================================================= +void TreeModel_ItemProperties::InitByStream (const Standard_SStream& aStream) +{ NCollection_IndexedDataMap aValues; TCollection_AsciiString aStreamText = Standard_Dump::Text (aStream); Standard_Dump::SplitJson (aStreamText, aValues); @@ -48,8 +57,15 @@ void TreeModel_ItemProperties::Init () Standard_DumpValue aKeyValue; if (!aStreamParent) { - const Handle(Standard_Transient)& anItemObject = Item()->Object(); - aKey = anItemObject.IsNull() ? "Dump" : anItemObject->DynamicType()->Name(); + if (!Item() || Item()->Object().IsNull()) + { + aKey = "Dump"; + } + else + { + const Handle(Standard_Transient)& anItemObject = Item()->Object(); + aKey = anItemObject.IsNull() ? "Dump" : anItemObject->DynamicType()->Name(); + } aKeyValue = Standard_DumpValue (aStreamText, 1); myKey = aKey; @@ -95,6 +111,11 @@ void TreeModel_ItemProperties::Init () (int)(aGreen * aDelta), (int)(aBlue * aDelta))); } } + // in case if the stream alert has empty key avalue, use as the key the first row value + if ((myKey.IsEmpty() || myKey.IsEqual ("Dump")) && myRowValues.Size() > 0) + { + myKey = myRowValues.FindFromIndex (1).Value.toString().toStdString().c_str(); + } } // ======================================================================= @@ -172,10 +193,16 @@ ViewControl_EditType TreeModel_ItemProperties::EditType (const int, const int th // function : SetData // purpose : // ======================================================================= -bool TreeModel_ItemProperties::SetData (const int /*theRow*/, const int theColumn, const QVariant& /*theValue*/, int) +bool TreeModel_ItemProperties::SetData (const int theRow, const int theColumn, const QVariant& theValue, int theRole) { if (theColumn == 0) return false; + + if (theRole == Qt::DisplayRole || theRole == Qt::EditRole) + { + myRowValues.ChangeFromIndex (theRow + 1).Value = theValue; + } + return false; } @@ -185,6 +212,8 @@ bool TreeModel_ItemProperties::SetData (const int /*theRow*/, const int theColum // ======================================================================= void TreeModel_ItemProperties::Presentations (NCollection_List& thePresentations) { + if (!Item()) + return; const Standard_SStream& aStream = Item()->Stream(); Convert_Tools::ConvertStreamToPresentations (aStream, 1, -1, thePresentations); } diff --git a/tools/TreeModel/TreeModel_ItemProperties.hxx b/tools/TreeModel/TreeModel_ItemProperties.hxx index 7f498d70e4..a86ef9baec 100644 --- a/tools/TreeModel/TreeModel_ItemProperties.hxx +++ b/tools/TreeModel/TreeModel_ItemProperties.hxx @@ -73,6 +73,9 @@ public: //! Sets the current item void SetItem (const TreeModel_ItemBasePtr& theItem) { myItem = theItem; } + //! Fills properties with the stream value + Standard_EXPORT void InitByStream (const Standard_SStream& theStream); + //! Returns the current item TreeModel_ItemBasePtr Item() const { return myItem; } @@ -80,7 +83,7 @@ public: Standard_EXPORT void Init(); //! If the item has internal values, there should be reseted here. - Standard_EXPORT virtual void Reset(); + Standard_EXPORT void Reset(); //! Returns number of table rows //! \return an integer value @@ -108,18 +111,18 @@ public: //! \param theColumn a model index column //! \param theRole a view role //! \return true if the value is changed - Standard_EXPORT virtual bool SetData (const int theRow, const int theColumn, const QVariant& theValue, - int theRole = Qt::DisplayRole); + Standard_EXPORT bool SetData (const int theRow, const int theColumn, const QVariant& theValue, + int theRole = Qt::DisplayRole); //! Returns presentation of the attribute to be visualized in the view //! \thePresentations [out] container of presentation handles to be visualized - Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + Standard_EXPORT void Presentations (NCollection_List& thePresentations); //! Returns flags for the item: ItemIsEnabled | Qt::ItemIsSelectable. //! Additional flag for the column 1 is Qt::ItemIsEditable. //! \param theIndex a model index //! \return flags - Standard_EXPORT virtual Qt::ItemFlags TableFlags (const int theRow, const int theColumn) const; + Standard_EXPORT Qt::ItemFlags TableFlags (const int theRow, const int theColumn) const; //! Returns stream value of the item to fulfill property panel. //! \return stream value or dummy diff --git a/tools/TreeModel/TreeModel_ModelBase.cxx b/tools/TreeModel/TreeModel_ModelBase.cxx index a87cbe662e..806684a4f1 100644 --- a/tools/TreeModel/TreeModel_ModelBase.cxx +++ b/tools/TreeModel/TreeModel_ModelBase.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -295,6 +296,40 @@ QList TreeModel_ModelBase::SelectedItems (const QModelInd return anItems; } +// ======================================================================= +// function : SubItemsPresentations +// purpose : +// ======================================================================= +void TreeModel_ModelBase::SubItemsPresentations (const QModelIndexList& theIndices, + NCollection_List& thePresentations) +{ + QList anItems; + + for (QModelIndexList::const_iterator anIndicesIt = theIndices.begin(); anIndicesIt != theIndices.end(); anIndicesIt++) + { + TreeModel_ItemBasePtr anItem = TreeModel_ModelBase::GetItemByIndex (*anIndicesIt); + if (!anItem || anItems.contains (anItem)) + continue; + subItemsPresentations (anItem, thePresentations); + } +} + +// ======================================================================= +// function : subItemPresentations +// purpose : +// ======================================================================= +void TreeModel_ModelBase::subItemsPresentations (const TreeModel_ItemBasePtr& theItem, + NCollection_List& thePresentations) +{ + theItem->Presentations (thePresentations); + + QList anItems; + for (int aRowId = 0; aRowId < theItem->rowCount(); aRowId++) + { + subItemsPresentations (theItem->Child (aRowId, theItem->Column()), thePresentations); + } +} + // ======================================================================= // function : createRoot // purpose : diff --git a/tools/TreeModel/TreeModel_ModelBase.hxx b/tools/TreeModel/TreeModel_ModelBase.hxx index b8a31e903e..20b17ae9b3 100644 --- a/tools/TreeModel/TreeModel_ModelBase.hxx +++ b/tools/TreeModel/TreeModel_ModelBase.hxx @@ -180,6 +180,12 @@ public: //! \return model items from the list Standard_EXPORT static QList SelectedItems (const QModelIndexList& theIndices); + //! Returns presentations of sub items + //! \param theIndices a container of selected indices + //! \thePresentations [out] container of presentation handles to be visualized + Standard_EXPORT static void SubItemsPresentations (const QModelIndexList& theIndices, + NCollection_List& thePresentations); + protected: //! Creates root item //! \param theColumnId index of a column @@ -190,6 +196,12 @@ protected: //! \return an item pointer Standard_EXPORT static void* getIndexValue (const TreeModel_ItemBasePtr& theItem); + //! Returns presentations of sub items + //! \param theIndices a container of selected indices + //! \thePresentations [out] container of presentation handles to be visualized + static void subItemsPresentations (const TreeModel_ItemBasePtr& theItem, + NCollection_List& thePresentations); + private: //! Creates root item //! \param theColumnId index of a column diff --git a/tools/VInspector/VInspector_ItemBase.hxx b/tools/VInspector/VInspector_ItemBase.hxx index 4e35513625..cfe70758d8 100644 --- a/tools/VInspector/VInspector_ItemBase.hxx +++ b/tools/VInspector/VInspector_ItemBase.hxx @@ -51,11 +51,6 @@ public: //! \return the value Standard_EXPORT virtual QVariant initValue (const int theItemRole) const Standard_OVERRIDE; - //! Returns presentation of the attribute to be visualized in the view - //! \thePresentations [out] container of presentation handles to be visualized - virtual void Presentations (NCollection_List& thePresentations) - { (void)thePresentations; } - //! Returns transform persistent of the item or NULL Handle(Graphic3d_TransformPers) TransformPersistence() const { return myTransformPersistence; } diff --git a/tools/VInspector/VInspector_ItemPresentableObject.hxx b/tools/VInspector/VInspector_ItemPresentableObject.hxx index 28ea239953..31df492fc6 100644 --- a/tools/VInspector/VInspector_ItemPresentableObject.hxx +++ b/tools/VInspector/VInspector_ItemPresentableObject.hxx @@ -61,7 +61,7 @@ public: //! Returns presentation of the attribute to be visualized in the view //! \thePresentations [out] container of presentation handles to be visualized - Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations); + Standard_EXPORT virtual void Presentations (NCollection_List& thePresentations) Standard_OVERRIDE; protected: diff --git a/tools/VInspector/VInspector_Window.cxx b/tools/VInspector/VInspector_Window.cxx index 1991dbe631..4e76e98113 100644 --- a/tools/VInspector/VInspector_Window.cxx +++ b/tools/VInspector/VInspector_Window.cxx @@ -634,12 +634,12 @@ void VInspector_Window::onExportToShapeView() TCollection_AsciiString aPluginName ("TKShapeView"); NCollection_List aParameters; - if (myParameters->FindParameters (aPluginName)) - aParameters = myParameters->Parameters (aPluginName); + //if (myParameters->FindParameters (aPluginName)) + // aParameters = myParameters->Parameters (aPluginName); NCollection_List anItemNames; - if (myParameters->FindSelectedNames (aPluginName)) - anItemNames = myParameters->GetSelectedNames (aPluginName); + //if (myParameters->FindSelectedNames (aPluginName)) + // anItemNames = myParameters->GetSelectedNames (aPluginName); QStringList anExportedPointers; if (aSelectedShapes.Extent() > 0) @@ -659,23 +659,23 @@ void VInspector_Window::onExportToShapeView() } } - // search for objects to be exported - QList anItems = TreeModel_ModelBase::SelectedItems (myTreeView->selectionModel()->selectedIndexes()); - for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) - { - TreeModel_ItemBasePtr anItem = *anItemIt; - VInspector_ItemBasePtr aVItem = itemDynamicCast(anItem); - if (!aVItem) - continue; - - const Handle(Standard_Transient)& anObject = aVItem->Object(); - if (anObject.IsNull()) - continue; - - aParameters.Append (anObject); - anItemNames.Append (anObject->DynamicType()->Name()); - anExportedPointers.append (Standard_Dump::GetPointerInfo (anObject, true).ToCString()); - } + //// search for objects to be exported + //QList anItems = TreeModel_ModelBase::SelectedItems (myTreeView->selectionModel()->selectedIndexes()); + //for (QList::const_iterator anItemIt = anItems.begin(); anItemIt != anItems.end(); ++anItemIt) + //{ + // TreeModel_ItemBasePtr anItem = *anItemIt; + // VInspector_ItemBasePtr aVItem = itemDynamicCast(anItem); + // if (!aVItem) + // continue; + + // const Handle(Standard_Transient)& anObject = aVItem->Object(); + // if (anObject.IsNull()) + // continue; + + // aParameters.Append (anObject); + // anItemNames.Append (anObject->DynamicType()->Name()); + // anExportedPointers.append (Standard_Dump::GetPointerInfo (anObject, true).ToCString()); + //} if (anExportedPointers.isEmpty()) return; diff --git a/tools/ViewControl/FILES b/tools/ViewControl/FILES index 9fda7a71be..3560ed5779 100644 --- a/tools/ViewControl/FILES +++ b/tools/ViewControl/FILES @@ -3,6 +3,8 @@ ViewControl_MessageDialog.cxx ViewControl_MessageDialog.hxx ViewControl_PropertyView.cxx ViewControl_PropertyView.hxx +ViewControl_PropertiesDialog.cxx +ViewControl_PropertiesDialog.hxx ViewControl_Table.cxx ViewControl_Table.hxx ViewControl_TableModel.cxx diff --git a/tools/ViewControl/ViewControl_PropertiesDialog.cxx b/tools/ViewControl/ViewControl_PropertiesDialog.cxx new file mode 100644 index 0000000000..c72627aa6e --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertiesDialog.cxx @@ -0,0 +1,65 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#include + +#include +#include + +#include +#include +#include +#include +#include + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +ViewControl_PropertiesDialog::ViewControl_PropertiesDialog (QWidget* theParent) +: QDialog (theParent) +{ + setWindowTitle ("Properties"); + + QGridLayout* aLayout = new QGridLayout (this); + myTable = new ViewControl_Table (this); + ViewControl_TableModel* aModel = new ViewControl_TableModel (myTable->TableView()); + myTable->SetModel (aModel); + + aLayout->addWidget(myTable->TableView(), 0, 0, 1, 3); + + myOkButton = new QPushButton ("Ok", this); + myCancelButton = new QPushButton ("Cancel", this); + connect (myOkButton, SIGNAL (clicked()), this, SLOT (accept())); + connect (myCancelButton, SIGNAL (clicked()), this, SLOT (reject())); + aLayout->addWidget (myOkButton, 1, 1); + aLayout->addWidget (myCancelButton, 1, 2); + + aLayout->setColumnStretch (0, 1); + + myCancelButton->setDefault (true); + + setMinimumSize (200, 600); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +void ViewControl_PropertiesDialog::Init (const Handle(TreeModel_ItemProperties)& theProperties) +{ + ViewControl_TableModelValues* aTableValues = new ViewControl_TableModelValues(); + aTableValues->SetProperties (theProperties); + + myTable->Init (aTableValues); +} diff --git a/tools/ViewControl/ViewControl_PropertiesDialog.hxx b/tools/ViewControl/ViewControl_PropertiesDialog.hxx new file mode 100644 index 0000000000..609bcb9226 --- /dev/null +++ b/tools/ViewControl/ViewControl_PropertiesDialog.hxx @@ -0,0 +1,54 @@ +// Copyright (c) 2020 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef ViewControl_PropertiesDialog_H +#define ViewControl_PropertiesDialog_H + +#include +#include + +#include + +#include +#include +#include + +class TreeModel_ItemProperties; + +class QWidget; +class QPushButton; + +//! \class ViewControl_PropertiesDialog +//! Dialog providing table of stream values +class ViewControl_PropertiesDialog : public QDialog +{ + Q_OBJECT +public: + + //! Constructor + Standard_EXPORT ViewControl_PropertiesDialog (QWidget* theParent); + + //! Destructor + virtual ~ViewControl_PropertiesDialog() {} + + Standard_EXPORT void Init (const Handle(TreeModel_ItemProperties)& theProperties); + +private: + ViewControl_Table* myTable; //!< table view + + QPushButton* myOkButton; //!< accept button + QPushButton* myCancelButton; //!< reject button +}; + + +#endif -- 2.39.5