TechDraw: add Balloons

This commit is contained in:
Franck Jullien
2019-03-11 22:37:06 +01:00
committed by wmayer
parent 0305555d52
commit c5942d6a78
32 changed files with 1864 additions and 5 deletions

View File

@@ -39,6 +39,7 @@
#include "DrawViewMulti.h"
#include "DrawViewImage.h"
#include "DrawViewDetail.h"
#include "DrawViewBalloon.h"
namespace TechDraw {
extern PyObject* initModule();
@@ -78,6 +79,7 @@ PyMOD_INIT_FUNC(TechDraw)
TechDraw::DrawProjGroup ::init();
TechDraw::DrawProjGroupItem ::init();
TechDraw::DrawViewDetail ::init();
TechDraw::DrawViewBalloon ::init();
TechDraw::DrawTemplate ::init();

View File

@@ -74,6 +74,8 @@ SET(Draw_SRCS
DrawViewCollection.h
DrawViewDimension.cpp
DrawViewDimension.h
DrawViewBalloon.cpp
DrawViewBalloon.h
DrawViewSection.cpp
DrawViewSection.h
DrawHatch.cpp

View File

@@ -49,6 +49,7 @@
#include "DrawViewCollection.h"
#include "DrawViewPart.h"
#include "DrawViewDimension.h"
#include "DrawViewBalloon.h"
#include <Mod/TechDraw/App/DrawPagePy.h> // generated from DrawPagePy.xml
@@ -81,9 +82,9 @@ DrawPage::DrawPage(void)
ADD_PROPERTY_TYPE(KeepUpdated, (autoUpdate), group, (App::PropertyType)(App::Prop_None), "Keep page in sync with model");
ADD_PROPERTY_TYPE(Template, (0), group, (App::PropertyType)(App::Prop_None), "Attached Template");
Template.setScope(App::LinkScope::Global);
Template.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(Views, (0), group, (App::PropertyType)(App::Prop_None), "Attached Views");
Views.setScope(App::LinkScope::Global);
Views.setScope(App::LinkScope::Global);
// Projection Properties
ProjectionType.setEnums(ProjectionTypeEnums);
@@ -255,8 +256,9 @@ int DrawPage::addView(App::DocumentObject *docObj)
return -1;
DrawView* view = static_cast<DrawView*>(docObj);
//position all new views in center of Page (exceptDVDimension)
if (!docObj->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId())) {
//position all new views in center of Page (exceptDVDimension)
if (!docObj->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId()) &&
!docObj->isDerivedFrom(TechDraw::DrawViewBalloon::getClassTypeId())) {
view->X.setValue(getPageWidth()/2.0);
view->Y.setValue(getPageHeight()/2.0);
}

View File

@@ -0,0 +1,175 @@
/***************************************************************************
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
* *
* 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 <sstream>
# include <cstring>
# include <cstdlib>
# include <exception>
# include <QString>
# include <QStringList>
# include <QRegExp>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <gp_Pnt.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
#endif
#include <QLocale>
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Parameter.h>
#include <Base/Quantity.h>
#include <Base/Tools.h>
#include <Base/UnitsApi.h>
#include <Mod/Measure/App/Measurement.h>
#include "Geometry.h"
#include "DrawViewPart.h"
#include "DrawViewBalloon.h"
#include "DrawUtil.h"
#include "LineGroup.h"
//#include <Mod/TechDraw/App/DrawViewBalloonPy.h> // generated from DrawViewDimensionPy.xml
using namespace TechDraw;
//===========================================================================
// DrawViewDimension
//===========================================================================
PROPERTY_SOURCE(TechDraw::DrawViewBalloon, TechDraw::DrawView)
const char* DrawViewBalloon::endTypeEnums[]= {"Arrow",
"Dot",
NULL};
const char* DrawViewBalloon::balloonTypeEnums[]= {"Circular",
"None",
"Triangle",
"Inspection",
"Hexagon",
"Square",
"Rectangle",
NULL};
DrawViewBalloon::DrawViewBalloon(void)
{
ADD_PROPERTY_TYPE(Text , (""),"",App::Prop_None,"The text to be displayed");
ADD_PROPERTY_TYPE(sourceView,(0),"",(App::PropertyType)(App::Prop_None),"Source view for balloon");
ADD_PROPERTY_TYPE(OriginX,(0),"",(App::PropertyType)(App::Prop_None),"Balloon origin x");
ADD_PROPERTY_TYPE(OriginY,(0),"",(App::PropertyType)(App::Prop_None),"Balloon origin y");
ADD_PROPERTY_TYPE(OriginIsSet, (false), "",(App::PropertyType)(App::Prop_None),"Balloon origin is set");
EndType.setEnums(endTypeEnums);
ADD_PROPERTY(EndType,((long)0));
Symbol.setEnums(balloonTypeEnums);
ADD_PROPERTY(Symbol,((long)0));
ADD_PROPERTY_TYPE(SymbolScale,(1),"",(App::PropertyType)(App::Prop_None),"Balloon symbol scale");
ADD_PROPERTY_TYPE(TextWrapLen,(-1),"",(App::PropertyType)(App::Prop_None),"Balloon symbol scale");
OriginX.setStatus(App::Property::Hidden,false);
OriginY.setStatus(App::Property::Hidden,false);
OriginIsSet.setStatus(App::Property::Hidden,false);
OriginIsSet.setStatus(App::Property::ReadOnly,true);
sourceView.setScope(App::LinkScope::Global);
sourceView.setStatus(App::Property::Hidden,true);
Rotation.setStatus(App::Property::Hidden,true);
ScaleType.setStatus(App::Property::Hidden,true);
Scale.setStatus(App::Property::Hidden,true);
Caption.setStatus(App::Property::Hidden,true);
X.setStatus(App::Property::Hidden,true);
Y.setStatus(App::Property::Hidden,true);
}
DrawViewBalloon::~DrawViewBalloon()
{
}
void DrawViewBalloon::onChanged(const App::Property* prop)
{
DrawView::onChanged(prop);
}
void DrawViewBalloon::onDocumentRestored()
{
}
short DrawViewBalloon::mustExecute() const
{
bool result = 0;
if (!isRestoring()) {
result = Text.isTouched();
}
if (result) {
return result;
}
auto dvp = getViewPart();
if (dvp != nullptr) {
result = dvp->isTouched();
}
if (result) {
return result;
}
return DrawView::mustExecute();
}
DrawViewPart* DrawViewBalloon::getViewPart() const
{
App::DocumentObject* obj = sourceView.getValue();
DrawViewPart* result = dynamic_cast<DrawViewPart*>(obj);
return result;
}
App::DocumentObjectExecReturn *DrawViewBalloon::execute(void)
{
requestPaint();
return App::DocumentObject::execute();
}
/*
PyObject *DrawViewBalloon::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {
// ref counter is set to 1
PythonObject = Py::Object(new DrawViewBalloonPy(this),true);
}
return Py::new_reference_to(PythonObject);
}
*/

View File

@@ -0,0 +1,85 @@
/***************************************************************************
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
* *
* 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 _TechDraw_DrawViewBalloon_h_
#define _TechDraw_DrawViewBalloon_h_
#include <tuple>
# include <App/DocumentObject.h>
# include <App/FeaturePython.h>
# include <App/PropertyLinks.h>
#include "DrawView.h"
class TopoDS_Shape;
namespace Measure {
class Measurement;
}
namespace TechDraw {
class DrawViewPart;
class TechDrawExport DrawViewBalloon : public TechDraw::DrawView
{
PROPERTY_HEADER(TechDraw::DrawViewBalloon);
public:
/// Constructor
DrawViewBalloon();
virtual ~DrawViewBalloon();
App::PropertyLink sourceView;
App::PropertyString Text;
App::PropertyEnumeration EndType;
App::PropertyEnumeration Symbol;
App::PropertyFloat SymbolScale;
App::PropertyFloat OriginX;
App::PropertyFloat OriginY;
App::PropertyBool OriginIsSet;
App::PropertyFloat TextWrapLen;
short mustExecute() const;
DrawViewPart* getViewPart() const;
//virtual PyObject *getPyObject(void);
virtual App::DocumentObjectExecReturn *execute(void);
//@}
/// returns the type name of the ViewProvider
virtual const char* getViewProviderName(void) const {
return "TechDrawGui::ViewProviderBalloon";
}
protected:
void onChanged(const App::Property* prop);
virtual void onDocumentRestored();
private:
static const char* endTypeEnums[];
static const char* balloonTypeEnums[];
};
} //namespace TechDraw
#endif

View File

@@ -97,6 +97,7 @@
#include "DrawHatch.h"
#include "DrawGeomHatch.h"
#include "DrawViewDimension.h"
#include "DrawViewBalloon.h"
#include "DrawViewDetail.h"
#include "DrawPage.h"
#include "EdgeWalker.h"
@@ -559,6 +560,20 @@ std::vector<TechDraw::DrawViewDimension*> DrawViewPart::getDimensions() const
return result;
}
std::vector<TechDraw::DrawViewBalloon*> DrawViewPart::getBalloons() const
{
std::vector<TechDraw::DrawViewBalloon*> result;
std::vector<App::DocumentObject*> children = getInList();
std::sort(children.begin(),children.end(),std::less<App::DocumentObject*>());
std::vector<App::DocumentObject*>::iterator newEnd = std::unique(children.begin(),children.end());
for (std::vector<App::DocumentObject*>::iterator it = children.begin(); it != newEnd; ++it) {
if ((*it)->getTypeId().isDerivedFrom(DrawViewBalloon::getClassTypeId())) {
TechDraw::DrawViewBalloon* balloon = dynamic_cast<TechDraw::DrawViewBalloon*>(*it);
result.push_back(balloon);
}
}
return result;
}
const std::vector<TechDrawGeometry::Vertex *> & DrawViewPart::getVertexGeometry() const
{
@@ -837,6 +852,22 @@ void DrawViewPart::unsetupObject()
}
}
// Remove Balloons which reference this DVP
// must use page->removeObject first
page = findParentPage();
if (page != nullptr) {
std::vector<TechDraw::DrawViewBalloon*> balloons = getBalloons();
std::vector<TechDraw::DrawViewBalloon*>::iterator it3 = balloons.begin();
for (; it3 != balloons.end(); it3++) {
page->removeView(*it3);
const char* name = (*it3)->getNameInDocument();
if (name) {
Base::Interpreter().runStringArg("App.getDocument(\"%s\").removeObject(\"%s\")",
docName.c_str(), name);
}
}
}
}
//! is this an Isometric projection?

View File

@@ -67,6 +67,7 @@ class DrawViewDimension;
class DrawProjectSplit;
class DrawViewSection;
class DrawViewDetail;
class DrawViewBalloon;
}
namespace TechDraw
@@ -103,6 +104,7 @@ public:
std::vector<TechDraw::DrawHatch*> getHatches(void) const;
std::vector<TechDraw::DrawGeomHatch*> getGeomHatches(void) const;
std::vector<TechDraw::DrawViewDimension*> getDimensions() const;
std::vector<TechDraw::DrawViewBalloon*> getBalloons() const;
//TODO: are there use-cases for Python access to TechDrawGeometry???

View File

@@ -96,6 +96,7 @@ SET(TDTest_SRCS
TDTest/DVDimensionTest.py
TDTest/DVPartTest.py
TDTest/DVSectionTest.py
TDTest/DVBalloonTest.py
)
SET(TDTestFile_SRCS

View File

@@ -43,6 +43,7 @@
#include "ViewProviderPage.h"
#include "ViewProviderDrawingView.h"
#include "ViewProviderDimension.h"
#include "ViewProviderBalloon.h"
#include "ViewProviderProjGroup.h"
#include "ViewProviderProjGroupItem.h"
#include "ViewProviderTemplate.h"
@@ -113,6 +114,7 @@ PyMOD_INIT_FUNC(TechDrawGui)
TechDrawGui::ViewProviderTemplate::init();
TechDrawGui::ViewProviderDimension::init();
TechDrawGui::ViewProviderBalloon::init();
TechDrawGui::ViewProviderViewPart::init();
TechDrawGui::ViewProviderProjGroupItem::init();
TechDrawGui::ViewProviderProjGroup::init();

View File

@@ -30,6 +30,7 @@ set(TechDrawGui_MOC_HDRS
QGISVGTemplate.h
QGIDrawingTemplate.h
QGIViewDimension.h
QGIViewBalloon.h
TaskProjGroup.h
DlgPrefsTechDrawImp.h
DlgPrefsTechDraw2Imp.h
@@ -148,6 +149,8 @@ SET(TechDrawGuiView_SRCS
QGIViewCollection.h
QGIViewDimension.cpp
QGIViewDimension.h
QGIViewBalloon.cpp
QGIViewBalloon.h
QGIProjGroup.cpp
QGIProjGroup.h
QGIViewPart.cpp
@@ -193,6 +196,8 @@ SET(TechDrawGuiViewProvider_SRCS
ViewProviderTemplate.h
ViewProviderDimension.cpp
ViewProviderDimension.h
ViewProviderBalloon.cpp
ViewProviderBalloon.h
ViewProviderViewPart.cpp
ViewProviderViewPart.h
ViewProviderProjGroup.cpp

View File

@@ -61,6 +61,7 @@
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewClip.h>
#include <Mod/TechDraw/App/DrawViewAnnotation.h>
#include <Mod/TechDraw/App/DrawViewSymbol.h>
@@ -680,6 +681,109 @@ bool CmdTechDrawAnnotation::isActive(void)
return DrawGuiUtil::needPage(this);
}
//===========================================================================
// TechDraw_NewBalloon
//===========================================================================
//! common checks of Selection for Dimension commands
//non-empty selection, no more than maxObjs selected and at least 1 DrawingPage exists
bool _checkSelectionBalloon(Gui::Command* cmd, unsigned maxObjs) {
std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx();
if (selection.size() == 0) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("Select an object first"));
return false;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() > maxObjs){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("Too many objects selected"));
return false;
}
std::vector<App::DocumentObject*> pages = cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
if (pages.empty()){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Incorrect selection"),
QObject::tr("Create a page first."));
return false;
}
return true;
}
bool _checkDrawViewPartBalloon(Gui::Command* cmd) {
std::vector<Gui::SelectionObject> selection = cmd->getSelection().getSelectionEx();
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if( !objFeat ) {
QMessageBox::warning( Gui::getMainWindow(),
QObject::tr("Incorrect selection"),
QObject::tr("No View of a Part in selection.") );
return false;
}
return true;
}
DEF_STD_CMD_A(CmdTechDrawNewBalloon);
CmdTechDrawNewBalloon::CmdTechDrawNewBalloon()
: Command("TechDraw_NewBalloon")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Insert a new balloon");
sToolTipText = QT_TR_NOOP("Insert a new balloon");
sWhatsThis = "TechDraw_Balloon";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_Balloon";
}
void CmdTechDrawNewBalloon::activated(int iMsg)
{
Q_UNUSED(iMsg);
bool result = _checkSelectionBalloon(this,1);
if (!result)
return;
result = _checkDrawViewPartBalloon(this);
if (!result)
return;
std::string FeatName = getUniqueObjectName("Balloon");
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if( objFeat == nullptr ) {
return;
}
TechDraw::DrawPage* page = objFeat->findParentPage();
std::string PageName = page->getNameInDocument();
TechDraw::DrawViewBalloon *balloon = 0;
openCommand("Create Balloon");
doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')",FeatName.c_str());
doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str());
balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(getDocument()->getObject(FeatName.c_str()));
if (!balloon) {
throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
}
balloon->sourceView.setValue(objFeat);
commitCommand();
balloon->recomputeFeature();
//Horrible hack to force Tree update
double x = objFeat->X.getValue();
objFeat->X.setValue(x);
}
bool CmdTechDrawNewBalloon::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_Clip
@@ -1228,4 +1332,5 @@ void CreateTechDrawCommands(void)
rcCmdMgr.addCommand(new CmdTechDrawDraftView());
rcCmdMgr.addCommand(new CmdTechDrawArchView());
rcCmdMgr.addCommand(new CmdTechDrawSpreadsheet());
rcCmdMgr.addCommand(new CmdTechDrawNewBalloon());
}

View File

@@ -75,6 +75,7 @@
#include <Mod/TechDraw/App/DrawViewClip.h>
#include <Mod/TechDraw/App/DrawViewCollection.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawViewSection.h>
#include <Mod/TechDraw/App/DrawViewSpreadsheet.h>
@@ -86,6 +87,7 @@
#include "QGIView.h"
#include "QGIViewPart.h"
#include "QGIViewDimension.h"
#include "QGIViewBalloon.h"
#include "QGIViewClip.h"
#include "QGIVertex.h"
#include "QGIEdge.h"
@@ -161,6 +163,7 @@ MDIViewPage::MDIViewPage(ViewProviderPage *pageVp, Gui::Document* doc, QWidget*
//when restoring, it is possible for a Dimension to be loaded before the ViewPart it applies to
//therefore we need to make sure parentage of the graphics representation is set properly. bit of a kludge.
setDimensionGroups();
setBalloonGroups();
App::DocumentObject *obj = m_vpPage->getDrawPage()->Template.getValue();
auto pageTemplate( dynamic_cast<TechDraw::DrawTemplate *>(obj) );
@@ -205,6 +208,23 @@ void MDIViewPage::setDimensionGroups(void)
}
}
void MDIViewPage::setBalloonGroups(void)
{
const std::vector<QGIView *> &allItems = m_view->getViews();
std::vector<QGIView *>::const_iterator itInspect;
int balloonItemType = QGraphicsItem::UserType + 140;
for (itInspect = allItems.begin(); itInspect != allItems.end(); itInspect++) {
if (((*itInspect)->type() == balloonItemType) && (!(*itInspect)->group())) {
QGIView* parent = m_view->findParent((*itInspect));
if (parent) {
QGIViewBalloon* balloon = dynamic_cast<QGIViewBalloon*>((*itInspect));
m_view->addBalloonToParent(balloon,parent);
}
}
}
}
void MDIViewPage::setDocumentObject(const std::string& name)
{
m_objectName = name;
@@ -294,6 +314,9 @@ bool MDIViewPage::attachView(App::DocumentObject *obj)
} else if (typeId.isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId()) ) {
qview = m_view->addViewDimension( static_cast<TechDraw::DrawViewDimension *>(obj) );
} else if (typeId.isDerivedFrom(TechDraw::DrawViewBalloon::getClassTypeId()) ) {
qview = m_view->addViewBalloon( static_cast<TechDraw::DrawViewBalloon *>(obj) );
} else if (typeId.isDerivedFrom(TechDraw::DrawViewAnnotation::getClassTypeId()) ) {
qview = m_view->addDrawViewAnnotation( static_cast<TechDraw::DrawViewAnnotation *>(obj) );

View File

@@ -126,6 +126,7 @@ protected:
void closeEvent(QCloseEvent*);
QPrinter::PaperSize getPaperSize(int w, int h) const;
void setDimensionGroups(void);
void setBalloonGroups(void);
void showStatusMsg(const char* s1, const char* s2, const char* s3) const;
void onDeleteObject(const App::DocumentObject& obj);

View File

@@ -9,6 +9,7 @@ QGraphicsItemEdge: 103
QGraphicsItemFace: 104
QGraphicsItemVertex: 105
QGraphicsItemViewDimension : 106
QGraphicsItemViewBalloon : 140
QGraphicsItemDatumLabel : 107
QGraphicsItemViewSection : 108
QGraphicsItemArrow: 109

View File

@@ -110,6 +110,10 @@ QGIView::QGIView()
isVisible(true);
}
QGIView::~QGIView()
{
signalSelectPoint.disconnect_all_slots();
}
void QGIView::alignTo(QGraphicsItem*item, const QString &alignment)
{
@@ -179,6 +183,8 @@ QVariant QGIView::itemChange(GraphicsItemChange change, const QVariant &value)
void QGIView::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
signalSelectPoint(this, event->pos());
if(m_locked) {
event->ignore();
} else {

View File

@@ -52,7 +52,7 @@ class TechDrawGuiExport QGIView : public QGraphicsItemGroup
{
public:
QGIView();
virtual ~QGIView() = default;
virtual ~QGIView();
enum {Type = QGraphicsItem::UserType + 101};
int type() const override { return Type;}
@@ -102,6 +102,7 @@ public:
MDIViewPage* getMDIViewPage(void) const;
// Mouse handling
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
boost::signals2::signal<void (QGIView*, QPointF)> signalSelectPoint;
protected:
QGIView* getQGIVByName(std::string name);

View File

@@ -0,0 +1,571 @@
/***************************************************************************
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
* Copyright (c) 2019 Franck Jullien <franck.jullien@gmail.com> *
* *
* 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 <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
# include <TopoDS_Shape.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Curve.hxx>
# include <Precision.hxx>
# include <QGraphicsScene>
# include <QGraphicsSceneMouseEvent>
# include <QPainter>
# include <QPaintDevice>
# include <QSvgGenerator>
# include <math.h>
#endif
#include <App/Application.h>
#include <App/Material.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Parameter.h>
#include <Base/UnitsApi.h>
#include <Gui/Command.h>
#include <string>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/Geometry.h>
#include "Rez.h"
#include "ZVALUE.h"
#include "QGIArrow.h"
#include "QGIDimLines.h"
#include "QGIViewBalloon.h"
#include "ViewProviderBalloon.h"
#include "DrawGuiUtil.h"
#include "QGIViewPart.h"
#include "QGIViewDimension.h"
#include "QGVPage.h"
#include "MDIViewPage.h"
#define PI 3.14159
//TODO: hide the Qt coord system (+y down).
using namespace TechDraw;
using namespace TechDrawGui;
//**************************************************************
QGIViewBalloon::QGIViewBalloon() :
hasHover(false),
m_lineWidth(0.0)
{
setHandlesChildEvents(false);
setFlag(QGraphicsItem::ItemIsMovable, false);
setCacheMode(QGraphicsItem::NoCache);
balloonLabel = new QGIDatumLabel();
addToGroup(balloonLabel);
balloonLabel->setColor(getNormalColor());
balloonLabel->setPrettyNormal();
balloonLines = new QGIDimLines();
addToGroup(balloonLines);
balloonShape = new QGIDimLines();
addToGroup(balloonShape);
arrow = new QGIArrow();
addToGroup(arrow);
balloonLabel->setZValue(ZVALUE::LABEL);
arrow->setZValue(ZVALUE::DIMENSION);
balloonLines->setZValue(ZVALUE::DIMENSION);
balloonLines->setStyle(Qt::SolidLine);
balloonShape->setZValue(ZVALUE::DIMENSION);
balloonShape->setStyle(Qt::SolidLine);
oldLabelCenter = new QPointF;
oldLabelCenter->setX(0.0);
oldLabelCenter->setY(0.0);
balloonLabel->setPosFromCenter(0, 0);
// connecting the needed slots and signals
QObject::connect(
balloonLabel, SIGNAL(dragging(bool)),
this , SLOT (balloonLabelDragged(bool)));
QObject::connect(
balloonLabel, SIGNAL(dragFinished()),
this , SLOT (balloonLabelDragFinished()));
QObject::connect(
balloonLabel, SIGNAL(selected(bool)),
this , SLOT (select(bool)));
QObject::connect(
balloonLabel, SIGNAL(hover(bool)),
this , SLOT (hover(bool)));
toggleBorder(false);
setZValue(ZVALUE::DIMENSION); //note: this won't paint dimensions over another View if it stacks
//above this Dimension's parent view. need Layers?
}
void QGIViewBalloon::disconnect(void)
{
auto bnd = boost::bind(&QGIViewBalloon::parentViewMousePressed, this, _1, _2);
if (m_parent) {
m_parent->signalSelectPoint.disconnect(bnd);
}
}
void QGIViewBalloon::connect(QGIView *parent)
{
auto bnd = boost::bind(&QGIViewBalloon::parentViewMousePressed, this, _1, _2);
parent->signalSelectPoint.connect(bnd);
m_parent = parent;
}
void QGIViewBalloon::parentViewMousePressed(QGIView *view, QPointF pos)
{
Q_UNUSED(view);
//Base::Console().Message("%s::parentViewMousePressed from %s\n", this->getViewName(), view->getViewName());
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if ( vp == nullptr ) {
return;
}
auto balloon( dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject()) );
if( balloon == nullptr )
return;
auto bnd = boost::bind(&QGIViewBalloon::parentViewMousePressed, this, _1, _2);
if (balloon->OriginIsSet.getValue() == false) {
balloon->OriginX.setValue(pos.x());
balloon->OriginY.setValue(pos.y());
balloon->OriginIsSet.setValue(true);
m_parent->signalSelectPoint.disconnect(bnd);
MDIViewPage* mdi = getMDIViewPage();
QGVPage* page;
if (mdi != nullptr) {
page = mdi->getQGVPage();
}
QString labelText = QString::fromUtf8(std::to_string(page->balloonIndex).c_str());
balloon->Text.setValue(std::to_string(page->balloonIndex++).c_str());
QFont font = balloonLabel->getFont();
font.setPointSizeF(Rez::guiX(vp->Fontsize.getValue()));
font.setFamily(QString::fromUtf8(vp->Font.getValue()));
balloonLabel->setFont(font);
prepareGeometryChange();
// Default label position
balloonLabel->setPosFromCenter(pos.x() + 200, pos.y() -200);
balloonLabel->setDimString(labelText, Rez::guiX(balloon->TextWrapLen.getValue()));
}
draw();
}
void QGIViewBalloon::setViewPartFeature(TechDraw::DrawViewBalloon *balloon)
{
if(balloon == 0)
return;
setViewFeature(static_cast<TechDraw::DrawView *>(balloon));
float x = Rez::guiX(balloon->X.getValue());
float y = Rez::guiX(-balloon->Y.getValue());
balloonLabel->setColor(getNormalColor());
balloonLabel->setPosFromCenter(x, y);
QString labelText = QString::fromUtf8(balloon->Text.getStrValue().data());
balloonLabel->setDimString(labelText, Rez::guiX(balloon->TextWrapLen.getValue()));
updateBalloon();
draw();
}
void QGIViewBalloon::select(bool state)
{
setSelected(state);
draw();
}
void QGIViewBalloon::hover(bool state)
{
hasHover = state;
draw();
}
void QGIViewBalloon::updateView(bool update)
{
Q_UNUSED(update);
auto balloon( dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject()) );
if( balloon == nullptr )
return;
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if ( vp == nullptr ) {
return;
}
if (update) {
QString labelText = QString::fromUtf8(balloon->Text.getStrValue().data());
balloonLabel->setDimString(labelText, Rez::guiX(balloon->TextWrapLen.getValue()));
balloonLabel->setColor(getNormalColor());
}
updateBalloon();
draw();
}
void QGIViewBalloon::updateBalloon(bool obtuse)
{
(void) obtuse;
const auto balloon( dynamic_cast<TechDraw::DrawViewBalloon *>(getViewObject()) );
if( balloon == nullptr ) {
return;
}
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if ( vp == nullptr ) {
return;
}
if (balloon->OriginIsSet.getValue() == false)
return;
QFont font = balloonLabel->getFont();
font.setPointSizeF(Rez::guiX(vp->Fontsize.getValue()));
font.setFamily(QString::fromUtf8(vp->Font.getValue()));
balloonLabel->setFont(font);
}
void QGIViewBalloon::balloonLabelDragged(bool ctrl)
{
draw_modifier(ctrl);
}
void QGIViewBalloon::balloonLabelDragFinished()
{
auto dim( dynamic_cast<TechDraw::DrawViewBalloon *>(getViewObject()) );
if( dim == nullptr ) {
return;
}
double x = Rez::appX(balloonLabel->X()),
y = Rez::appX(balloonLabel->Y());
Gui::Command::openCommand("Drag Balloon");
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.X = %f", dim->getNameInDocument(), x);
Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Y = %f", dim->getNameInDocument(), -y);
Gui::Command::commitCommand();
}
void QGIViewBalloon::draw()
{
draw_modifier(false);
}
void QGIViewBalloon::draw_modifier(bool modifier)
{
if (!isVisible()) { //should this be controlled by parent ViewPart?
return;
}
TechDraw::DrawViewBalloon *balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(getViewObject());
if((!balloon) || //nothing to draw, don't try
(!balloon->isDerivedFrom(TechDraw::DrawViewBalloon::getClassTypeId()))) {
balloonLabel->hide();
hide();
return;
}
if (balloon->OriginIsSet.getValue() == false) {
return;
}
balloonLabel->show();
show();
const TechDraw::DrawViewPart *refObj = balloon->getViewPart();
if(!refObj->hasGeometry()) { //nothing to draw yet (restoring)
balloonLabel->hide();
hide();
return;
}
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if ( vp == nullptr ) {
return;
}
m_colNormal = getNormalColor();
balloonLabel->setColor(m_colNormal);
m_lineWidth = Rez::guiX(vp->LineWidth.getValue());
double textWidth = balloonLabel->getDimText()->boundingRect().width();
double textHeight = balloonLabel->getDimText()->boundingRect().height();
QRectF mappedRect = mapRectFromItem(balloonLabel, balloonLabel->boundingRect());
Base::Vector3d lblCenter = Base::Vector3d(mappedRect.center().x(), mappedRect.center().y(), 0.0);
if (balloon->isLocked()) {
lblCenter.x = (oldLabelCenter->x());
lblCenter.y = (oldLabelCenter->y());
balloonLabel->setFlag(QGraphicsItem::ItemIsMovable, false);
} else
balloonLabel->setFlag(QGraphicsItem::ItemIsMovable, true);
Base::Vector3d dLineStart;
Base::Vector3d kinkPoint;
double kinkLength = Rez::guiX(5.0);
float orginX = balloon->OriginX.getValue();
float orginY = balloon->OriginY.getValue();
const char *balloonType = balloon->Symbol.getValueAsString();
float scale = balloon->SymbolScale.getValue();
double offset;
QPainterPath balloonPath;
if (strcmp(balloonType, "Circular") == 0) {
double balloonRadius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2));
balloonRadius = balloonRadius * scale;
balloonPath.moveTo(lblCenter.x, lblCenter.y);
balloonPath.addEllipse(lblCenter.x - balloonRadius,lblCenter.y - balloonRadius, balloonRadius * 2, balloonRadius * 2);
offset = balloonRadius;
} else if (strcmp(balloonType, "None") == 0) {
balloonPath = QPainterPath();
offset = (textWidth / 2.0) + Rez::guiX(2.0);
} else if (strcmp(balloonType, "Rectangle") == 0) {
//Add some room
textWidth = (textWidth * scale) + Rez::guiX(2.0);
textHeight = (textHeight * scale) + Rez::guiX(1.0);
balloonPath.addRect(lblCenter.x -(textWidth / 2.0), lblCenter.y - (textHeight / 2.0), textWidth, textHeight);
offset = (textWidth / 2.0);
} else if (strcmp(balloonType, "Triangle") == 0) {
double radius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2));
radius = radius * scale;
radius += Rez::guiX(3.0);
offset = (tan(30 * PI / 180) * radius);
QPolygonF triangle;
double startAngle = -PI / 2;
double angle = startAngle;
for (int i = 0; i < 4; i++) {
triangle += QPointF(lblCenter.x + (radius * cos(angle)), lblCenter.y + (radius * sin(angle)));
angle += (2 * PI / 3);
}
balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle)));
balloonPath.addPolygon(triangle);
} else if (strcmp(balloonType, "Inspection") == 0) {
//Add some room
textWidth = (textWidth * scale) + Rez::guiX(2.0);
textHeight = (textHeight * scale) + Rez::guiX(1.0);
QPointF textBoxCorner(lblCenter.x - (textWidth / 2.0), lblCenter.y - (textHeight / 2.0));
balloonPath.moveTo(textBoxCorner);
balloonPath.lineTo(textBoxCorner.x() + textWidth, textBoxCorner.y());
balloonPath.arcTo(textBoxCorner.x() + textWidth - (textHeight / 2.0), textBoxCorner.y(), textHeight, textHeight, 90, -180);
balloonPath.lineTo(textBoxCorner.x(), textBoxCorner.y() + textHeight);
balloonPath.arcTo(textBoxCorner.x() - (textHeight / 2), textBoxCorner.y(), textHeight, textHeight, -90, -180);
offset = (textWidth / 2.0) + (textHeight / 2.0);
} else if (strcmp(balloonType, "Square") == 0) {
//Add some room
textWidth = (textWidth * scale) + Rez::guiX(2.0);
textHeight = (textHeight * scale) + Rez::guiX(1.0);
double max = std::max(textWidth, textHeight);
balloonPath.addRect(lblCenter.x -(max / 2.0), lblCenter.y - (max / 2.0), max, max);
offset = (max / 2.0);
} else if (strcmp(balloonType, "Hexagon") == 0) {
double radius = sqrt(pow((textHeight / 2.0), 2) + pow((textWidth / 2.0), 2));
radius = radius * scale;
radius += Rez::guiX(1.0);
offset = radius;
QPolygonF triangle;
double startAngle = -2 * PI / 3;
double angle = startAngle;
for (int i = 0; i < 7; i++) {
triangle += QPointF(lblCenter.x + (radius * cos(angle)), lblCenter.y + (radius * sin(angle)));
angle += (2 * PI / 6);
}
balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle)));
balloonPath.addPolygon(triangle);
}
offset = (lblCenter.x < orginX) ? offset : -offset;
dLineStart.y = lblCenter.y;
dLineStart.x = lblCenter.x + offset;
kinkLength = (lblCenter.x < orginX) ? kinkLength : -kinkLength;
kinkPoint.y = dLineStart.y;
kinkPoint.x = dLineStart.x + kinkLength;
QPainterPath dLinePath;
dLinePath.moveTo(dLineStart.x, dLineStart.y);
dLinePath.lineTo(kinkPoint.x, kinkPoint.y);
if (modifier) {
balloon->OriginX.setValue(orginX + lblCenter.x - oldLabelCenter->x());
balloon->OriginY.setValue(orginY + lblCenter.y - oldLabelCenter->y());
}
orginX = balloon->OriginX.getValue();
orginY = balloon->OriginY.getValue();
dLinePath.lineTo(orginX, orginY);
oldLabelCenter->setX(lblCenter.x);
oldLabelCenter->setY(lblCenter.y);
balloonLines->setPath(dLinePath);
balloonShape->setPath(balloonPath);
const char *endType = balloon->EndType.getValueAsString();
if (strcmp(endType, "Arrow") == 0) {
arrow->setStyle(QGIArrow::getPrefArrowStyle());
} else if (strcmp(endType, "Dot") == 0) {
arrow->setStyle(3);
}
arrow->setSize(QGIArrow::getPrefArrowSize());
arrow->draw();
Base::Vector3d orign(orginX, orginY, 0.0);
Base::Vector3d dirballoonLinesLine = (orign - kinkPoint).Normalize();
float arAngle = atan2(dirballoonLinesLine.y, dirballoonLinesLine.x) * 180 / M_PI;
arrow->setPos(orginX, orginY);
arrow->setRotation(arAngle);
arrow->show();
// redraw the Dimension and the parent View
if (hasHover && !isSelected()) {
arrow->setPrettyPre();
balloonLines->setPrettyPre();
balloonShape->setPrettyPre();
} else if (isSelected()) {
arrow->setPrettySel();
balloonLines->setPrettySel();
balloonShape->setPrettySel();
} else {
arrow->setPrettyNormal();
balloonLines->setPrettyNormal();
balloonShape->setPrettyNormal();
}
update();
if (parentItem()) {
//TODO: parent redraw still required with new frame/label??
parentItem()->update();
} else {
Base::Console().Log("INFO - QGIVD::draw - no parent to update\n");
}
}
void QGIViewBalloon::drawBorder(void)
{
//Dimensions have no border!
// Base::Console().Message("TRACE - QGIViewDimension::drawBorder - doing nothing!\n");
}
QVariant QGIViewBalloon::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == ItemSelectedHasChanged && scene()) {
if(isSelected()) {
balloonLabel->setSelected(true);
} else {
balloonLabel->setSelected(false);
}
draw();
}
return QGIView::itemChange(change, value);
}
void QGIViewBalloon::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) {
QStyleOptionGraphicsItem myOption(*option);
myOption.state &= ~QStyle::State_Selected;
QPaintDevice* hw = painter->device();
QSvgGenerator* svg = dynamic_cast<QSvgGenerator*>(hw);
setPens();
//double balloonLinesSaveWidth = arrow->getWidth();
if (svg) {
setSvgPens();
} else {
setPens();
}
QGIView::paint (painter, &myOption, widget);
setPens();
}
void QGIViewBalloon::setSvgPens(void)
{
double svgLineFactor = 3.0; //magic number. should be a setting somewhere.
balloonLines->setWidth(m_lineWidth/svgLineFactor);
balloonShape->setWidth(m_lineWidth/svgLineFactor);
arrow->setWidth(arrow->getWidth()/svgLineFactor);
}
void QGIViewBalloon::setPens(void)
{
balloonLines->setWidth(m_lineWidth);
balloonShape->setWidth(m_lineWidth);
arrow->setWidth(m_lineWidth);
}
QColor QGIViewBalloon::getNormalColor()
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions");
App::Color fcColor;
fcColor.setPackedValue(hGrp->GetUnsigned("Color", 0x00000000));
m_colNormal = fcColor.asValue<QColor>();
auto balloon( dynamic_cast<TechDraw::DrawViewBalloon*>(getViewObject()) );
if( balloon == nullptr )
return m_colNormal;
auto vp = static_cast<ViewProviderBalloon*>(getViewProvider(getViewObject()));
if ( vp == nullptr ) {
return m_colNormal;
}
m_colNormal = vp->Color.getValue().asValue<QColor>();
return m_colNormal;
}
#include <Mod/TechDraw/Gui/moc_QGIViewBalloon.cpp>

View File

@@ -0,0 +1,112 @@
/***************************************************************************
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
* Copyright (c) 2019 Franck Jullien <franck.jullien@gmail.com> *
* *
* 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 DRAWINGGUI_QGRAPHICSITEMVIEWBALLOON_H
#define DRAWINGGUI_QGRAPHICSITEMVIEWBALLOON_H
#include <QObject>
#include <QGraphicsView>
#include <QStyleOptionGraphicsItem>
#include <QGraphicsItem>
#include <QGraphicsObject>
#include <QColor>
#include <QFont>
#include <Base/Vector3D.h>
#include "QGIView.h"
#include "QGIViewPart.h"
#include "QGCustomText.h"
#include "QGIViewDimension.h"
namespace TechDraw {
class DrawViewBalloon;
}
namespace TechDrawGeometry {
class BaseGeom;
class AOC;
}
namespace TechDrawGui
{
class QGIArrow;
class QGIDimLines;
class QGIViewBalloon;
//*******************************************************************
class TechDrawGuiExport QGIViewBalloon : public QObject, public QGIView
{
Q_OBJECT
public:
enum {Type = QGraphicsItem::UserType + 140};
explicit QGIViewBalloon();
virtual ~QGIViewBalloon() = default;
void setViewPartFeature(TechDraw::DrawViewBalloon *obj);
int type() const override { return Type;}
virtual void drawBorder() override;
virtual void updateView(bool update = false) override;
virtual void paint( QPainter * painter,
const QStyleOptionGraphicsItem * option,
QWidget * widget = 0 ) override;
virtual QColor getNormalColor(void) override;
QString getLabelText(void);
void connect(QGIView *parent);
void disconnect(void);
void draw_modifier(bool modifier);
public Q_SLOTS:
void balloonLabelDragged(bool ctrl);
void balloonLabelDragFinished(void);
void select(bool state);
void hover(bool state);
void updateBalloon(bool obtuse = false);
protected:
void draw() override;
virtual QVariant itemChange( GraphicsItemChange change,
const QVariant &value ) override;
virtual void setSvgPens(void);
virtual void setPens(void);
QString getPrecision(void);
protected:
bool hasHover;
QGIDatumLabel* balloonLabel;
QGIDimLines* balloonLines;
QGIDimLines* balloonShape;
QGIArrow* arrow;
double m_lineWidth;
bool m_obtuse;
void parentViewMousePressed(QGIView *view, QPointF pos);
QPointF *oldLabelCenter;
QGIView *m_parent;
};
} // namespace MDIViewPageGui
#endif // DRAWINGGUI_QGRAPHICSITEMVIEWBALLOON_H

View File

@@ -210,6 +210,13 @@ void QGIDatumLabel::setDimString(QString t)
m_dimText->setPlainText(t);
}
void QGIDatumLabel::setDimString(QString t, qreal maxWidth)
{
prepareGeometryChange();
m_dimText->setPlainText(t);
m_dimText->setTextWidth(maxWidth);
}
void QGIDatumLabel::setTolString()
{
prepareGeometryChange();

View File

@@ -73,6 +73,7 @@ public:
void setFont(QFont f);
QFont getFont(void) { return m_dimText->font(); }
void setDimString(QString t);
void setDimString(QString t, qreal maxWidth);
void setTolString();
void setPrettySel(void);
void setPrettyPre(void);

View File

@@ -58,6 +58,7 @@
#include <Mod/TechDraw/App/DrawSVGTemplate.h>
#include <Mod/TechDraw/App/DrawParametricTemplate.h>
#include <Mod/TechDraw/App/DrawViewCollection.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawProjGroup.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
@@ -75,6 +76,7 @@
#include "TemplateTextField.h"
#include "QGIViewCollection.h"
#include "QGIViewDimension.h"
#include "QGIViewBalloon.h"
#include "QGIProjGroup.h"
#include "QGIViewPart.h"
#include "QGIViewSection.h"
@@ -134,6 +136,8 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGraphicsScene* s, QWidget *parent)
bkgBrush = new QBrush(getBackgroundColor());
balloonIndex = 1;
resetCachedContent();
}
@@ -255,7 +259,13 @@ int QGVPage::removeQViewByName(const char* name)
break;
}
}
if (found) {
int balloonItemType = QGraphicsItem::UserType + 140;
if (ourItem->type() == balloonItemType) {
QGIViewBalloon* balloon = dynamic_cast<QGIViewBalloon*>(ourItem);
balloon->disconnect();
}
removeQViewFromScene(ourItem);
delete ourItem;
}
@@ -383,6 +393,39 @@ QGIView * QGVPage::addDrawViewImage(TechDraw::DrawViewImage *view)
return qview;
}
QGIView * QGVPage::addViewBalloon(TechDraw::DrawViewBalloon *balloon)
{
auto balloonGroup( new QGIViewBalloon );
auto ourScene( scene() );
assert(ourScene);
ourScene->addItem(balloonGroup);
balloonGroup->setViewPartFeature(balloon);
// Find if it belongs to a parent
QGIView *parent = 0;
parent = findParent(balloonGroup);
if(parent) {
balloonGroup->connect(parent);
addBalloonToParent(balloonGroup,parent);
}
return balloonGroup;
}
void QGVPage::addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent)
{
assert(balloon);
assert(parent); //blow up if we don't have Dimension or Parent
QPointF posRef(0.,0.);
QPointF mapPos = balloon->mapToItem(parent, posRef);
balloon->moveBy(-mapPos.x(), -mapPos.y());
parent->addToGroup(balloon);
balloon->setZValue(ZVALUE::DIMENSION);
}
QGIView * QGVPage::addViewDimension(TechDraw::DrawViewDimension *dim)
{
auto dimGroup( new QGIViewDimension );
@@ -469,6 +512,23 @@ QGIView * QGVPage::findParent(QGIView *view) const
}
}
//If type is balloon we check references first
TechDraw::DrawViewBalloon *balloon = 0;
balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(myView);
if(balloon) {
App::DocumentObject* obj = balloon->sourceView.getValue();
if(obj) {
// Attach the dimension to the first object's group
for(std::vector<QGIView *>::const_iterator it = qviews.begin(); it != qviews.end(); ++it) {
if(strcmp((*it)->getViewName(), obj->getNameInDocument()) == 0) {
return *it;
}
}
}
}
// Check if part of view collection
for(std::vector<QGIView *>::const_iterator it = qviews.begin(); it != qviews.end(); ++it) {
QGIViewCollection *grp = 0;

View File

@@ -41,6 +41,7 @@ class DrawViewClip;
class DrawViewCollection;
class DrawViewSpreadsheet;
class DrawViewImage;
class DrawViewBalloon;
}
namespace TechDrawGui
@@ -49,6 +50,7 @@ class QGIView;
class QGIViewDimension;
class QGITemplate;
class ViewProviderPage;
class QGIViewBalloon;
class TechDrawGuiExport QGVPage : public QGraphicsView
{
@@ -64,6 +66,7 @@ public:
void drawBackground(QPainter *p, const QRectF &rect) override;
QGIView * addViewDimension(TechDraw::DrawViewDimension *dim);
QGIView * addViewBalloon(TechDraw::DrawViewBalloon *balloon);
QGIView * addProjectionGroup(TechDraw::DrawProjGroup *view);
QGIView * addViewPart(TechDraw::DrawViewPart *part);
QGIView * addViewSection(TechDraw::DrawViewPart *part);
@@ -80,6 +83,7 @@ public:
QGIView* getQGIVByName(std::string name);
QGIView* findParent(QGIView *) const;
void addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent);
void addDimToParent(QGIViewDimension* dim, QGIView* parent);
// const std::vector<QGIView *> & getViews() const { return views; } //only used in MDIVP
std::vector<QGIView *> getViews() const; //only used in MDIVP
@@ -104,6 +108,8 @@ public:
void saveSvg(QString filename);
void postProcessXml(QTemporaryFile* tempFile, QString filename, QString pagename);
int balloonIndex;
public Q_SLOTS:
void setHighQualityAntialiasing(bool highQualityAntialiasing);

View File

@@ -30,6 +30,7 @@
<file>icons/TechDraw_Dimension_Horizontal.svg</file>
<file>icons/TechDraw_Dimension_Length.svg</file>
<file>icons/TechDraw_Dimension_Radius.svg</file>
<file>icons/TechDraw_Balloon.svg</file>
<file>icons/TechDraw_Dimension_Vertical.svg</file>
<file>icons/TechDraw_Dimension_Link.svg</file>
<file>icons/preferences-techdraw.svg</file>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -0,0 +1,128 @@
/***************************************************************************
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
* Copyright (c) 2012 Luke Parry <l.parry@warwick.ac.uk> *
* Copyright (c) 2019 Franck Jullien <franck.jullien@gmail.com> *
* *
* 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_
#endif
/// Here the FreeCAD includes sorted by Base,App,Gui......
#include <Base/Console.h>
#include <Base/Parameter.h>
#include <Base/Exception.h>
#include <Base/Sequencer.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include "ViewProviderBalloon.h"
using namespace TechDrawGui;
PROPERTY_SOURCE(TechDrawGui::ViewProviderBalloon, TechDrawGui::ViewProviderDrawingView)
//**************************************************************************
// Construction/Destruction
ViewProviderBalloon::ViewProviderBalloon()
{
sPixmap = "TechDraw_Balloon";
static const char *group = "Balloon Format";
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Labels");
std::string fontName = hGrp->GetASCII("LabelFont", "osifont");
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions");
double fontSize = hGrp->GetFloat("FontSize", 3.5);
ADD_PROPERTY_TYPE(Font ,(fontName.c_str()),group,App::Prop_None, "The name of the font to use");
ADD_PROPERTY_TYPE(Fontsize,(fontSize) ,group,(App::PropertyType)(App::Prop_None),"Dimension text size in units");
hGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Decorations");
std::string lgName = hGrp->GetASCII("LineGroup","FC 0.70mm");
auto lg = TechDraw::LineGroup::lineGroupFactory(lgName);
double weight = lg->getWeight("Thin");
delete lg; //Coverity CID 174670
ADD_PROPERTY_TYPE(LineWidth,(weight) ,group,(App::PropertyType)(App::Prop_None),"Dimension line weight");
hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions");
App::Color fcColor;
fcColor.setPackedValue(hGrp->GetUnsigned("Color", 0x00000000));
ADD_PROPERTY_TYPE(Color,(fcColor),group,App::Prop_None,"The color of the Dimension");
}
ViewProviderBalloon::~ViewProviderBalloon()
{
}
void ViewProviderBalloon::attach(App::DocumentObject *pcFeat)
{
// call parent attach method
ViewProviderDrawingView::attach(pcFeat);
}
void ViewProviderBalloon::setDisplayMode(const char* ModeName)
{
ViewProviderDrawingView::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderBalloon::getDisplayModes(void) const
{
// get the modes of the father
std::vector<std::string> StrList = ViewProviderDrawingView::getDisplayModes();
return StrList;
}
void ViewProviderBalloon::updateData(const App::Property* p)
{
ViewProviderDrawingView::updateData(p);
}
void ViewProviderBalloon::onChanged(const App::Property* p)
{
if ((p == &Font) ||
(p == &Fontsize) ||
(p == &LineWidth)) {
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);
}
}
Gui::ViewProviderDocumentObject::onChanged(p);
}
TechDraw::DrawViewBalloon* ViewProviderBalloon::getViewObject() const
{
return dynamic_cast<TechDraw::DrawViewBalloon*>(pcObject);
}

View File

@@ -0,0 +1,68 @@
/***************************************************************************
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
* Copyright (c) 2012 Luke Parry <l.parry@warwick.ac.uk> *
* Copyright (c) 2019 Franck Jullien <franck.jullien@gmail.com> *
* *
* 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 DRAWINGGUI_VIEWPROVIDERBALLOON_H
#define DRAWINGGUI_VIEWPROVIDERBALLOON_H
#include <App/PropertyUnits.h>
#include "ViewProviderDrawingView.h"
#include <Mod/TechDraw/App/DrawViewBalloon.h>
namespace TechDrawGui {
class TechDrawGuiExport ViewProviderBalloon : public ViewProviderDrawingView
{
PROPERTY_HEADER(TechDrawGui::ViewProviderBalloon);
public:
/// constructor
ViewProviderBalloon();
/// destructor
virtual ~ViewProviderBalloon();
App::PropertyFont Font;
App::PropertyLength Fontsize;
App::PropertyFloat LineWidth;
App::PropertyColor Color;
virtual void attach(App::DocumentObject *);
virtual void setDisplayMode(const char* ModeName);
virtual bool useNewSelectionModel(void) const {return false;}
/// returns a list of all possible modes
virtual std::vector<std::string> getDisplayModes(void) const;
virtual void updateData(const App::Property*);
virtual void onChanged(const App::Property* p);
virtual TechDraw::DrawViewBalloon* getViewObject() const;
};
} // namespace TechDrawGui
#endif // DRAWINGGUI_VIEWPROVIDERBALLOON_H

View File

@@ -56,6 +56,7 @@
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawUtil.h>
@@ -259,6 +260,7 @@ std::vector<App::DocumentObject*> ViewProviderPage::claimChildren(void) const
// Collect any child views
// for Page, valid children are any View except: DrawProjGroupItem
// DrawViewDimension
// DrawViewBalloon
// any FeatuerView in a DrawViewClip
// DrawHatch
@@ -272,6 +274,7 @@ std::vector<App::DocumentObject*> ViewProviderPage::claimChildren(void) const
if(docObj->isDerivedFrom(TechDraw::DrawProjGroupItem::getClassTypeId()) ||
docObj->isDerivedFrom(TechDraw::DrawViewDimension::getClassTypeId()) ||
docObj->isDerivedFrom(TechDraw::DrawHatch::getClassTypeId()) ||
docObj->isDerivedFrom(TechDraw::DrawViewBalloon::getClassTypeId()) ||
(featView && featView->isInClip()) )
continue;
else

View File

@@ -37,6 +37,7 @@
#include <App/DocumentObject.h>
#include <Mod/TechDraw/App/DrawViewDimension.h>
#include <Mod/TechDraw/App/DrawViewBalloon.h>
#include <Mod/TechDraw/App/DrawViewMulti.h>
#include <Mod/TechDraw/App/DrawHatch.h>
#include <Mod/TechDraw/App/DrawGeomHatch.h>
@@ -178,6 +179,8 @@ std::vector<App::DocumentObject*> ViewProviderViewPart::claimChildren(void) cons
temp.push_back((*it));
} else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawGeomHatch::getClassTypeId())) {
temp.push_back((*it));
} else if ((*it)->getTypeId().isDerivedFrom(TechDraw::DrawViewBalloon::getClassTypeId())) {
temp.push_back((*it));
}
}
return temp;

View File

@@ -78,6 +78,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
*draw << "TechDraw_NewAngleDimension";
*draw << "TechDraw_NewAngle3PtDimension";
*draw << "TechDraw_LinkDimension";
*draw << "TechDraw_NewBalloon";
*draw << "Separator";
*draw << "TechDraw_ExportPage";
*draw << "TechDraw_ExportPageDxf";
@@ -128,6 +129,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
*dims << "TechDraw_NewAngleDimension";
*dims << "TechDraw_NewAngle3PtDimension";
*dims << "TechDraw_LinkDimension";
*dims << "TechDraw_NewBalloon";
// *dims << "TechDraw_NewDimension"
Gui::ToolBarItem *file = new Gui::ToolBarItem(root);
@@ -181,6 +183,7 @@ Gui::ToolBarItem* Workbench::setupCommandBars() const
*dims << "TechDraw_NewAngleDimension";
*dims << "TechDraw_NewAngle3PtDimension";
*dims << "TechDraw_LinkDimension";
*dims << "TechDraw_NewBalloon";
// *dims << "TechDraw_NewDimension";
Gui::ToolBarItem *file = new Gui::ToolBarItem(root);

View File

@@ -13,6 +13,7 @@ namespace ZVALUE {
const int EDGE = 50;
const int VERTEX = 60;
const int DIMENSION = 110;
const int LABEL = 120;
const int SECTIONLINE = 80; //TODO: change to "DECORATION"? section lines, symmetry lines, etc?
const int HIGHLIGHT = 80;
const int MATTING = 100;

View File

@@ -0,0 +1,84 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# test script for TechDraw module
# creates a page and 2 views
# adds 1 length dimension to view1
# adds 1 radius dimension to view2
from __future__ import print_function
import FreeCAD
import Part
import Measure
import TechDraw
import os
def DVBalloonTest():
path = os.path.dirname(os.path.abspath(__file__))
print ('TDBalloon path: ' + path)
templateFileSpec = path + '/TestTemplate.svg'
FreeCAD.newDocument("TDBalloon")
FreeCAD.setActiveDocument("TDBalloon")
FreeCAD.ActiveDocument=FreeCAD.getDocument("TDBalloon")
#make source feature
box = FreeCAD.ActiveDocument.addObject("Part::Box","Box")
sphere = FreeCAD.ActiveDocument.addObject("Part::Sphere","Sphere")
#make a page
page = FreeCAD.ActiveDocument.addObject('TechDraw::DrawPage','Page')
FreeCAD.ActiveDocument.addObject('TechDraw::DrawSVGTemplate','Template')
FreeCAD.ActiveDocument.Template.Template = templateFileSpec
FreeCAD.ActiveDocument.Page.Template = FreeCAD.ActiveDocument.Template
page.Scale = 5.0
# page.ViewObject.show() # unit tests run in console mode
#make Views
view1 = FreeCAD.ActiveDocument.addObject('TechDraw::DrawViewPart','View')
FreeCAD.ActiveDocument.View.Source = [FreeCAD.ActiveDocument.Box]
rc = page.addView(view1)
view1.X = 30
view1.Y = 150
view2 = FreeCAD.activeDocument().addObject('TechDraw::DrawViewPart','View001')
FreeCAD.activeDocument().View001.Source = [FreeCAD.activeDocument().Sphere]
rc = page.addView(view2)
view2.X = 220
view2.Y = 150
FreeCAD.ActiveDocument.recompute()
print("Place balloon")
balloon1 = FreeCAD.ActiveDocument.addObject('TechDraw::DrawViewBalloon','Balloon1')
balloon1.sourceView=view1
balloon1.OriginIsSet=1
balloon1.OriginX=view1.X + 20
balloon1.OriginY=view1.Y + 20
balloon1.Text="1"
balloon1.Y=balloon1.OriginX + 20
balloon1.X=balloon1.OriginY + 20
print("adding balloon1 to page")
rc = page.addView(balloon1)
balloon2 = FreeCAD.ActiveDocument.addObject('TechDraw::DrawViewBalloon','Balloon2')
balloon2.sourceView=view2
balloon2.OriginIsSet=1
balloon2.OriginX=view2.X + 20
balloon2.OriginY=view2.Y + 20
balloon2.Text="2"
balloon2.Y=balloon2.OriginX + 20
balloon2.X=balloon2.OriginY + 20
print("adding balloon2 to page")
rc = page.addView(balloon2)
FreeCAD.ActiveDocument.recompute()
rc = False
if ("Up-to-date" in balloon2.State) and ("Up-to-date" in balloon2.State):
rc = True
FreeCAD.closeDocument("TDBalloon")
return rc
if __name__ == '__main__':
DVBalloonTest()

View File

@@ -31,6 +31,7 @@ from TDTest.DVAnnoSymImageTest import DVAnnoSymImageTest
from TDTest.DVDimensionTest import DVDimensionTest
from TDTest.DVPartTest import DVPartTest
from TDTest.DVSectionTest import DVSectionTest
from TDTest.DVBalloonTest import DVBalloonTest
#---------------------------------------------------------------------------
# define the test cases to test the FreeCAD TechDraw module
@@ -86,3 +87,10 @@ class TechDrawTestCases(unittest.TestCase):
else:
print("TD DrawViewSection test failed")
def testBalloonCase(self):
print("starting TD DrawViewBalloon test")
rc = DVBalloonTest()
if rc:
print("TD DrawViewBalloon test passed")
else:
print("TD DrawViewBalloon test failed")