From 49cc3e4cca4f4765ac536200d427e6a26b777fba Mon Sep 17 00:00:00 2001 From: kosta Date: Thu, 9 Feb 2023 22:07:17 +0100 Subject: [PATCH] [bos #32523][EDF] SALOME on Demand GUI. Large getExtTreeWidget() method divided to get info from python to graph and render graph methods. --- src/LightApp/LightApp_ExtInfoDlg.cxx | 99 ++++++++++++++++++++++------ src/LightApp/LightApp_ExtInfoDlg.h | 4 ++ 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/LightApp/LightApp_ExtInfoDlg.cxx b/src/LightApp/LightApp_ExtInfoDlg.cxx index 1695775f4..9589a8f9b 100644 --- a/src/LightApp/LightApp_ExtInfoDlg.cxx +++ b/src/LightApp/LightApp_ExtInfoDlg.cxx @@ -44,6 +44,44 @@ #include #include + +/*! RAII wrapper to graphviz Agraph_t.*/ +class GraphWrapper +{ + public: + virtual ~GraphWrapper(); + + void init(char* name, Agdesc_t desc = Agstrictdirected, Agdisc_t* disc = nullptr); + + Agraph_t* getGraph() const { return m_graph; } + GVC_t* getGvc() const { return m_gvc; } + + private: + Agraph_t* m_graph = nullptr; + GVC_t* m_gvc = nullptr; +}; + +GraphWrapper::~GraphWrapper() +{ + if (m_graph) + { + agclose(m_graph); + m_graph = nullptr; + } + + if (m_gvc) + { + gvFreeContext(m_gvc); + m_gvc = nullptr; + } +} + +void GraphWrapper::init(char *name, Agdesc_t desc /* = Agstrictdirected */, Agdisc_t* disc /* = nullptr */) +{ + m_graph = agopen(name, desc, disc); + m_gvc = gvContext(); +} + /*!Constructor.*/ LightApp_ExtInfoDlg::LightApp_ExtInfoDlg(QWidget* parent) : QtxDialog(parent, true, true, ButtonFlags::OK) @@ -165,33 +203,27 @@ QWidget* LightApp_ExtInfoDlg::getExtListWidget(QWidget* parent) const return extListWidget; } -/*! Return widget with an image of dependency tree fot installed extensions */ -QWidget* LightApp_ExtInfoDlg::getExtTreeWidget(QWidget* parent) const +/*! Fill a given extension tree graph with nodes and edges */ +bool LightApp_ExtInfoDlg::fillExtTreeGraph(const GraphWrapper& graph) const { - MESSAGE("Start to get extensions dependency tree...\n"); - - auto extTreeWidget = new QSvgWidget(parent); + MESSAGE("Start to get info from SalomeOnDemandTK.extension_query...\n"); // Import Python module that manages SALOME extensions PyLockWrapper lck; // acquire GIL PyObjWrapper extensionQuery = PyImport_ImportModule((char*)"SalomeOnDemandTK.extension_query"); auto extRootDir = getenv("SALOME_APPLICATION_DIR"); PyObjWrapper dependencyTree = PyObject_CallMethod(extensionQuery, (char*)"dependency_tree", (char*)"s", extRootDir); - ASSERT(dependencyTree); if (!dependencyTree) { PyErr_Print(); - return extTreeWidget; + return false; } - // Graph to be filled up from python data - char graphName[] = "extTreeGraph"; - Agraph_t* extTreeGraph = agopen(graphName, Agstrictdirected, nullptr); - GVC_t* gvc = gvContext(); + Agraph_t* extTreeGraph = graph.getGraph(); // Python declarations - PyObject *extName = nullptr; - PyObject *dependantsList = nullptr; + PyObject* extName = nullptr; + PyObject* dependantsList = nullptr; Py_ssize_t pos = 0; // Iterate the tree @@ -221,31 +253,58 @@ QWidget* LightApp_ExtInfoDlg::getExtTreeWidget(QWidget* parent) const } } + return true; +} + +/*! Render dependency tree to array of bytes */ +QByteArray LightApp_ExtInfoDlg::renderExtTreeGraph(const GraphWrapper& graph) const +{ + Agraph_t* extTreeGraph = graph.getGraph(); + GVC_t* gvc = graph.getGvc(); + // Layout and render to buffer + MESSAGE("Layout dependency tree...\n"); int res = gvLayout(gvc, extTreeGraph, "dot"); if (res) { MESSAGE("gvLayout failed!\n"); - return extTreeWidget; + return {}; } + MESSAGE("Render dependency tree...\n"); char* buffer = nullptr; unsigned int bufferLength = 0; res = gvRenderData(gvc, extTreeGraph, "svg", &buffer, &bufferLength); if (res) { MESSAGE("gvRenderData failed!\n"); - return extTreeWidget; + return {}; } - // Load the buffer into widget QByteArray renderedGraph(buffer, bufferLength); - extTreeWidget->load(renderedGraph); - - // Clean up section + + // Clean up layout and buffer gvFreeLayout(gvc, extTreeGraph); gvFreeRenderData(buffer); - agclose(extTreeGraph); + + return renderedGraph; +} + +/*! Return widget with an image of dependency tree fot installed extensions */ +QWidget* LightApp_ExtInfoDlg::getExtTreeWidget(QWidget* parent) const +{ + MESSAGE("Start to make a widget to show dependency tree...\n"); + + auto extTreeWidget = new QSvgWidget(parent); + + // Graph to be filled up from python data + GraphWrapper extTreeGraph; + char graphName[] = "extTreeGraph"; + extTreeGraph.init(graphName); + if (fillExtTreeGraph(extTreeGraph)) + { + extTreeWidget->load(renderExtTreeGraph(extTreeGraph)); + } return extTreeWidget; } diff --git a/src/LightApp/LightApp_ExtInfoDlg.h b/src/LightApp/LightApp_ExtInfoDlg.h index 3db7e0a66..b4d9323ce 100644 --- a/src/LightApp/LightApp_ExtInfoDlg.h +++ b/src/LightApp/LightApp_ExtInfoDlg.h @@ -31,6 +31,8 @@ #include class QTableWidget; +class GraphWrapper; +class QByteArray; /*! \class LightApp_ExtInfoDlg @@ -49,6 +51,8 @@ private: QWidget* getExtTreeWidget(QWidget* parent) const; bool fillExtListWidget(QTableWidget* extListWidget) const; + bool fillExtTreeGraph(const GraphWrapper& graph) const; + QByteArray renderExtTreeGraph(const GraphWrapper& graph) const; }; #endif -- 2.39.2