diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 122f88f37..a53b96d6b 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -201,6 +201,32 @@ void Document::writeDependencyGraphViz(std::ostream &out) out << "}" << endl; } +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); + } + } + + if (!names.empty()) + boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0]))); +} + //bool _has_cycle_dfs(const DependencyList & g, vertex_t u, default_color_type * color) //{ // color[u] = gray_color; @@ -906,32 +932,6 @@ 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); - } - } - - if (!names.empty()) - boost::write_graphviz(out, DepList, boost::make_label_writer(&(names[0]))); -} - bool Document::saveAs(const char* file) { Base::FileInfo fi(file); diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 9993d6bcd..9c659d817 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -472,7 +472,7 @@ Py::List DocumentPy::getRedoNames(void) const Py::String DocumentPy::getDependencyGraph(void) const { std::stringstream out; - getDocumentPtr()->writeDependencyGraphViz(out); + getDocumentPtr()->exportGraphviz(out); return Py::String(out.str()); } diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 33a26703f..0dcfded9f 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -167,6 +167,7 @@ set(Gui_MOC_HDRS EditorView.h FileDialog.h Flag.h + GraphvizView.h GuiApplicationNativeEventAware.h HelpView.h InputVector.h @@ -748,7 +749,6 @@ SOURCE_GROUP("View3D\\Inventor" FILES ${Inventor_SRCS}) SET(Widget_CPP_SRCS FileDialog.cpp MainWindow.cpp - MDIView.cpp PrefWidgets.cpp InputField.cpp ProgressBar.cpp @@ -761,7 +761,6 @@ SET(Widget_CPP_SRCS SET(Widget_HPP_SRCS FileDialog.h MainWindow.h - MDIView.h PrefWidgets.h InputField.h ProgressBar.h @@ -777,6 +776,21 @@ SET(Widget_SRCS ) SOURCE_GROUP("Widget" FILES ${Widget_SRCS}) +# The view sources +SET(View_CPP_SRCS + MDIView.cpp + GraphvizView.cpp +) +SET(View_HPP_SRCS + MDIView.h + GraphvizView.h +) +SET(View_SRCS + ${View_CPP_SRCS} + ${View_HPP_SRCS} +) +SOURCE_GROUP("View" FILES ${View_SRCS}) + # The workbench sources SET(Workbench_CPP_SRCS DockWindowManager.cpp @@ -879,6 +893,7 @@ SET(FreeCADGui_SRCS ${View3D_SRCS} ${Viewprovider_SRCS} ${Widget_SRCS} + ${View_SRCS} ${Workbench_SRCS} ${Selection_SRCS} ${FreeCADGui_SRCS} diff --git a/src/Gui/CommandDoc.cpp b/src/Gui/CommandDoc.cpp index 177063305..87e16a578 100644 --- a/src/Gui/CommandDoc.cpp +++ b/src/Gui/CommandDoc.cpp @@ -27,8 +27,6 @@ # include # include # include -# include -# include # include # include # include @@ -67,6 +65,7 @@ #include #include "MergeDocuments.h" #include "NavigationStyle.h" +#include "GraphvizView.h" using namespace Gui; @@ -326,28 +325,6 @@ bool StdCmdMergeProjects::isActive(void) // Std_ExportGraphviz //=========================================================================== -namespace Gui { -class ImageView : public MDIView -{ -public: - ImageView(const QPixmap& p, QWidget* parent=0) : MDIView(0, parent) - { - scene = new QGraphicsScene(); - scene->addPixmap(p); - view = new QGraphicsView(scene, this); - view->show(); - setCentralWidget(view); - } - ~ImageView() - { - delete scene; - delete view; - } - QGraphicsScene* scene; - QGraphicsView* view; -}; -} - DEF_STD_CMD_A(StdCmdExportGraphviz); StdCmdExportGraphviz::StdCmdExportGraphviz() @@ -420,7 +397,8 @@ void StdCmdExportGraphviz::activated(int iMsg) QPixmap px; if (px.loadFromData(proc.readAll(), "PNG")) { - Gui::ImageView* view = new Gui::ImageView(px); + Gui::GraphvizView* view = new Gui::GraphvizView(px); + view->setDependencyGraph(str.str()); view->setWindowTitle(qApp->translate("Std_ExportGraphviz","Dependency graph")); getMainWindow()->addWindow(view); } diff --git a/src/Gui/GraphvizView.cpp b/src/Gui/GraphvizView.cpp new file mode 100644 index 000000000..c678cc783 --- /dev/null +++ b/src/Gui/GraphvizView.cpp @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (c) 2014 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +#endif +# include +# include +#include "FileDialog.h" + + +#include "GraphvizView.h" +#include + +using namespace Gui; + + +GraphvizView::GraphvizView(const QPixmap& p, QWidget* parent) + : MDIView(0, parent) +{ + scene = new QGraphicsScene(); + scene->addPixmap(p); + view = new QGraphicsView(scene, this); + view->show(); + setCentralWidget(view); +} + +GraphvizView::~GraphvizView() +{ + delete scene; + delete view; +} + +void GraphvizView::setDependencyGraph(const std::string& s) +{ + graphCode = s; +} + +QByteArray GraphvizView::exportGraph(const QString& filter) +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Paths"); + QProcess proc; + QStringList args; + if (filter.indexOf(QLatin1String("png")) > 0) + args << QLatin1String("-Tpng"); + else if (filter.indexOf(QLatin1String("svg")) > 0) + args << QLatin1String("-Tsvg"); + else if (filter.indexOf(QLatin1String("pdf")) > 0) + args << QLatin1String("-Tpdf"); + else + return QByteArray(); + +#ifdef FC_OS_LINUX + QString path = QString::fromUtf8(hGrp->GetASCII("Graphviz", "/usr/bin").c_str()); +#else + QString path = QString::fromUtf8(hGrp->GetASCII("Graphviz").c_str()); +#endif + +#ifdef FC_OS_WIN32 + QString exe = QString::fromAscii("\"%1/dot\"").arg(path); +#else + QString exe = QString::fromAscii("%1/dot").arg(path); +#endif + proc.setEnvironment(QProcess::systemEnvironment()); + proc.start(exe, args); + if (!proc.waitForStarted()) { + return QByteArray(); + } + + proc.write(graphCode.c_str(), graphCode.size()); + proc.closeWriteChannel(); + if (!proc.waitForFinished()) + return QByteArray(); + + return proc.readAll(); +} + +bool GraphvizView::onMsg(const char* pMsg,const char** ppReturn) +{ + if (strcmp("Save",pMsg) == 0 || strcmp("SaveAs",pMsg) == 0) { + QStringList filter; + filter << tr("PNG format (*.png)"); + filter << tr("SVG format (*.svg)"); + filter << tr("PDF format (*.pdf)"); + + QString selectedFilter; + QString fn = Gui::FileDialog::getSaveFileName(this, tr("Export graph"), QString(), filter.join(QLatin1String(";;")), &selectedFilter); + if (!fn.isEmpty()) { + QByteArray buffer = exportGraph(selectedFilter); + if (buffer.isEmpty()) + return false; + QFile file(fn); + if (file.open(QFile::WriteOnly)) { + file.write(buffer); + file.close(); + return true; + } + } + } + else if (strcmp("Print",pMsg) == 0) { + return true; + } + else if (strcmp("PrintPreview",pMsg) == 0) { + return true; + } + else if (strcmp("PrintPdf",pMsg) == 0) { + return true; + } + + return false; +} + +bool GraphvizView::onHasMsg(const char* pMsg) const +{ + if (strcmp("Save",pMsg) == 0) + return true; + else if (strcmp("SaveAs",pMsg) == 0) + return true; + else if (strcmp("Print",pMsg) == 0) + return true; + else if (strcmp("PrintPreview",pMsg) == 0) + return true; + else if (strcmp("PrintPdf",pMsg) == 0) + return true; + return false; +} + +void GraphvizView::print(QPrinter* printer) +{ + QPainter p(printer); + QRect rect = printer->pageRect(); + view->scene()->render(&p, rect); + //QByteArray buffer = exportGraph(QString::fromLatin1("(*.svg)")); + //QSvgRenderer svg(buffer); + //svg.render(&p, rect); + p.end(); +} + +void GraphvizView::print() +{ + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + printer.setOrientation(QPrinter::Landscape); + QPrintDialog dlg(&printer, this); + if (dlg.exec() == QDialog::Accepted) { + print(&printer); + } +} + +void GraphvizView::printPdf() +{ + QStringList filter; + filter << tr("PDF format (*.pdf)"); + + QString selectedFilter; + QString fn = Gui::FileDialog::getSaveFileName(this, tr("Export graph"), QString(), filter.join(QLatin1String(";;")), &selectedFilter); + if (!fn.isEmpty()) { + QByteArray buffer = exportGraph(selectedFilter); + if (buffer.isEmpty()) + return; + QFile file(fn); + if (file.open(QFile::WriteOnly)) { + file.write(buffer); + file.close(); + } + } +} + +void GraphvizView::printPreview() +{ + QPrinter printer(QPrinter::HighResolution); + printer.setFullPage(true); + printer.setOrientation(QPrinter::Landscape); + + QPrintPreviewDialog dlg(&printer, this); + connect(&dlg, SIGNAL(paintRequested (QPrinter *)), + this, SLOT(print(QPrinter *))); + dlg.exec(); +} + +#include "moc_GraphvizView.cpp" diff --git a/src/Gui/GraphvizView.h b/src/Gui/GraphvizView.h new file mode 100644 index 000000000..492ff7609 --- /dev/null +++ b/src/Gui/GraphvizView.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (c) 2014 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_GRAPHVIZVIEW_H +#define GUI_GRAPHVIZVIEW_H + +#include "MDIView.h" + +class QGraphicsScene; +class QGraphicsView; + +namespace Gui +{ +class GuiExport GraphvizView : public MDIView +{ + Q_OBJECT + +public: + GraphvizView(const QPixmap&, QWidget* parent=0); + ~GraphvizView(); + + void setDependencyGraph(const std::string&); + QByteArray exportGraph(const QString& filter); + + /// Message handler + virtual bool onMsg(const char* pMsg,const char** ppReturn); + /// Message handler test + virtual bool onHasMsg(const char* pMsg) const; + /** @name Printing */ + //@{ + virtual void print(QPrinter* printer); + /** Print content of view */ + virtual void print(); + /** Print to PDF file */ + virtual void printPdf(); + /** Show a preview dialog */ + virtual void printPreview(); + //@} + +private: + std::string graphCode; + QGraphicsScene* scene; + QGraphicsView* view; +}; + +} // namespace Gui + +#endif // GUI_GRAPHVIZVIEW_H