From 9170bfe0451cea8dd63650995af2db4575b3ad4d Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 12 Jun 2012 19:03:29 +0200 Subject: [PATCH] Export object dependencies to graphviz file --- src/App/Document.cpp | 25 ++++++++++ src/App/Document.h | 1 + src/App/DocumentPy.xml | 5 ++ src/App/DocumentPyImp.cpp | 19 ++++++++ src/Gui/CommandDoc.cpp | 76 ++++++++++++++++++++++++++++++ src/Gui/Workbench.cpp | 5 +- src/Mod/Complete/Gui/Workbench.cpp | 3 +- 7 files changed, 131 insertions(+), 3 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 61d1b7921..cba2e757b 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -847,6 +847,31 @@ unsigned int Document::getMemSize (void) const return size; } +void Document::exportGraphviz(std::ostream& out) +{ + std::vector names; + names.reserve(d->objectMap.size()); + DependencyList DepList; + std::map VertexObjectList; + + // Filling up the adjacency List + for (std::map::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) { + // add the object as Vertex and remember the index + VertexObjectList[It->second] = add_vertex(DepList); + names.push_back(It->second->Label.getValue()); + } + // add the edges + for (std::map::const_iterator It = d->objectMap.begin(); It != d->objectMap.end();++It) { + std::vector OutList = It->second->getOutList(); + for (std::vector::const_iterator It2=OutList.begin();It2!=OutList.end();++It2) { + if (*It2) + add_edge(VertexObjectList[It->second],VertexObjectList[*It2],DepList); + } + } + + boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0]))); +} + // Save the document under the name it has been opened bool Document::save (void) { diff --git a/src/App/Document.h b/src/App/Document.h index 38b247a20..9b705e8c9 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -114,6 +114,7 @@ public: /// Restore the document from the file in Property Path void restore (void); void exportObjects(const std::vector&, std::ostream&); + void exportGraphviz(std::ostream&); std::vector importObjects(std::istream&); /// Opens the document from its file name //void open (void); diff --git a/src/App/DocumentPy.xml b/src/App/DocumentPy.xml index 3897af801..4a996e111 100644 --- a/src/App/DocumentPy.xml +++ b/src/App/DocumentPy.xml @@ -23,6 +23,11 @@ Restore the document from disc + + + Export the dependencies of the objects as graph + + Open a new Undo/Redo transaction. diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 64b04d8b9..4b5d805d4 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -92,6 +92,25 @@ PyObject* DocumentPy::restore(PyObject * args) Py_Return; } +PyObject* DocumentPy::exportGraphviz(PyObject * args) +{ + char* fn=0; + if (!PyArg_ParseTuple(args, "|s",&fn)) // convert args: Python->C + return NULL; // NULL triggers exception + if (fn) { + Base::FileInfo fi(fn); + Base::ofstream str(fi); + getDocumentPtr()->exportGraphviz(str); + str.close(); + Py_Return; + } + else { + std::stringstream str; + getDocumentPtr()->exportGraphviz(str); + return PyString_FromString(str.str().c_str()); + } +} + PyObject* DocumentPy::addObject(PyObject *args) { char *sType,*sName=0; diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index a445f68c1..a83d5ea5e 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -24,12 +24,16 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include # include # include +# include +# include #endif #include #include +#include #include #include #include @@ -311,6 +315,77 @@ bool StdCmdMergeProjects::isActive(void) return this->hasActiveDocument(); } +//=========================================================================== +// Std_ExportGraphviz +//=========================================================================== + +DEF_STD_CMD_A(StdCmdExportGraphviz); + +StdCmdExportGraphviz::StdCmdExportGraphviz() + : Command("Std_ExportGraphviz") +{ + // seting the + sGroup = QT_TR_NOOP("Tools"); + sMenuText = QT_TR_NOOP("Dependency graph..."); + sToolTipText = QT_TR_NOOP("Show the dependency graph of the objects in the active document"); + sStatusTip = QT_TR_NOOP("Show the dependency graph of the objects in the active document"); + sWhatsThis = "Std_ExportGraphviz"; + eType = 0; +} + +void StdCmdExportGraphviz::activated(int iMsg) +{ + App::Document* doc = App::GetApplication().getActiveDocument(); + Base::FileInfo fi(Base::FileInfo::getTempFileName()); + Base::ofstream str(fi); + doc->exportGraphviz(str); + str.close(); + + Base::FileInfo out(Base::FileInfo::getTempFileName()); + QProcess proc; + QEventLoop loop; + QObject::connect(&proc, SIGNAL(finished(int, QProcess::ExitStatus)), + &loop, SLOT(quit())); + QStringList args; + args << QLatin1String("-Tpng") << QString::fromUtf8(fi.filePath().c_str()) + << QLatin1String("-o") << QString::fromUtf8(out.filePath().c_str()); + QString exe = QLatin1String("dot"); + QStringList env = QProcess::systemEnvironment(); + proc.setEnvironment(env); + proc.start(exe, args); + if (proc.state() == QProcess::Running) { + loop.exec(); + fi.deleteFile(); + } + else { + QMessageBox::warning(getMainWindow(), + qApp->translate("Std_ExportGraphviz","Graphviz not found"), + qApp->translate("Std_ExportGraphviz","Graphviz couldn't be found on your system")); + fi.deleteFile(); + return; + } + + if (out.exists()) { + QPixmap px(QString::fromUtf8(out.filePath().c_str()), "PNG"); + out.deleteFile(); + QLabel* label = new QLabel(0); + label->setAttribute(Qt::WA_DeleteOnClose); + label->setPixmap(px); + label->resize(px.size()); + label->show(); + } + else { + QMessageBox::warning(getMainWindow(), + qApp->translate("Std_ExportGraphviz","Graphviz failed"), + qApp->translate("Std_ExportGraphviz","Graphviz failed to create an image file")); + } +} + +bool StdCmdExportGraphviz::isActive(void) +{ + return (getActiveGuiDocument() ? true : false); +} + //=========================================================================== // Std_New //=========================================================================== @@ -1126,6 +1201,7 @@ void CreateDocCommands(void) rcCmdMgr.addCommand(new StdCmdImport()); rcCmdMgr.addCommand(new StdCmdExport()); rcCmdMgr.addCommand(new StdCmdMergeProjects()); + rcCmdMgr.addCommand(new StdCmdExportGraphviz()); rcCmdMgr.addCommand(new StdCmdSave()); rcCmdMgr.addCommand(new StdCmdSaveAs()); diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index 26ca5d698..f055c2443 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -490,8 +490,9 @@ MenuItem* StdWorkbench::setupMenuBar() const MenuItem* tool = new MenuItem( menuBar ); tool->setCommand("&Tools"); *tool << "Std_DlgParameter" << "Separator" - << "Std_ViewScreenShot" << "Std_SceneInspector" << "Std_DemoMode" - << "Separator" << "Std_DlgCustomize"; + << "Std_ViewScreenShot" << "Std_SceneInspector" + << "Std_ExportGraphviz" << "Std_ProjectUtil" + << "Std_DemoMode" << "Separator" << "Std_DlgCustomize"; // Macro MenuItem* macro = new MenuItem( menuBar ); diff --git a/src/Mod/Complete/Gui/Workbench.cpp b/src/Mod/Complete/Gui/Workbench.cpp index 9b0b0fcf0..707e32131 100644 --- a/src/Mod/Complete/Gui/Workbench.cpp +++ b/src/Mod/Complete/Gui/Workbench.cpp @@ -183,7 +183,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Std_DlgMacroRecord" << "Std_MacroStopRecord" << "Std_DlgMacroExecute" << "Std_DlgMacroExecuteDirect" << "Separator" << "Std_ViewScreenShot" << "Std_SceneInspector" - << "Std_ProjectUtil" << "Std_DemoMode" << "Separator" << "Std_DlgCustomize"; + << "Std_ExportGraphviz" << "Std_ProjectUtil" + << "Std_DemoMode" << "Separator" << "Std_DlgCustomize"; // Mesh **************************************************************************************************** Gui::MenuItem* mesh = new Gui::MenuItem( menuBar );