Added zoom and automatic refresh of dependency graph view.
This commit is contained in:
parent
1749ff2d5d
commit
f99fd100e6
|
@ -200,7 +200,7 @@ void Document::writeDependencyGraphViz(std::ostream &out)
|
||||||
out << "}" << endl;
|
out << "}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::exportGraphviz(std::ostream& out)
|
void Document::exportGraphviz(std::ostream& out) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
names.reserve(d->objectMap.size());
|
names.reserve(d->objectMap.size());
|
||||||
|
@ -1437,6 +1437,8 @@ void Document::recompute()
|
||||||
it->second->purgeTouched();
|
it->second->purgeTouched();
|
||||||
}
|
}
|
||||||
d->vertexMap.clear();
|
d->vertexMap.clear();
|
||||||
|
|
||||||
|
signalRecomputed(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Document::getErrorDescription(const App::DocumentObject*Obj) const
|
const char * Document::getErrorDescription(const App::DocumentObject*Obj) const
|
||||||
|
|
|
@ -129,6 +129,7 @@ public:
|
||||||
Base::XMLReader&)> signalImportObjects;
|
Base::XMLReader&)> signalImportObjects;
|
||||||
boost::signal<void (const std::vector<App::DocumentObject*>&, Base::Reader&,
|
boost::signal<void (const std::vector<App::DocumentObject*>&, Base::Reader&,
|
||||||
const std::map<std::string, std::string>&)> signalImportViewObjects;
|
const std::map<std::string, std::string>&)> signalImportViewObjects;
|
||||||
|
boost::signal<void (const App::Document&)> signalRecomputed;
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/** @name File handling of the document */
|
/** @name File handling of the document */
|
||||||
|
@ -141,7 +142,7 @@ public:
|
||||||
/// Restore the document from the file in Property Path
|
/// Restore the document from the file in Property Path
|
||||||
void restore (void);
|
void restore (void);
|
||||||
void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&);
|
void exportObjects(const std::vector<App::DocumentObject*>&, std::ostream&);
|
||||||
void exportGraphviz(std::ostream&);
|
void exportGraphviz(std::ostream&) const;
|
||||||
std::vector<App::DocumentObject*> importObjects(Base::XMLReader& reader);
|
std::vector<App::DocumentObject*> importObjects(Base::XMLReader& reader);
|
||||||
/// Opens the document from its file name
|
/// Opens the document from its file name
|
||||||
//void open (void);
|
//void open (void);
|
||||||
|
|
|
@ -201,6 +201,7 @@ set(Gui_MOC_HDRS
|
||||||
EditorView.h
|
EditorView.h
|
||||||
FileDialog.h
|
FileDialog.h
|
||||||
Flag.h
|
Flag.h
|
||||||
|
GraphicsViewZoom.h
|
||||||
GraphvizView.h
|
GraphvizView.h
|
||||||
GuiApplicationNativeEventAware.h
|
GuiApplicationNativeEventAware.h
|
||||||
HelpView.h
|
HelpView.h
|
||||||
|
@ -253,6 +254,12 @@ set(Gui_MOC_HDRS
|
||||||
fc_wrap_cpp(Gui_MOC_SRCS ${Gui_MOC_HDRS})
|
fc_wrap_cpp(Gui_MOC_SRCS ${Gui_MOC_HDRS})
|
||||||
#SOURCE_GROUP("Moc" FILES ${Gui_MOC_SRCS})
|
#SOURCE_GROUP("Moc" FILES ${Gui_MOC_SRCS})
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/moc_GraphvizView-internal.cpp
|
||||||
|
COMMAND ${QT_MOC_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/moc_GraphvizView-internal.cpp ${CMAKE_CURRENT_SOURCE_DIR}/GraphvizView.cpp
|
||||||
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/GraphvizView.cpp)
|
||||||
|
|
||||||
|
set_property(SOURCE GraphvizView.cpp APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/moc_GraphvizView-internal.cpp)
|
||||||
|
|
||||||
SET(Gui_UIC_SRCS
|
SET(Gui_UIC_SRCS
|
||||||
AboutApplication.ui
|
AboutApplication.ui
|
||||||
Clipping.ui
|
Clipping.ui
|
||||||
|
@ -915,6 +922,7 @@ SET(FreeCADGui_CPP_SRCS
|
||||||
Document.cpp
|
Document.cpp
|
||||||
DocumentModel.cpp
|
DocumentModel.cpp
|
||||||
DocumentPyImp.cpp
|
DocumentPyImp.cpp
|
||||||
|
GraphicsViewZoom.cpp
|
||||||
GuiApplicationNativeEventAware.cpp
|
GuiApplicationNativeEventAware.cpp
|
||||||
GuiConsole.cpp
|
GuiConsole.cpp
|
||||||
Macro.cpp
|
Macro.cpp
|
||||||
|
@ -934,6 +942,7 @@ SET(FreeCADGui_SRCS
|
||||||
Document.h
|
Document.h
|
||||||
DocumentModel.h
|
DocumentModel.h
|
||||||
FreeCADGuiInit.py
|
FreeCADGuiInit.py
|
||||||
|
GraphicsViewZoom.h
|
||||||
GuiApplicationNativeEventAware.h
|
GuiApplicationNativeEventAware.h
|
||||||
GuiConsole.h
|
GuiConsole.h
|
||||||
InventorAll.h
|
InventorAll.h
|
||||||
|
|
|
@ -361,72 +361,10 @@ StdCmdExportGraphviz::StdCmdExportGraphviz()
|
||||||
void StdCmdExportGraphviz::activated(int iMsg)
|
void StdCmdExportGraphviz::activated(int iMsg)
|
||||||
{
|
{
|
||||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||||
std::stringstream str;
|
Gui::GraphvizView* view = new Gui::GraphvizView(*doc);
|
||||||
doc->exportGraphviz(str);
|
|
||||||
|
|
||||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Paths");
|
|
||||||
QProcess proc;
|
|
||||||
QStringList args;
|
|
||||||
args << QLatin1String("-Tpng");
|
|
||||||
#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
|
|
||||||
bool pathChanged = false;
|
|
||||||
#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());
|
|
||||||
do {
|
|
||||||
proc.start(exe, args);
|
|
||||||
if (!proc.waitForStarted()) {
|
|
||||||
int ret = QMessageBox::warning(getMainWindow(),
|
|
||||||
qApp->translate("Std_ExportGraphviz","Graphviz not found"),
|
|
||||||
qApp->translate("Std_ExportGraphviz","Graphviz couldn't be found on your system.\n"
|
|
||||||
"Do you want to specify its installation path if it's already installed?"),
|
|
||||||
QMessageBox::Yes, QMessageBox::No);
|
|
||||||
if (ret == QMessageBox::No)
|
|
||||||
return;
|
|
||||||
path = QFileDialog::getExistingDirectory(Gui::getMainWindow(),
|
|
||||||
qApp->translate("Std_ExportGraphviz","Graphviz installation path"));
|
|
||||||
if (path.isEmpty())
|
|
||||||
return;
|
|
||||||
pathChanged = true;
|
|
||||||
#ifdef FC_OS_WIN32
|
|
||||||
exe = QString::fromAscii("\"%1/dot\"").arg(path);
|
|
||||||
#else
|
|
||||||
exe = QString::fromAscii("%1/dot").arg(path);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (pathChanged)
|
|
||||||
hGrp->SetASCII("Graphviz", (const char*)path.toUtf8());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while(true);
|
|
||||||
|
|
||||||
proc.write(str.str().c_str(), str.str().size());
|
|
||||||
proc.closeWriteChannel();
|
|
||||||
if (!proc.waitForFinished())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QPixmap px;
|
|
||||||
if (px.loadFromData(proc.readAll(), "PNG")) {
|
|
||||||
Gui::GraphvizView* view = new Gui::GraphvizView(px);
|
|
||||||
view->setDependencyGraph(str.str());
|
|
||||||
view->setWindowTitle(qApp->translate("Std_ExportGraphviz","Dependency graph"));
|
view->setWindowTitle(qApp->translate("Std_ExportGraphviz","Dependency graph"));
|
||||||
getMainWindow()->addWindow(view);
|
getMainWindow()->addWindow(view);
|
||||||
}
|
}
|
||||||
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)
|
bool StdCmdExportGraphviz::isActive(void)
|
||||||
{
|
{
|
||||||
|
|
94
src/Gui/GraphicsViewZoom.cpp
Normal file
94
src/Gui/GraphicsViewZoom.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (c) 2015 Pavel Strakhov <ri@idzaaus.org> *
|
||||||
|
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on
|
||||||
|
*
|
||||||
|
* http://stackoverflow.com/questions/19113532/qgraphicsview-zooming-in-and-out-under-mouse-position-using-mouse-wheel
|
||||||
|
*
|
||||||
|
* Re-licensed to LGPL after having contacted original author by e-mail.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PreCompiled.h"
|
||||||
|
#ifndef _PreComp_
|
||||||
|
# include <QGraphicsView>
|
||||||
|
# include <QMouseEvent>
|
||||||
|
# include <QApplication>
|
||||||
|
# include <QScrollBar>
|
||||||
|
# include <qmath.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GraphicsViewZoom.h>
|
||||||
|
|
||||||
|
GraphicsViewZoom::GraphicsViewZoom(QGraphicsView* view)
|
||||||
|
: QObject(view), _view(view)
|
||||||
|
{
|
||||||
|
_view->viewport()->installEventFilter(this);
|
||||||
|
_view->setMouseTracking(true);
|
||||||
|
_modifiers = Qt::ControlModifier;
|
||||||
|
_zoom_factor_base = 1.0015;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsViewZoom::gentle_zoom(double factor) {
|
||||||
|
_view->scale(factor, factor);
|
||||||
|
_view->centerOn(target_scene_pos);
|
||||||
|
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
|
||||||
|
_view->viewport()->height() / 2.0);
|
||||||
|
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
|
||||||
|
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsViewZoom::set_modifiers(Qt::KeyboardModifiers modifiers) {
|
||||||
|
_modifiers = modifiers;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsViewZoom::set_zoom_factor_base(double value) {
|
||||||
|
_zoom_factor_base = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsViewZoom::eventFilter(QObject *object, QEvent *event) {
|
||||||
|
if (event->type() == QEvent::MouseMove) {
|
||||||
|
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
|
||||||
|
QPointF delta = target_viewport_pos - mouse_event->pos();
|
||||||
|
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
|
||||||
|
target_viewport_pos = mouse_event->pos();
|
||||||
|
target_scene_pos = _view->mapToScene(mouse_event->pos());
|
||||||
|
}
|
||||||
|
} else if (event->type() == QEvent::Wheel) {
|
||||||
|
QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
|
||||||
|
if (QApplication::keyboardModifiers() == _modifiers) {
|
||||||
|
if (wheel_event->orientation() == Qt::Vertical) {
|
||||||
|
double angle = wheel_event->delta();
|
||||||
|
double factor = qPow(_zoom_factor_base, angle);
|
||||||
|
gentle_zoom(factor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Q_UNUSED(object);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_GraphicsViewZoom.cpp"
|
90
src/Gui/GraphicsViewZoom.h
Normal file
90
src/Gui/GraphicsViewZoom.h
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* Copyright (c) 2015 Pavel Strakhov <ri@idzaaus.org> *
|
||||||
|
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||||
|
* *
|
||||||
|
* 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 *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on
|
||||||
|
*
|
||||||
|
* http://stackoverflow.com/questions/19113532/qgraphicsview-zooming-in-and-out-under-mouse-position-using-mouse-wheel
|
||||||
|
*
|
||||||
|
* Re-licensed to LGPL after having contacted original author by e-mail.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GRAPHICSVIEWZOOM_H
|
||||||
|
#define GRAPHICSVIEWZOOM_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This class adds ability to zoom QGraphicsView using mouse wheel. The point under cursor
|
||||||
|
* remains motionless while it's possible.
|
||||||
|
*
|
||||||
|
* Note that it becomes not possible when the scene's
|
||||||
|
* size is not large enough comparing to the viewport size. QGraphicsView centers the picture
|
||||||
|
* when it's smaller than the view. And QGraphicsView's scrolls boundaries don't allow to
|
||||||
|
* put any picture point at any viewport position.
|
||||||
|
*
|
||||||
|
* When the user starts scrolling, this class remembers original scene position and
|
||||||
|
* keeps it until scrolling is completed. It's better than getting original scene position at
|
||||||
|
* each scrolling step because that approach leads to position errors due to before-mentioned
|
||||||
|
* positioning restrictions.
|
||||||
|
*
|
||||||
|
* When zommed using scroll, this class emits zoomed() signal.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* new GraphicsViewZoom(view);
|
||||||
|
*
|
||||||
|
* The object will be deleted automatically when the view is deleted.
|
||||||
|
*
|
||||||
|
* You can set keyboard modifiers used for zooming using set_modified(). Zooming will be
|
||||||
|
* performed only on exact match of modifiers combination. The default modifier is Ctrl.
|
||||||
|
*
|
||||||
|
* You can change zoom velocity by calling set_zoom_factor_base().
|
||||||
|
* Zoom coefficient is calculated as zoom_factor_base^angle_delta
|
||||||
|
* (see QWheelEvent::angleDelta).
|
||||||
|
* The default zoom factor base is 1.0015.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QGraphicsView;
|
||||||
|
|
||||||
|
class GraphicsViewZoom : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GraphicsViewZoom(QGraphicsView* view);
|
||||||
|
void gentle_zoom(double factor);
|
||||||
|
void set_modifiers(Qt::KeyboardModifiers modifiers);
|
||||||
|
void set_zoom_factor_base(double value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QGraphicsView* _view;
|
||||||
|
Qt::KeyboardModifiers _modifiers;
|
||||||
|
double _zoom_factor_base;
|
||||||
|
QPointF target_scene_pos, target_viewport_pos;
|
||||||
|
bool eventFilter(QObject* object, QEvent* event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GRAPHICSVIEWZOOM_H
|
|
@ -24,32 +24,120 @@
|
||||||
#include "PreCompiled.h"
|
#include "PreCompiled.h"
|
||||||
|
|
||||||
#ifndef _PreComp_
|
#ifndef _PreComp_
|
||||||
|
# include <QApplication>
|
||||||
# include <QFile>
|
# include <QFile>
|
||||||
# include <QPrinter>
|
# include <QPrinter>
|
||||||
# include <QPrintDialog>
|
# include <QPrintDialog>
|
||||||
# include <QPrintPreviewDialog>
|
# include <QPrintPreviewDialog>
|
||||||
# include <QProcess>
|
# include <QProcess>
|
||||||
# include <QSvgRenderer>
|
# include <QSvgRenderer>
|
||||||
#endif
|
# include <QGraphicsSvgItem>
|
||||||
|
# include <QMessageBox>
|
||||||
# include <QGraphicsScene>
|
# include <QGraphicsScene>
|
||||||
# include <QGraphicsView>
|
# include <QGraphicsView>
|
||||||
|
# include <QThread>
|
||||||
|
# include <QProcess>
|
||||||
|
# include <boost/bind.hpp>
|
||||||
|
#endif
|
||||||
|
#include "GraphicsViewZoom.h"
|
||||||
#include "FileDialog.h"
|
#include "FileDialog.h"
|
||||||
|
|
||||||
|
|
||||||
#include "GraphvizView.h"
|
#include "GraphvizView.h"
|
||||||
|
#include "Application.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include <App/Application.h>
|
#include <App/Application.h>
|
||||||
|
#include <App/Document.h>
|
||||||
|
|
||||||
using namespace Gui;
|
using namespace Gui;
|
||||||
|
|
||||||
|
namespace Gui {
|
||||||
|
|
||||||
GraphvizView::GraphvizView(const QPixmap& p, QWidget* parent)
|
/**
|
||||||
: MDIView(0, parent)
|
* @brief The GraphvizWorker class
|
||||||
|
*
|
||||||
|
* Implements a QThread class that does the actual conversion from dot to
|
||||||
|
* svg. All critical communcation is done using queued signals.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class GraphvizWorker : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GraphvizWorker(QObject * parent = 0)
|
||||||
|
: QThread(parent)
|
||||||
{
|
{
|
||||||
|
proc.moveToThread(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setData(const QByteArray & data)
|
||||||
|
{
|
||||||
|
str = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
// Write data to process
|
||||||
|
proc.write(str);
|
||||||
|
proc.closeWriteChannel();
|
||||||
|
if (!proc.waitForFinished()) {
|
||||||
|
Q_EMIT error();
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit result; it will get queued for processing in the main thread
|
||||||
|
Q_EMIT svgFileRead(proc.readAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess * process() {
|
||||||
|
return &proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void svgFileRead(const QByteArray & data);
|
||||||
|
void error();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QProcess proc;
|
||||||
|
QByteArray str;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphvizView::GraphvizView(App::Document & _doc, QWidget* parent)
|
||||||
|
: MDIView(0, parent)
|
||||||
|
, doc(_doc)
|
||||||
|
, nPending(0)
|
||||||
|
{
|
||||||
|
// Create scene
|
||||||
scene = new QGraphicsScene();
|
scene = new QGraphicsScene();
|
||||||
scene->addPixmap(p);
|
|
||||||
|
// Create item to hold the graph
|
||||||
|
svgItem = new QGraphicsSvgItem();
|
||||||
|
renderer = new QSvgRenderer(this);
|
||||||
|
svgItem->setSharedRenderer(renderer);
|
||||||
|
scene->addItem(svgItem);
|
||||||
|
|
||||||
|
// Create view and zoomer object
|
||||||
view = new QGraphicsView(scene, this);
|
view = new QGraphicsView(scene, this);
|
||||||
|
zoomer = new GraphicsViewZoom(view);
|
||||||
|
zoomer->set_modifiers(Qt::NoModifier);
|
||||||
view->show();
|
view->show();
|
||||||
|
|
||||||
|
// Set central widget to view
|
||||||
setCentralWidget(view);
|
setCentralWidget(view);
|
||||||
|
|
||||||
|
// Create worker thread
|
||||||
|
thread = new GraphvizWorker(this);
|
||||||
|
connect(thread, SIGNAL(finished()), this, SLOT(done()));
|
||||||
|
connect(thread, SIGNAL(error()), this, SLOT(error()));
|
||||||
|
connect(thread, SIGNAL(svgFileRead(const QByteArray &)), this, SLOT(svgFileRead(const QByteArray &)));
|
||||||
|
|
||||||
|
// Connect signal from document
|
||||||
|
recomputeConnection = _doc.signalRecomputed.connect(boost::bind(&GraphvizView::updateSvgItem, this, _1));
|
||||||
|
undoConnection = _doc.signalUndo.connect(boost::bind(&GraphvizView::updateSvgItem, this, _1));
|
||||||
|
redoConnection = _doc.signalRedo.connect(boost::bind(&GraphvizView::updateSvgItem, this, _1));
|
||||||
|
|
||||||
|
updateSvgItem(_doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphvizView::~GraphvizView()
|
GraphvizView::~GraphvizView()
|
||||||
|
@ -58,10 +146,111 @@ GraphvizView::~GraphvizView()
|
||||||
delete view;
|
delete view;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphvizView::setDependencyGraph(const std::string& s)
|
void GraphvizView::updateSvgItem(const App::Document &doc)
|
||||||
{
|
{
|
||||||
graphCode = s;
|
nPending++;
|
||||||
|
|
||||||
|
// Skip if thread is working now
|
||||||
|
if (nPending > 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Paths");
|
||||||
|
QProcess * proc = thread->process();
|
||||||
|
QStringList args;
|
||||||
|
args << QLatin1String("-Tsvg");
|
||||||
|
#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
|
||||||
|
bool pathChanged = false;
|
||||||
|
#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());
|
||||||
|
do {
|
||||||
|
proc->start(exe, args);
|
||||||
|
if (!proc->waitForStarted()) {
|
||||||
|
int ret = QMessageBox::warning(Gui::getMainWindow(),
|
||||||
|
qApp->translate("Std_ExportGraphviz","Graphviz not found"),
|
||||||
|
qApp->translate("Std_ExportGraphviz","Graphviz couldn't be found on your system.\n"
|
||||||
|
"Do you want to specify its installation path if it's already installed?"),
|
||||||
|
QMessageBox::Yes, QMessageBox::No);
|
||||||
|
if (ret == QMessageBox::No) {
|
||||||
|
disconnectSignals();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
path = QFileDialog::getExistingDirectory(Gui::getMainWindow(),
|
||||||
|
qApp->translate("Std_ExportGraphviz","Graphviz installation path"));
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
disconnectSignals();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pathChanged = true;
|
||||||
|
#ifdef FC_OS_WIN32
|
||||||
|
exe = QString::fromAscii("\"%1/dot\"").arg(path);
|
||||||
|
#else
|
||||||
|
exe = QString::fromAscii("%1/dot").arg(path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (pathChanged)
|
||||||
|
hGrp->SetASCII("Graphviz", (const char*)path.toUtf8());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(true);
|
||||||
|
|
||||||
|
// Create graph in dot format
|
||||||
|
std::stringstream stream;
|
||||||
|
doc.exportGraphviz(stream);
|
||||||
|
graphCode = stream.str();
|
||||||
|
|
||||||
|
// Update worker thread, and start it
|
||||||
|
thread->setData(QByteArray(graphCode.c_str(), graphCode.size()));
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphvizView::svgFileRead(const QByteArray & data)
|
||||||
|
{
|
||||||
|
// Update renderer with new SVG file, and give message if something went wrong
|
||||||
|
if (renderer->load(data))
|
||||||
|
svgItem->setSharedRenderer(renderer);
|
||||||
|
else {
|
||||||
|
QMessageBox::warning(getMainWindow(),
|
||||||
|
qApp->translate("Std_ExportGraphviz","Graphviz failed"),
|
||||||
|
qApp->translate("Std_ExportGraphviz","Graphviz failed to create an image file"));
|
||||||
|
disconnectSignals();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphvizView::error()
|
||||||
|
{
|
||||||
|
// If the worker fails for some reason, stop giving it more data later
|
||||||
|
disconnectSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphvizView::done()
|
||||||
|
{
|
||||||
|
nPending--;
|
||||||
|
if (nPending > 0) {
|
||||||
|
nPending = 0;
|
||||||
|
updateSvgItem(doc);
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphvizView::disconnectSignals()
|
||||||
|
{
|
||||||
|
recomputeConnection.disconnect();
|
||||||
|
undoConnection.disconnect();
|
||||||
|
redoConnection.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
|
||||||
QByteArray GraphvizView::exportGraph(const QString& format)
|
QByteArray GraphvizView::exportGraph(const QString& format)
|
||||||
{
|
{
|
||||||
|
@ -217,3 +406,4 @@ void GraphvizView::printPreview()
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_GraphvizView.cpp"
|
#include "moc_GraphvizView.cpp"
|
||||||
|
#include "moc_GraphvizView-internal.cpp"
|
||||||
|
|
|
@ -25,21 +25,29 @@
|
||||||
#define GUI_GRAPHVIZVIEW_H
|
#define GUI_GRAPHVIZVIEW_H
|
||||||
|
|
||||||
#include "MDIView.h"
|
#include "MDIView.h"
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/signals.hpp>
|
||||||
|
|
||||||
|
|
||||||
class QGraphicsScene;
|
class QGraphicsScene;
|
||||||
class QGraphicsView;
|
class QGraphicsView;
|
||||||
|
class QSvgRenderer;
|
||||||
|
class QGraphicsSvgItem;
|
||||||
|
class GraphicsViewZoom;
|
||||||
|
|
||||||
namespace Gui
|
namespace Gui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class GraphvizWorker;
|
||||||
|
|
||||||
class GuiExport GraphvizView : public MDIView
|
class GuiExport GraphvizView : public MDIView
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GraphvizView(const QPixmap&, QWidget* parent=0);
|
GraphvizView(App::Document &_doc, QWidget* parent=0);
|
||||||
~GraphvizView();
|
~GraphvizView();
|
||||||
|
|
||||||
void setDependencyGraph(const std::string&);
|
|
||||||
QByteArray exportGraph(const QString& filter);
|
QByteArray exportGraph(const QString& filter);
|
||||||
|
|
||||||
/// Message handler
|
/// Message handler
|
||||||
|
@ -57,10 +65,29 @@ public:
|
||||||
virtual void printPreview();
|
virtual void printPreview();
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void svgFileRead(const QByteArray & data);
|
||||||
|
void error();
|
||||||
|
void done();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateSvgItem(const App::Document &doc);
|
||||||
|
void disconnectSignals();
|
||||||
|
|
||||||
|
const App::Document& doc;
|
||||||
std::string graphCode;
|
std::string graphCode;
|
||||||
QGraphicsScene* scene;
|
QGraphicsScene* scene;
|
||||||
QGraphicsView* view;
|
QGraphicsView* view;
|
||||||
|
GraphicsViewZoom* zoomer;
|
||||||
|
QGraphicsSvgItem* svgItem;
|
||||||
|
QSvgRenderer* renderer;
|
||||||
|
GraphvizWorker* thread;
|
||||||
|
int nPending;
|
||||||
|
|
||||||
|
typedef boost::BOOST_SIGNALS_NAMESPACE::scoped_connection Connection;
|
||||||
|
Connection recomputeConnection;
|
||||||
|
Connection undoConnection;
|
||||||
|
Connection redoConnection;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Gui
|
} // namespace Gui
|
||||||
|
|
|
@ -169,5 +169,8 @@
|
||||||
//#include <QWebSettings>
|
//#include <QWebSettings>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "qmath.h"
|
||||||
|
#include <QGraphicsView>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user