Merge pull request #5082 from pavltom/Balloon_Updates

TechDraw - Balloon handling updates
This commit is contained in:
Chris Hennes
2021-10-09 13:28:48 -05:00
committed by GitHub
13 changed files with 245 additions and 56 deletions

View File

@@ -100,7 +100,6 @@ DrawPage::DrawPage(void)
"Auto-numbering for Balloons");
Scale.setConstraints(&scaleRange);
balloonPlacing = false;
balloonParent = nullptr;
}

View File

@@ -94,7 +94,6 @@ public:
bool isUnsetting(void) { return nowUnsetting; }
void requestPaint(void);
std::vector<App::DocumentObject*> getAllViews(void) ;
bool balloonPlacing;
DrawViewPart *balloonParent; //could be many balloons on page?
int getNextBalloonIndex(void);

View File

@@ -87,6 +87,7 @@ const char* DrawViewBalloon::balloonTypeEnums[]= {"Circular",
"Hexagon",
"Square",
"Rectangle",
"Line",
NULL};
DrawViewBalloon::DrawViewBalloon(void)

View File

@@ -87,14 +87,19 @@
#include <Mod/TechDraw/Gui/QGVPage.h>
#include "DrawGuiUtil.h"
#include "PreferencesGui.h"
#include "MDIViewPage.h"
#include "PreferencesGui.h"
#include "QGIViewPart.h"
#include "Rez.h"
#include "TaskProjGroup.h"
#include "TaskSectionView.h"
#include "TaskActiveView.h"
#include "TaskDetail.h"
#include "ViewProviderPage.h"
#include "ViewProviderViewPart.h"
class Vertex;
using namespace TechDrawGui;
using namespace TechDraw;
using namespace std;
@@ -801,6 +806,42 @@ bool _checkDrawViewPartBalloon(Gui::Command* cmd) {
return true;
}
bool _checkDirectPlacement(const QGIViewPart *viewPart, const std::vector<std::string> &subNames, QPointF &placement)
{
// Let's see, if we can help speed up the placement of the balloon:
// As of now we support:
// Single selected vertex: place the ballon tip end here
// Single selected edge: place the ballon tip at its midpoint (suggested placement for e.g. chamfer dimensions)
//
// Single selected faces are currently not supported, but maybe we could in this case use the center of mass?
if (subNames.size() != 1) {
// If nothing or more than one subjects are selected, let the user decide, where to place the balloon
return false;
}
std::string geoType = TechDraw::DrawUtil::getGeomTypeFromName(subNames[0]);
if (geoType == "Vertex") {
int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]);
TechDraw::Vertex *vertex = static_cast<DrawViewPart *>(viewPart->getViewObject())->getProjVertexByIndex(index);
if (vertex) {
placement = viewPart->mapToScene(Rez::guiX(vertex->x()), Rez::guiX(vertex->y()));
return true;
}
}
else if (geoType == "Edge") {
int index = TechDraw::DrawUtil::getIndexFromName(subNames[0]);
TechDraw::BaseGeom *geo = static_cast<DrawViewPart *>(viewPart->getViewObject())->getGeomByIndex(index);
if (geo) {
Base::Vector3d midPoint(Rez::guiX(geo->getMidPoint()));
placement = viewPart->mapToScene(midPoint.x, midPoint.y);
return true;
}
}
return false;
}
DEF_STD_CMD_A(CmdTechDrawBalloon)
CmdTechDrawBalloon::CmdTechDrawBalloon()
@@ -826,6 +867,7 @@ void CmdTechDrawBalloon::activated(int iMsg)
return;
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
auto objFeat( dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject()) );
if( objFeat == nullptr ) {
return;
@@ -833,10 +875,25 @@ void CmdTechDrawBalloon::activated(int iMsg)
TechDraw::DrawPage* page = objFeat->findParentPage();
std::string PageName = page->getNameInDocument();
page->balloonParent = objFeat;
page->balloonPlacing = true;
page->balloonParent = objFeat;
Gui::Document *guiDoc = Gui::Application::Instance->getDocument(page->getDocument());
ViewProviderPage *pageVP = dynamic_cast<ViewProviderPage *>(guiDoc->getViewProvider(page));
ViewProviderViewPart *partVP = dynamic_cast<ViewProviderViewPart *>(guiDoc->getViewProvider(objFeat));
if (pageVP && partVP) {
QGVPage *viewPage = pageVP->getGraphicsView();
if (viewPage) {
viewPage->startBalloonPlacing();
QGIViewPart *viewPart = dynamic_cast<QGIViewPart *>(partVP->getQView());
QPointF placement;
if (viewPart && _checkDirectPlacement(viewPart, selection[0].getSubNames(), placement)) {
viewPage->createBalloon(placement, objFeat);
}
}
}
}
bool CmdTechDrawBalloon::isActive(void)

View File

@@ -424,6 +424,15 @@
<normaloff>:/icons/rectangle.svg</normaloff>:/icons/rectangle.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Line</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/bottomline.svg</normaloff>:/icons/bottomline.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="8" column="0">

View File

@@ -118,8 +118,6 @@ QGIView::QGIView()
m_lockWidth = (double) sizeLock.width();
m_lockHeight = (double) sizeLock.height();
m_lock->hide();
setCursor(Qt::ArrowCursor);
}
QGIView::~QGIView()

View File

@@ -676,6 +676,7 @@ void QGIViewBalloon::drawBalloon(bool dragged)
float scale = balloon->ShapeScale.getValue();
double offsetLR = 0;
double offsetUD = 0;
QPainterPath balloonPath;
if (strcmp(balloonType, "Circular") == 0) {
@@ -747,16 +748,26 @@ void QGIViewBalloon::drawBalloon(bool dragged)
balloonPath.moveTo(lblCenter.x + (radius * cos(startAngle)), lblCenter.y + (radius * sin(startAngle)));
balloonPath.addPolygon(triangle);
}
else if (strcmp(balloonType, "Line") == 0) {
textHeight = textHeight*scale + Rez::guiX(0.5);
textWidth = textWidth*scale + Rez::guiX(1.0);
offsetLR = textWidth/2.0;
offsetUD = textHeight/2.0;
balloonPath.moveTo(lblCenter.x - textWidth/2.0, lblCenter.y + offsetUD);
balloonPath.lineTo(lblCenter.x + textWidth/2.0, lblCenter.y + offsetUD);
}
balloonShape->setPath(balloonPath);
offsetLR = (lblCenter.x < arrowTipX) ? offsetLR : -offsetLR ;
if (DrawUtil::fpCompare(kinkLength, 0.0)) { //if no kink, then dLine start sb on line from center to arrow
if (DrawUtil::fpCompare(kinkLength, 0.0) && strcmp(balloonType, "Line")) { //if no kink, then dLine start sb on line from center to arrow
dLineStart = lblCenter;
kinkPoint = dLineStart;
} else {
dLineStart.y = lblCenter.y;
dLineStart.y = lblCenter.y + offsetUD;
dLineStart.x = lblCenter.x + offsetLR ;
kinkLength = (lblCenter.x < arrowTipX) ? kinkLength : -kinkLength;
kinkPoint.y = dLineStart.y;

View File

@@ -57,6 +57,12 @@
#include <Gui/Selection.h>
#include <Gui/WaitCursor.h>
#include <Gui/Command.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
#include <Gui/MainWindow.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Mod/TechDraw/App/Geometry.h>
#include <Mod/TechDraw/App/DrawPage.h>
@@ -126,6 +132,7 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGraphicsScene* s, QWidget *parent)
m_renderer(Native),
drawBkg(true),
m_vpPage(0),
balloonPlacing(false),
panningActive(false)
{
assert(vp);
@@ -166,13 +173,13 @@ QGVPage::QGVPage(ViewProviderPage *vp, QGraphicsScene* s, QWidget *parent)
setAlignment(Qt::AlignCenter);
setDragMode(ScrollHandDrag);
setCursor(QCursor(Qt::ArrowCursor));
resetCursor();
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
bkgBrush = new QBrush(getBackgroundColor());
balloonCursor = new QLabel(this);
balloonCursor->setPixmap(QPixmap(QString::fromUtf8(":/icons/TechDraw_Balloon.svg")));
balloonCursor->setPixmap(prepareCursorPixmap("TechDraw_Balloon.svg", balloonHotspot = QPoint(8, 59)));
balloonCursor->hide();
resetCachedContent();
@@ -184,11 +191,17 @@ QGVPage::~QGVPage()
}
void QGVPage::startBalloonPlacing(void)
{
balloonPlacing = true;
activateCursor(QCursor(*balloonCursor->pixmap(), balloonHotspot.x(), balloonHotspot.y()));
}
void QGVPage::cancelBalloonPlacing(void)
{
getDrawPage()->balloonPlacing = false;
balloonCursor->hide();
QApplication::restoreOverrideCursor();
balloonPlacing = false;
balloonCursor->hide();
resetCursor();
}
void QGVPage::drawBackground(QPainter *p, const QRectF &)
@@ -448,12 +461,13 @@ QGIView * QGVPage::addViewBalloon(TechDraw::DrawViewBalloon *balloon)
QGIView *parent = 0;
parent = findParent(vBalloon);
if(parent)
if (parent) {
addBalloonToParent(vBalloon,parent);
}
if (getDrawPage()->balloonPlacing) {
vBalloon->placeBalloon(balloon->origin);
cancelBalloonPlacing();
if (balloonPlacing) {
vBalloon->placeBalloon(balloon->origin);
cancelBalloonPlacing();
}
return vBalloon;
@@ -470,6 +484,29 @@ void QGVPage::addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent)
balloon->setZValue(ZVALUE::DIMENSION);
}
void QGVPage::createBalloon(QPointF origin, DrawViewPart *parent)
{
std::string featName = getDrawPage()->getDocument()->getUniqueObjectName("Balloon");
std::string pageName = getDrawPage()->getNameInDocument();
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon"));
Command::doCommand(Command::Doc, "App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')", featName.c_str());
Command::doCommand(Command::Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)", pageName.c_str(), featName.c_str());
TechDraw::DrawViewBalloon *balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(getDrawPage()->getDocument()->getObject(featName.c_str()));
if (!balloon) {
throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
}
balloon->SourceView.setValue(parent);
balloon->origin = origin;
Gui::Command::commitCommand();
parent->touch(true);
Gui::Command::updateActive();
}
QGIView * QGVPage::addViewDimension(TechDraw::DrawViewDimension *dim)
{
auto dimGroup( new QGIViewDimension );
@@ -1119,21 +1156,14 @@ void QGVPage::kbPanScroll(int xMove, int yMove)
void QGVPage::enterEvent(QEvent *event)
{
QGraphicsView::enterEvent(event);
if(getDrawPage()->balloonPlacing) {
if (balloonPlacing) {
balloonCursor->hide();
QApplication::setOverrideCursor(QCursor(QPixmap(QString::fromUtf8(":/icons/TechDraw_Balloon.svg")),0,32));
} else {
QApplication::restoreOverrideCursor();
viewport()->setCursor(Qt::ArrowCursor);
}
}
void QGVPage::leaveEvent(QEvent * event)
{
QApplication::restoreOverrideCursor();
if(getDrawPage()->balloonPlacing) {
if (balloonPlacing) {
int left_x;
if (balloonCursorPos.x() < 32)
left_x = 0;
@@ -1192,33 +1222,9 @@ void QGVPage::mouseMoveEvent(QMouseEvent *event)
void QGVPage::mouseReleaseEvent(QMouseEvent *event)
{
if(getDrawPage()->balloonPlacing) {
QApplication::restoreOverrideCursor();
if (balloonPlacing) {
balloonCursor->hide();
std::string FeatName = getDrawPage()->getDocument()->getUniqueObjectName("Balloon");
std::string PageName = getDrawPage()->getNameInDocument();
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon"));
TechDraw::DrawViewBalloon *balloon = 0;
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Balloon"));
Command::doCommand(Command::Doc,"App.activeDocument().addObject('TechDraw::DrawViewBalloon','%s')",FeatName.c_str());
Command::doCommand(Command::Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str());
balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(getDrawPage()->getDocument()->getObject(FeatName.c_str()));
if (!balloon) {
throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
}
balloon->SourceView.setValue(getDrawPage()->balloonParent);
balloon->origin = mapToScene(event->pos());
Gui::Command::commitCommand();
balloon->recomputeFeature();
//Horrible hack to force Tree update
double x = getDrawPage()->balloonParent->X.getValue();
getDrawPage()->balloonParent->X.setValue(x);
createBalloon(mapToScene(event->pos()), getDrawPage()->balloonParent);
}
if (event->button()&Qt::MiddleButton) {
@@ -1227,7 +1233,7 @@ void QGVPage::mouseReleaseEvent(QMouseEvent *event)
}
QGraphicsView::mouseReleaseEvent(event);
viewport()->setCursor(Qt::ArrowCursor);
resetCursor();
}
TechDraw::DrawPage* QGVPage::getDrawPage()
@@ -1244,4 +1250,54 @@ QColor QGVPage::getBackgroundColor()
return fcColor.asValue<QColor>();
}
double QGVPage::getDevicePixelRatio() const {
for (Gui::MDIView *view : m_vpPage->getDocument()->getMDIViews()) {
if (view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
return static_cast<Gui::View3DInventor *>(view)->getViewer()->devicePixelRatio();
}
}
return 1.0;
}
QPixmap QGVPage::prepareCursorPixmap(const char *iconName, QPoint &hotspot) {
QPointF floatHotspot(hotspot);
double pixelRatio = getDevicePixelRatio();
// Due to impossibility to query cursor size via Qt API, we stick to (32x32)*device_pixel_ratio
// as FreeCAD Wiki suggests - see https://wiki.freecadweb.org/HiDPI_support#Custom_cursor_size
double cursorSize = 32.0*pixelRatio;
QPixmap pixmap = Gui::BitmapFactory().pixmapFromSvg(iconName, QSizeF(cursorSize, cursorSize));
pixmap.setDevicePixelRatio(pixelRatio);
// The default (and here expected) SVG cursor graphics size is 64x64 pixels, thus we must adjust
// the 64x64 based hotspot position for our 32x32 based cursor pixmaps accordingly
floatHotspot *= 0.5;
#if !defined(Q_OS_WIN32) && !defined(Q_OS_MAC)
// On XCB platform, the pixmap device pixel ratio is not taken into account for cursor hot spot,
// therefore we must take care of the transformation ourselves...
// Refer to QTBUG-68571 - https://bugreports.qt.io/browse/QTBUG-68571
if (qGuiApp->platformName() == QLatin1String("xcb")) {
floatHotspot *= pixelRatio;
}
#endif
hotspot = floatHotspot.toPoint();
return pixmap;
}
void QGVPage::activateCursor(QCursor cursor) {
this->setCursor(cursor);
viewport()->setCursor(cursor);
}
void QGVPage::resetCursor() {
this->setCursor(Qt::ArrowCursor);
viewport()->setCursor(Qt::ArrowCursor);
}
#include <Mod/TechDraw/Gui/moc_QGVPage.cpp>

View File

@@ -93,6 +93,10 @@ public:
QGIView* findParent(QGIView *) const;
void addBalloonToParent(QGIViewBalloon* balloon, QGIView* parent);
void createBalloon(QPointF origin, TechDraw::DrawViewPart *parent);
void startBalloonPlacing(void);
void cancelBalloonPlacing(void);
void addDimToParent(QGIViewDimension* dim, QGIView* parent);
void addLeaderToParent(QGILeaderLine* lead, QGIView* parent);
@@ -118,6 +122,7 @@ public:
void saveSvg(QString filename);
void postProcessXml(QTemporaryFile& tempFile, QString filename, QString pagename);
public Q_SLOTS:
void setHighQualityAntialiasing(bool highQualityAntialiasing);
@@ -140,6 +145,12 @@ protected:
QGITemplate *pageTemplate;
double getDevicePixelRatio() const;
QPixmap prepareCursorPixmap(const char *iconName, QPoint &hotspot);
void activateCursor(QCursor cursor);
void resetCursor();
private:
RendererType m_renderer;
@@ -153,9 +164,11 @@ private:
double m_zoomIncrement;
int m_reversePan;
int m_reverseScroll;
bool balloonPlacing;
QLabel *balloonCursor;
QPoint balloonCursorPos;
void cancelBalloonPlacing(void);
QPoint balloonHotspot;
QPoint panOrigin;
bool panningActive;

View File

@@ -109,6 +109,7 @@
<file>icons/rectangle.svg</file>
<file>icons/triangle.svg</file>
<file>icons/square.svg</file>
<file>icons/bottomline.svg</file>
<!-- MRTE -->
<file>icons/MRTE/menu.svg</file>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="48"
height="48"
id="svg4024">
<defs
id="defs4026" />
<metadata
id="metadata4029">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
style="stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
transform="translate(-0.97881415)"
id="g863">
<path
style="fill:none;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.3728823,36 H 44.584748"
id="path819-8-8-7" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -164,6 +164,15 @@
<normaloff>:/icons/rectangle.svg</normaloff>:/icons/rectangle.svg</iconset>
</property>
</item>
<item>
<property name="text">
<string>Line</string>
</property>
<property name="icon">
<iconset resource="Resources/TechDraw.qrc">
<normaloff>:/icons/bottomline.svg</normaloff>:/icons/bottomline.svg</iconset>
</property>
</item>
</widget>
</item>
<item row="4" column="0">

View File

@@ -91,6 +91,7 @@ public:
void setFrameState(bool state);
void toggleFrameState(void);
void setTemplateMarkers(bool state);
QGVPage *getGraphicsView() { return m_graphicsView; }
void setGraphicsView(QGVPage* gv);
virtual bool canDelete(App::DocumentObject* obj) const override;